From: Emmanuel Grumbach There is a new version of this command to indicate which AP type in UNII-9 is supported per country. This adds support for a new UEFI table that will include that data to be filled in the new AP type table. Rename the uats_table field in firmware_runtime structure since it includes now the UATS and the new UNEB table coming from UEFI. For the same reason, rename iwl_mld_init_uats. Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/fw/api/nvm-reg.h | 14 ++++++-- .../net/wireless/intel/iwlwifi/fw/runtime.h | 8 ++--- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 36 +++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 11 ++++++ drivers/net/wireless/intel/iwlwifi/mld/fw.c | 2 +- .../wireless/intel/iwlwifi/mld/regulatory.c | 32 ++++++++++++++--- .../wireless/intel/iwlwifi/mld/regulatory.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 24 +++++++------ 8 files changed, 102 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index bd6bf931866f..25c860a05b0e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -701,13 +701,23 @@ struct iwl_pnvm_init_complete_ntfy { #define UATS_TABLE_COL_SIZE 13 /** - * struct iwl_mcc_allowed_ap_type_cmd - struct for MCC_ALLOWED_AP_TYPE_CMD + * struct iwl_mcc_allowed_ap_type_cmd_v1 - struct for MCC_ALLOWED_AP_TYPE_CMD * @mcc_to_ap_type_map: mapping an MCC to 6 GHz AP type support (UATS) * @reserved: reserved */ -struct iwl_mcc_allowed_ap_type_cmd { +struct iwl_mcc_allowed_ap_type_cmd_v1 { u8 mcc_to_ap_type_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE]; __le16 reserved; } __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_1 */ +/** + * struct iwl_mcc_allowed_ap_type_cmd - struct for MCC_ALLOWED_AP_TYPE_CMD + * @mcc_to_ap_type_map: mapping an MCC to 6 GHz AP type support (UATS) + * @mcc_to_ap_type_unii9_map: mapping an MCC to UNII-9 AP type support allowed + */ +struct iwl_mcc_allowed_ap_type_cmd { + u8 mcc_to_ap_type_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE]; + u8 mcc_to_ap_type_unii9_map[UATS_TABLE_ROW_SIZE][UATS_TABLE_COL_SIZE]; +} __packed; /* MCC_ALLOWED_AP_TYPE_CMD_API_S_VER_2 */ + #endif /* __iwl_fw_api_nvm_reg_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index ff186fb2e0da..411e75b45530 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -106,8 +106,8 @@ struct iwl_txf_iter_data { * @cur_fw_img: current firmware image, must be maintained by * the driver by calling &iwl_fw_set_current_image() * @dump: debug dump data - * @uats_table: AP type table - * @uats_valid: is AP type table valid + * @ap_type_cmd: AP type tables (for enablement on 6 GHz) + * @ap_type_cmd_valid: if &ap_type_cmd is valid * @uefi_tables_lock_status: The status of the WIFI GUID UEFI variables lock: * 0: Unlocked, 1 and 2: Locked. * Only read the UEFI variables if locked. @@ -213,8 +213,8 @@ struct iwl_fw_runtime { u8 ppag_bios_source; struct iwl_sar_offset_mapping_cmd sgom_table; bool sgom_enabled; - struct iwl_mcc_allowed_ap_type_cmd uats_table; - bool uats_valid; + struct iwl_mcc_allowed_ap_type_cmd ap_type_cmd; + bool ap_type_cmd_valid; u8 uefi_tables_lock_status; struct iwl_phy_specific_cfg phy_filters; enum bios_source dsm_source; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index a7ba86e06c09..d4e1ab1f7c84 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -402,11 +402,11 @@ static int iwl_uefi_uats_parse(struct uefi_cnv_wlan_uats_data *uats_data, if (uats_data->revision != 1) return -EINVAL; - memcpy(fwrt->uats_table.mcc_to_ap_type_map, + memcpy(fwrt->ap_type_cmd.mcc_to_ap_type_map, uats_data->mcc_to_ap_type_map, - sizeof(fwrt->uats_table.mcc_to_ap_type_map)); + sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_map)); - fwrt->uats_valid = true; + fwrt->ap_type_cmd_valid = true; return 0; } @@ -429,6 +429,36 @@ void iwl_uefi_get_uats_table(struct iwl_trans *trans, } IWL_EXPORT_SYMBOL(iwl_uefi_get_uats_table); +void iwl_uefi_get_uneb_table(struct iwl_trans *trans, + struct iwl_fw_runtime *fwrt) +{ + struct uefi_cnv_wlan_uneb_data *data; + + data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UNEB_NAME, + "UNEB", sizeof(*data), NULL); + if (IS_ERR(data)) + return; + + if (data->revision != 1) { + IWL_DEBUG_RADIO(fwrt, + "Cannot read UNEB table. rev is invalid\n"); + goto out; + } + + BUILD_BUG_ON(sizeof(data->mcc_to_ap_type_map) != + sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_unii9_map)); + + memcpy(fwrt->ap_type_cmd.mcc_to_ap_type_unii9_map, + data->mcc_to_ap_type_map, + sizeof(fwrt->ap_type_cmd.mcc_to_ap_type_unii9_map)); + + fwrt->ap_type_cmd_valid = true; + +out: + kfree(data); +} +IWL_EXPORT_SYMBOL(iwl_uefi_get_uneb_table); + static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt, struct uefi_sar_profile *uefi_sar_prof, u8 prof_index, bool enabled) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index 349ac1505ad7..99170a72c3f1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -25,6 +25,7 @@ #define IWL_UEFI_PUNCTURING_NAME L"UefiCnvWlanPuncturing" #define IWL_UEFI_DSBR_NAME L"UefiCnvCommonDSBR" #define IWL_UEFI_WPFC_NAME L"WPFC" +#define IWL_UEFI_UNEB_NAME L"CnvUefiWlanUNEB" #define IWL_SGOM_MAP_SIZE 339 @@ -63,6 +64,9 @@ struct uefi_cnv_wlan_uats_data { u8 mcc_to_ap_type_map[IWL_UATS_MAP_SIZE - 1]; } __packed; +/* UNEB's layout is identical to UATS's */ +#define uefi_cnv_wlan_uneb_data uefi_cnv_wlan_uats_data + struct uefi_cnv_common_step_data { u8 revision; u8 step_mode; @@ -274,6 +278,8 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func, void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt); void iwl_uefi_get_uats_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt); +void iwl_uefi_get_uneb_table(struct iwl_trans *trans, + struct iwl_fw_runtime *fwrt); int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt); int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value); int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt); @@ -373,6 +379,11 @@ iwl_uefi_get_uats_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt) { } +static inline void +iwl_uefi_get_uneb_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt) +{ +} + static inline int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt) { diff --git a/drivers/net/wireless/intel/iwlwifi/mld/fw.c b/drivers/net/wireless/intel/iwlwifi/mld/fw.c index 19da521a4bab..7b1fb84a641c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/fw.c @@ -513,7 +513,7 @@ static int iwl_mld_config_fw(struct iwl_mld *mld) return ret; iwl_mld_init_tas(mld); - iwl_mld_init_uats(mld); + iwl_mld_init_ap_type_tables(mld); return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c index 6ab5a3410353..d1a55b565898 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c @@ -64,6 +64,7 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld) } iwl_uefi_get_uats_table(mld->trans, &mld->fwrt); + iwl_uefi_get_uneb_table(mld->trans, &mld->fwrt); iwl_bios_get_phy_filters(&mld->fwrt); } @@ -352,21 +353,42 @@ void iwl_mld_configure_lari(struct iwl_mld *mld) ret); } -void iwl_mld_init_uats(struct iwl_mld *mld) +void iwl_mld_init_ap_type_tables(struct iwl_mld *mld) { int ret; struct iwl_host_cmd cmd = { .id = WIDE_ID(REGULATORY_AND_NVM_GROUP, MCC_ALLOWED_AP_TYPE_CMD), - .data[0] = &mld->fwrt.uats_table, - .len[0] = sizeof(mld->fwrt.uats_table), + .data[0] = &mld->fwrt.ap_type_cmd, + .len[0] = sizeof(mld->fwrt.ap_type_cmd), .dataflags[0] = IWL_HCMD_DFL_NOCOPY, }; - if (!mld->fwrt.uats_valid) + if (!mld->fwrt.ap_type_cmd_valid) return; - ret = iwl_mld_send_cmd(mld, &cmd); + if (iwl_fw_lookup_cmd_ver(mld->fw, cmd.id, 1) == 1) { + struct iwl_mcc_allowed_ap_type_cmd_v1 *cmd_v1 = + kzalloc(sizeof(*cmd_v1), GFP_KERNEL); + + if (!cmd_v1) + return; + + BUILD_BUG_ON(sizeof(mld->fwrt.ap_type_cmd.mcc_to_ap_type_map) != + sizeof(cmd_v1->mcc_to_ap_type_map)); + + memcpy(cmd_v1->mcc_to_ap_type_map, + mld->fwrt.ap_type_cmd.mcc_to_ap_type_map, + sizeof(mld->fwrt.ap_type_cmd.mcc_to_ap_type_map)); + + cmd.data[0] = cmd_v1; + cmd.len[0] = sizeof(*cmd_v1); + ret = iwl_mld_send_cmd(mld, &cmd); + kfree(cmd_v1); + } else { + ret = iwl_mld_send_cmd(mld, &cmd); + } + if (ret) IWL_ERR(mld, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n", ret); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h index 3b01c645adda..5498c19789f4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h @@ -9,7 +9,7 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld); void iwl_mld_configure_lari(struct iwl_mld *mld); -void iwl_mld_init_uats(struct iwl_mld *mld); +void iwl_mld_init_ap_type_tables(struct iwl_mld *mld); void iwl_mld_init_tas(struct iwl_mld *mld); int iwl_mld_init_ppag(struct iwl_mld *mld); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 43cf94c9a36b..f5e5c10cc581 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -459,23 +459,18 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm, static void iwl_mvm_uats_init(struct iwl_mvm *mvm) { + int cmd_id = WIDE_ID(REGULATORY_AND_NVM_GROUP, + MCC_ALLOWED_AP_TYPE_CMD); + struct iwl_mcc_allowed_ap_type_cmd_v1 cmd = {}; u8 cmd_ver; int ret; - struct iwl_host_cmd cmd = { - .id = WIDE_ID(REGULATORY_AND_NVM_GROUP, - MCC_ALLOWED_AP_TYPE_CMD), - .flags = 0, - .data[0] = &mvm->fwrt.uats_table, - .len[0] = sizeof(mvm->fwrt.uats_table), - .dataflags[0] = IWL_HCMD_DFL_NOCOPY, - }; if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { IWL_DEBUG_RADIO(mvm, "UATS feature is not supported\n"); return; } - cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd.id, + cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, IWL_FW_CMD_VER_UNKNOWN); if (cmd_ver != 1) { IWL_DEBUG_RADIO(mvm, @@ -486,10 +481,17 @@ static void iwl_mvm_uats_init(struct iwl_mvm *mvm) iwl_uefi_get_uats_table(mvm->trans, &mvm->fwrt); - if (!mvm->fwrt.uats_valid) + if (!mvm->fwrt.ap_type_cmd_valid) return; - ret = iwl_mvm_send_cmd(mvm, &cmd); + BUILD_BUG_ON(sizeof(mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map) != + sizeof(cmd.mcc_to_ap_type_map)); + + memcpy(cmd.mcc_to_ap_type_map, + mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map, + sizeof(mvm->fwrt.ap_type_cmd.mcc_to_ap_type_map)); + + ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); if (ret < 0) IWL_ERR(mvm, "failed to send MCC_ALLOWED_AP_TYPE_CMD (%d)\n", ret); -- 2.34.1