diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/fw.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 93 |
1 files changed, 60 insertions, 33 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 5ea684802ad1..df49dd2e2026 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -642,7 +642,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm) /* if we needed reset then fail here, but notify and remove */ if (mvm->fw_product_reset) { iwl_mei_alive_notif(false); - iwl_trans_pcie_remove(mvm->trans, true); + iwl_trans_pcie_reset(mvm->trans, + IWL_RESET_MODE_RESCAN); } goto error; @@ -1093,36 +1094,40 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm) return iwl_mvm_ppag_send_cmd(mvm); } -static bool iwl_mvm_add_to_tas_block_list(__le32 *list, __le32 *le_size, unsigned int mcc) +static bool +iwl_mvm_add_to_tas_block_list(u16 *list, u8 *size, u16 mcc) { - int i; - u32 size = le32_to_cpu(*le_size); - /* Verify that there is room for another country */ - if (size >= IWL_WTAS_BLACK_LIST_MAX) + if (*size >= IWL_WTAS_BLACK_LIST_MAX) return false; - for (i = 0; i < size; i++) { - if (list[i] == cpu_to_le32(mcc)) + for (u8 i = 0; i < *size; i++) { + if (list[i] == mcc) return true; } - list[size++] = cpu_to_le32(mcc); - *le_size = cpu_to_le32(size); + list[*size++] = mcc; return true; } static void iwl_mvm_tas_init(struct iwl_mvm *mvm) { u32 cmd_id = WIDE_ID(REGULATORY_AND_NVM_GROUP, TAS_CONFIG); - int ret; + int fw_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, + IWL_FW_CMD_VER_UNKNOWN); + struct iwl_tas_selection_data selection_data = {}; + struct iwl_tas_config_cmd_v2_v4 cmd_v2_v4 = {}; + struct iwl_tas_config_cmd cmd_v5 = {}; struct iwl_tas_data data = {}; - struct iwl_tas_config_cmd cmd = {}; - int cmd_size, fw_ver; + void *cmd_data = &cmd_v2_v4; + int cmd_size; + int ret; BUILD_BUG_ON(ARRAY_SIZE(data.block_list_array) != IWL_WTAS_BLACK_LIST_MAX); - BUILD_BUG_ON(ARRAY_SIZE(cmd.common.block_list_array) != + BUILD_BUG_ON(ARRAY_SIZE(cmd_v2_v4.common.block_list_array) != + IWL_WTAS_BLACK_LIST_MAX); + BUILD_BUG_ON(ARRAY_SIZE(cmd_v5.block_list_array) != IWL_WTAS_BLACK_LIST_MAX); if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TAS_CFG)) { @@ -1138,7 +1143,7 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm) return; } - if (ret == 0) + if (ret == 0 && fw_ver < 5) return; if (!iwl_is_tas_approved()) { @@ -1161,27 +1166,49 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm) dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>"); } - fw_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, - IWL_FW_CMD_VER_UNKNOWN); - - memcpy(&cmd.common, &data, sizeof(struct iwl_tas_config_cmd_common)); - - /* Set v3 or v4 specific parts. will be trunctated for fw_ver < 3 */ - if (fw_ver == 4) { - cmd.v4.override_tas_iec = data.override_tas_iec; - cmd.v4.enable_tas_iec = data.enable_tas_iec; - cmd.v4.usa_tas_uhb_allowed = data.usa_tas_uhb_allowed; + if (fw_ver < 5) { + selection_data = iwl_parse_tas_selection(data.tas_selection, + data.table_revision); + cmd_v2_v4.common.block_list_size = + cpu_to_le32(data.block_list_size); + for (u8 i = 0; i < data.block_list_size; i++) + cmd_v2_v4.common.block_list_array[i] = + cpu_to_le32(data.block_list_array[i]); + } + + if (fw_ver == 5) { + cmd_size = sizeof(cmd_v5); + cmd_data = &cmd_v5; + cmd_v5.block_list_size = cpu_to_le16(data.block_list_size); + for (u16 i = 0; i < data.block_list_size; i++) + cmd_v5.block_list_array[i] = + cpu_to_le16(data.block_list_array[i]); + cmd_v5.tas_config_info.table_source = data.table_source; + cmd_v5.tas_config_info.table_revision = data.table_revision; + cmd_v5.tas_config_info.value = cpu_to_le32(data.tas_selection); + } else if (fw_ver == 4) { + cmd_size = sizeof(cmd_v2_v4.common) + sizeof(cmd_v2_v4.v4); + cmd_v2_v4.v4.override_tas_iec = selection_data.override_tas_iec; + cmd_v2_v4.v4.enable_tas_iec = selection_data.enable_tas_iec; + cmd_v2_v4.v4.usa_tas_uhb_allowed = + selection_data.usa_tas_uhb_allowed; + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT) && + selection_data.canada_tas_uhb_allowed) + cmd_v2_v4.v4.uhb_allowed_flags = TAS_UHB_ALLOWED_CANADA; + } else if (fw_ver == 3) { + cmd_size = sizeof(cmd_v2_v4.common) + sizeof(cmd_v2_v4.v3); + cmd_v2_v4.v3.override_tas_iec = + cpu_to_le16(selection_data.override_tas_iec); + cmd_v2_v4.v3.enable_tas_iec = + cpu_to_le16(selection_data.enable_tas_iec); + } else if (fw_ver == 2) { + cmd_size = sizeof(cmd_v2_v4.common); } else { - cmd.v3.override_tas_iec = cpu_to_le16(data.override_tas_iec); - cmd.v3.enable_tas_iec = cpu_to_le16(data.enable_tas_iec); + return; } - cmd_size = sizeof(struct iwl_tas_config_cmd_common); - if (fw_ver >= 3) - /* v4 is the same size as v3 */ - cmd_size += sizeof(struct iwl_tas_config_cmd_v3); - - ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, cmd_size, &cmd); + ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, cmd_size, cmd_data); if (ret < 0) IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret); } |