diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/fw.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 161 |
1 files changed, 85 insertions, 76 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 900f1e25b9da..e6c9528eeeda 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -698,6 +698,82 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, return 0; } +static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) +{ + struct iwl_notification_wait init_wait; + struct iwl_nvm_access_complete_cmd nvm_complete = {}; + struct iwl_init_extended_cfg_cmd init_cfg = { + .init_flags = cpu_to_le32(BIT(IWL_INIT_NVM)), + }; + static const u16 init_complete[] = { + INIT_COMPLETE_NOTIF, + }; + int ret; + + lockdep_assert_held(&mvm->mutex); + + iwl_init_notification_wait(&mvm->notif_wait, + &init_wait, + init_complete, + ARRAY_SIZE(init_complete), + iwl_wait_init_complete, + NULL); + + /* Will also start the device */ + ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR); + if (ret) { + IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); + goto error; + } + + /* Send init config command to mark that we are sending NVM access + * commands + */ + ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(SYSTEM_GROUP, + INIT_EXTENDED_CFG_CMD), 0, + sizeof(init_cfg), &init_cfg); + if (ret) { + IWL_ERR(mvm, "Failed to run init config command: %d\n", + ret); + goto error; + } + + /* Read the NVM only at driver load time, no need to do this twice */ + if (read_nvm) { + /* Read nvm */ + ret = iwl_nvm_init(mvm, true); + if (ret) { + IWL_ERR(mvm, "Failed to read NVM: %d\n", ret); + goto error; + } + } + + /* In case we read the NVM from external file, load it to the NIC */ + if (mvm->nvm_file_name) + iwl_mvm_load_nvm_to_nic(mvm); + + ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); + if (WARN_ON(ret)) + goto error; + + ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP, + NVM_ACCESS_COMPLETE), 0, + sizeof(nvm_complete), &nvm_complete); + if (ret) { + IWL_ERR(mvm, "Failed to run complete NVM access: %d\n", + ret); + goto error; + } + + /* We wait for the INIT complete notification */ + return iwl_wait_notification(&mvm->notif_wait, &init_wait, + MVM_UCODE_ALIVE_TIMEOUT); + +error: + iwl_remove_notification(&mvm->notif_wait, &init_wait); + return ret; +} + static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) { struct iwl_phy_cfg_cmd phy_cfg_cmd; @@ -726,6 +802,9 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) }; int ret; + if (iwl_mvm_has_new_tx_api(mvm)) + return iwl_run_unified_mvm_ucode(mvm, true); + lockdep_assert_held(&mvm->mutex); if (WARN_ON_ONCE(mvm->calibrating)) @@ -832,82 +911,6 @@ out: return ret; } -int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) -{ - struct iwl_notification_wait init_wait; - struct iwl_nvm_access_complete_cmd nvm_complete = {}; - struct iwl_init_extended_cfg_cmd init_cfg = { - .init_flags = cpu_to_le32(BIT(IWL_INIT_NVM)), - }; - static const u16 init_complete[] = { - INIT_COMPLETE_NOTIF, - }; - int ret; - - lockdep_assert_held(&mvm->mutex); - - iwl_init_notification_wait(&mvm->notif_wait, - &init_wait, - init_complete, - ARRAY_SIZE(init_complete), - iwl_wait_init_complete, - NULL); - - /* Will also start the device */ - ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR); - if (ret) { - IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); - goto error; - } - - /* Send init config command to mark that we are sending NVM access - * commands - */ - ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(SYSTEM_GROUP, - INIT_EXTENDED_CFG_CMD), 0, - sizeof(init_cfg), &init_cfg); - if (ret) { - IWL_ERR(mvm, "Failed to run init config command: %d\n", - ret); - goto error; - } - - /* Read the NVM only at driver load time, no need to do this twice */ - if (read_nvm) { - /* Read nvm */ - ret = iwl_nvm_init(mvm, true); - if (ret) { - IWL_ERR(mvm, "Failed to read NVM: %d\n", ret); - goto error; - } - } - - /* In case we read the NVM from external file, load it to the NIC */ - if (mvm->nvm_file_name) - iwl_mvm_load_nvm_to_nic(mvm); - - ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); - if (WARN_ON(ret)) - goto error; - - ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP, - NVM_ACCESS_COMPLETE), 0, - sizeof(nvm_complete), &nvm_complete); - if (ret) { - IWL_ERR(mvm, "Failed to run complete NVM access: %d\n", - ret); - goto error; - } - - /* We wait for the INIT complete notification */ - return iwl_wait_notification(&mvm->notif_wait, &init_wait, - MVM_UCODE_ALIVE_TIMEOUT); - -error: - iwl_remove_notification(&mvm->notif_wait, &init_wait); - return ret; -} - static void iwl_mvm_parse_shared_mem_a000(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) { @@ -1198,6 +1201,12 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm) enabled = !!(wifi_pkg->package.elements[1].integer.value); n_profiles = wifi_pkg->package.elements[2].integer.value; + /* in case of BIOS bug */ + if (n_profiles <= 0) { + ret = -EINVAL; + goto out_free; + } + for (i = 0; i < n_profiles; i++) { /* the tables start at element 3 */ static int pos = 3; |