Read the country code from SMBIOS and send it to the firmware. The firmware will then indicate the regulatory domain information for the country code, which ath12k will use. dmesg: [ 1242.637253] ath12k_pci 0000:02:00.0: worldwide regdomain setting from SMBIOS [ 1242.637259] ath12k_pci 0000:02:00.0: bdf variant name not found. [ 1242.637261] ath12k_pci 0000:02:00.0: SMBIOS bdf variant name not set. [ 1242.927543] ath12k_pci 0000:02:00.0: set current country pdev id 0 alpha2 00 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-02582-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1 Signed-off-by: Wen Gong <quic_wgong@xxxxxxxxxxx> Signed-off-by: Kang Yang <quic_kangyang@xxxxxxxxxxx> --- Depends-On: [PATCH ath-next v14 0/4] wifi: ath12k: add 11d scan offload support and handle country code for WCN7850 https://lore.kernel.org/linux-wireless/20250327020527.1527-1-quic_kangyang@xxxxxxxxxxx/ Note: This patch is an old patch in public review written by Wen Gong. Just resend it for him. Link: https://lore.kernel.org/linux-wireless/20230913105156.17618-1-quic_wgong@xxxxxxxxxxx/ v4: 1. fix assignment error for case ATH12K_SMBIOS_CC_ISO. 2. rebase on tag: ath/main(ath-202503251458). v3: 1. rebase on tag: ath-202503172347. 2. add branch tag. 3. add descripition for Wen Gong. v2: 1. rebase on tag: ath/main(ath-202502181756). 2. rewrite commit message. --- drivers/net/wireless/ath/ath12k/core.c | 26 +++++++++++++++++++++++-- drivers/net/wireless/ath/ath12k/core.h | 27 +++++++++++++++++++++++++- drivers/net/wireless/ath/ath12k/mac.c | 11 +++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 06e3ee16eb0e..b29b675c70b9 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -657,7 +657,7 @@ static void ath12k_core_stop(struct ath12k_base *ab) /* De-Init of components as needed */ } -static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data) +static void ath12k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void *data) { struct ath12k_base *ab = data; const char *magic = ATH12K_SMBIOS_BDF_EXT_MAGIC; @@ -679,6 +679,28 @@ static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data) return; } + spin_lock_bh(&ab->base_lock); + + switch (smbios->country_code_flag) { + case ATH12K_SMBIOS_CC_ISO: + ab->new_alpha2[0] = u16_get_bits(smbios->cc_code >> 8, 0xff); + ab->new_alpha2[1] = u16_get_bits(smbios->cc_code, 0xff); + ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot smbios cc_code %c%c\n", + ab->new_alpha2[0], ab->new_alpha2[1]); + break; + case ATH12K_SMBIOS_CC_WW: + ab->new_alpha2[0] = '0'; + ab->new_alpha2[1] = '0'; + ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot smbios worldwide regdomain\n"); + break; + default: + ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot ignore smbios country code setting %d\n", + smbios->country_code_flag); + break; + } + + spin_unlock_bh(&ab->base_lock); + if (!smbios->bdf_enabled) { ath12k_dbg(ab, ATH12K_DBG_BOOT, "bdf variant name not found.\n"); return; @@ -718,7 +740,7 @@ static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data) int ath12k_core_check_smbios(struct ath12k_base *ab) { ab->qmi.target.bdf_ext[0] = '\0'; - dmi_walk(ath12k_core_check_bdfext, ab); + dmi_walk(ath12k_core_check_cc_code_bdfext, ab); if (ab->qmi.target.bdf_ext[0] == '\0') return -ENODATA; diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 5f98b98b38cf..8a6f79490b41 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -175,9 +175,34 @@ struct ath12k_ext_irq_grp { struct net_device *napi_ndev; }; +enum ath12k_smbios_cc_type { + /* disable country code setting from SMBIOS */ + ATH12K_SMBIOS_CC_DISABLE = 0, + + /* set country code by ANSI country name, based on ISO3166-1 alpha2 */ + ATH12K_SMBIOS_CC_ISO = 1, + + /* worldwide regdomain */ + ATH12K_SMBIOS_CC_WW = 2, +}; + struct ath12k_smbios_bdf { struct dmi_header hdr; - u32 padding; + u8 features_disabled; + + /* enum ath12k_smbios_cc_type */ + u8 country_code_flag; + + /* To set specific country, you need to set country code + * flag=ATH12K_SMBIOS_CC_ISO first, then if country is United + * States, then country code value = 0x5553 ("US",'U' = 0x55, 'S'= + * 0x53). To set country to INDONESIA, then country code value = + * 0x4944 ("IN", 'I'=0x49, 'D'=0x44). If country code flag = + * ATH12K_SMBIOS_CC_WW, then you can use worldwide regulatory + * setting. + */ + u16 cc_code; + u8 bdf_enabled; u8 bdf_ext[]; } __packed; diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index d522972b24bf..6395035b5378 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -11628,6 +11628,17 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) goto err_unregister_hw; } + if (ar->ab->hw_params->current_cc_support && ab->new_alpha2[0]) { + struct wmi_set_current_country_arg current_cc = {}; + + memcpy(¤t_cc.alpha2, ab->new_alpha2, 2); + memcpy(&ar->alpha2, ab->new_alpha2, 2); + ret = ath12k_wmi_send_set_current_country_cmd(ar, ¤t_cc); + if (ret) + ath12k_warn(ar->ab, + "failed set cc code for mac register: %d\n", ret); + } + ath12k_fw_stats_init(ar); ath12k_debugfs_register(ar); } base-commit: 1aa05c6f5681b371b981bf1902f1b96528feec7c -- 2.34.1