summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/iwl-drv.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c66
1 files changed, 58 insertions, 8 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 77124b8b235e..5cec467b995b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -31,7 +31,6 @@
#define DRV_DESCRIPTION "Intel(R) Wireless WiFi driver for Linux"
MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_AUTHOR(DRV_AUTHOR);
MODULE_LICENSE("GPL");
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -550,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,
@@ -1133,6 +1169,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
case IWL_UCODE_TLV_TYPE_HCMD:
case IWL_UCODE_TLV_TYPE_REGIONS:
case IWL_UCODE_TLV_TYPE_TRIGGERS:
+ case IWL_UCODE_TLV_TYPE_CONF_SET:
if (iwlwifi_mod_params.enable_ini)
iwl_dbg_tlv_alloc(drv->trans, tlv, false);
break;
@@ -1166,6 +1203,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;
@@ -1271,23 +1313,31 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
const struct iwl_op_mode_ops *ops = op->ops;
struct dentry *dbgfs_dir = NULL;
struct iwl_op_mode *op_mode = NULL;
+ int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY;
+
+ for (retry = 0; retry <= max_retry; retry++) {
#ifdef CONFIG_IWLWIFI_DEBUGFS
- drv->dbgfs_op_mode = debugfs_create_dir(op->name,
- drv->dbgfs_drv);
- dbgfs_dir = drv->dbgfs_op_mode;
+ drv->dbgfs_op_mode = debugfs_create_dir(op->name,
+ drv->dbgfs_drv);
+ dbgfs_dir = drv->dbgfs_op_mode;
#endif
- op_mode = ops->start(drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir);
+ op_mode = ops->start(drv->trans, drv->trans->cfg,
+ &drv->fw, dbgfs_dir);
+
+ if (op_mode)
+ return op_mode;
+
+ IWL_ERR(drv, "retry init count %d\n", retry);
#ifdef CONFIG_IWLWIFI_DEBUGFS
- if (!op_mode) {
debugfs_remove_recursive(drv->dbgfs_op_mode);
drv->dbgfs_op_mode = NULL;
- }
#endif
+ }
- return op_mode;
+ return NULL;
}
static void _iwl_op_mode_stop(struct iwl_drv *drv)