@@ -100,6 +100,9 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_PNVM_SKU = 64,
IWL_UCODE_TLV_TCM_DEBUG_ADDRS = 65,
+ IWL_UCODE_TLV_SEC_TABLE_ADDR = 66,
+ IWL_UCODE_TLV_D3_KEK_KCK_ADDR = 67,
+
IWL_UCODE_TLV_FW_NUM_STATIONS = IWL_UCODE_TLV_CONST_BASE + 0,
IWL_UCODE_TLV_TYPE_DEBUG_INFO = IWL_UCODE_TLV_DEBUG_BASE + 0,
@@ -956,6 +959,10 @@ struct iwl_fw_tcm_error_addr {
__le32 addr;
}; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */
+struct iwl_fw_dump_exclude {
+ __le32 addr, size;
+};
+
static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
size_t fixed_size, size_t var_size)
{
@@ -176,6 +176,10 @@ struct iwl_fw_dbg {
u32 dump_mask;
};
+struct iwl_dump_exclude {
+ u32 addr, size;
+};
+
/**
* struct iwl_fw - variables associated with the firmware
*
@@ -198,6 +202,8 @@ struct iwl_fw_dbg {
* we get the ALIVE from the uCode
* @phy_integration_ver: PHY integration version string
* @phy_integration_ver_len: length of @phy_integration_ver
+ * @dump_excl: image dump exclusion areas for RT image
+ * @dump_excl_wowlan: image dump exclusion areas for WoWLAN image
*/
struct iwl_fw {
u32 ucode_ver;
@@ -229,6 +235,8 @@ struct iwl_fw {
u8 *phy_integration_ver;
u32 phy_integration_ver_len;
+
+ struct iwl_dump_exclude dump_excl[2], dump_excl_wowlan[2];
};
static inline const char *get_fw_dbg_mode_string(int mode)
@@ -549,6 +549,43 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
return 0;
}
+static void iwl_drv_set_dump_exclude(struct iwl_drv *drv,
+ enum iwl_ucode_tlv_type tlv_type,
+ const void *tlv_data, u32 tlv_len)
+{
+ const struct iwl_fw_dump_exclude *fw = tlv_data;
+ struct iwl_dump_exclude *excl;
+
+ if (tlv_len < sizeof(*fw))
+ return;
+
+ if (tlv_type == IWL_UCODE_TLV_SEC_TABLE_ADDR) {
+ excl = &drv->fw.dump_excl[0];
+
+ /* second time we find this, it's for WoWLAN */
+ if (excl->addr)
+ excl = &drv->fw.dump_excl_wowlan[0];
+ } else if (fw_has_capa(&drv->fw.ucode_capa,
+ IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG)) {
+ /* IWL_UCODE_TLV_D3_KEK_KCK_ADDR is regular image */
+ excl = &drv->fw.dump_excl[0];
+ } else {
+ /* IWL_UCODE_TLV_D3_KEK_KCK_ADDR is WoWLAN image */
+ excl = &drv->fw.dump_excl_wowlan[0];
+ }
+
+ if (excl->addr)
+ excl++;
+
+ if (excl->addr) {
+ IWL_DEBUG_FW_INFO(drv, "found too many excludes in fw file\n");
+ return;
+ }
+
+ excl->addr = le32_to_cpu(fw->addr) & ~FW_ADDR_CACHE_CONTROL;
+ excl->size = le32_to_cpu(fw->size);
+}
+
static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
const struct firmware *ucode_raw,
struct iwl_firmware_pieces *pieces,
@@ -1165,6 +1202,11 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
return -ENOMEM;
drv->fw.phy_integration_ver_len = tlv_len;
break;
+ case IWL_UCODE_TLV_SEC_TABLE_ADDR:
+ case IWL_UCODE_TLV_D3_KEK_KCK_ADDR:
+ iwl_drv_set_dump_exclude(drv, tlv_type,
+ tlv_data, tlv_len);
+ break;
default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;