wifi: ath12k: read country code from SMBIOS for WCN7850
authorWen Gong <quic_wgong@quicinc.com>
Thu, 17 Apr 2025 02:42:27 +0000 (10:42 +0800)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Fri, 16 May 2025 17:34:15 +0000 (10:34 -0700)
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@quicinc.com>
Signed-off-by: Kang Yang <kang.yang@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <quic_bqiang@quicinc.com>
Link: https://patch.msgid.link/20250417024227.1712-1-kang.yang@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/core.c
drivers/net/wireless/ath/ath12k/core.h
drivers/net/wireless/ath/ath12k/mac.c

index 7eccd9cf9036df8d9c3d8dc367990f995081bbcc..dea25ce9000974fc04af3695acf6d7a1b4487477 100644 (file)
@@ -697,7 +697,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;
@@ -719,6 +719,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;
@@ -758,7 +780,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;
index 4b8f434e3e9a8ff61e3c734c28277c28216fec25..1b7701b8afd1c696a9e2d53fb5232e38473e123c 100644 (file)
@@ -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;
index 4dae941c9615cf19e6cc2ed1bd72a6bf1cb812ca..59aa69ca1ae2937832004316a73c1b59945c9a24 100644 (file)
@@ -11651,6 +11651,18 @@ 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(&current_cc.alpha2, ab->new_alpha2, 2);
+                       memcpy(&ar->alpha2, ab->new_alpha2, 2);
+                       ret = ath12k_wmi_send_set_current_country_cmd(ar, &current_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);
        }