2023-09-13 14:13:11

by Wen Gong

[permalink] [raw]
Subject: [PATCH] wifi: ath12k: read country code from SMBIOS for WCN7850

This read the country code from SMBIOS and send the country code
to firmware, firmware will indicate the regulatory domain info of the
country code and then ath12k will use the info.

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-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4

Signed-off-by: Wen Gong <[email protected]>
---
depends on 5 patches in public review:
Wen Gong:

https://lore.kernel.org/linux-wireless/[email protected]/
wifi: ath12k: add read variant from SMBIOS for download board data

https://lore.kernel.org/linux-wireless/[email protected]/
wifi: ath12k: add read variant from SMBIOS for download board data
[PATCH 0/4] wifi: ath12k: add 11d scan offload support and handle country code for WCN7850
wifi: ath12k: add configure country code for WCN7850
wifi: ath12k: add 11d scan offload support
wifi: ath12k: avoid firmware crash when reg set for WCN7850
wifi: ath12k: store and send country code to firmware after recovery

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 4c4abeba39c8..de9b7604eaa2 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -377,7 +377,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;
@@ -399,6 +399,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, 0xff00);
+ 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;
@@ -438,7 +460,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 35a3b6357eb5..d35b97520e6d 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -142,9 +142,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 0df154c34f8f..ba292c2873d1 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -7509,6 +7509,17 @@ static int __ath12k_mac_register(struct ath12k *ar)
goto err_unregister_hw;
}

+ if (ar->ab->hw_params->current_cc_support && ab->new_alpha2[0]) {
+ struct wmi_set_current_country_params set_current_param = {};
+
+ memcpy(&set_current_param.alpha2, ab->new_alpha2, 2);
+ memcpy(&ar->alpha2, ab->new_alpha2, 2);
+ ret = ath12k_wmi_send_set_current_country_cmd(ar, &set_current_param);
+ if (ret)
+ ath12k_warn(ar->ab,
+ "failed set cc code for mac register: %d\n", ret);
+ }
+
return 0;

err_unregister_hw:

base-commit: 3f257461ab0ab19806bae2bfde4c3cd88dbf050e
prerequisite-patch-id: 2ee4ca0fc2ff95861b978c44b2cb04771c927ee1
prerequisite-patch-id: a341b369c2d9f319970dff05a117cc4c6c85c31c
prerequisite-patch-id: 04c82a480f25fa06001c9ff3fb1d30630f9ec82a
prerequisite-patch-id: 9ba56bba555d7c1b7dea4ad394d39d8397e79754
prerequisite-patch-id: 7c1c0cda8e48fee003376e035ac2b472d22cbae9
--
2.40.1


2023-09-14 03:30:55

by Jeff Johnson

[permalink] [raw]
Subject: Re: [PATCH] wifi: ath12k: read country code from SMBIOS for WCN7850

On 9/13/2023 3:51 AM, Wen Gong wrote:
> This read the country code from SMBIOS and send the country code
> to firmware, firmware will indicate the regulatory domain info of the
> country code and then ath12k will use the info.
>
> 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-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
>
> Signed-off-by: Wen Gong <[email protected]>

Acked-by: Jeff Johnson <[email protected]>

> ---
> depends on 5 patches in public review:
> Wen Gong:
>
> https://lore.kernel.org/linux-wireless/[email protected]/
> wifi: ath12k: add read variant from SMBIOS for download board data
>
> https://lore.kernel.org/linux-wireless/[email protected]/
> wifi: ath12k: add read variant from SMBIOS for download board data
> [PATCH 0/4] wifi: ath12k: add 11d scan offload support and handle country code for WCN7850
> wifi: ath12k: add configure country code for WCN7850
> wifi: ath12k: add 11d scan offload support
> wifi: ath12k: avoid firmware crash when reg set for WCN7850
> wifi: ath12k: store and send country code to firmware after recovery
>
> 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 4c4abeba39c8..de9b7604eaa2 100644
> --- a/drivers/net/wireless/ath/ath12k/core.c
> +++ b/drivers/net/wireless/ath/ath12k/core.c
> @@ -377,7 +377,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;
> @@ -399,6 +399,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, 0xff00);
> + 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;
> @@ -438,7 +460,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 35a3b6357eb5..d35b97520e6d 100644
> --- a/drivers/net/wireless/ath/ath12k/core.h
> +++ b/drivers/net/wireless/ath/ath12k/core.h
> @@ -142,9 +142,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 0df154c34f8f..ba292c2873d1 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -7509,6 +7509,17 @@ static int __ath12k_mac_register(struct ath12k *ar)
> goto err_unregister_hw;
> }
>
> + if (ar->ab->hw_params->current_cc_support && ab->new_alpha2[0]) {
> + struct wmi_set_current_country_params set_current_param = {};
> +
> + memcpy(&set_current_param.alpha2, ab->new_alpha2, 2);
> + memcpy(&ar->alpha2, ab->new_alpha2, 2);
> + ret = ath12k_wmi_send_set_current_country_cmd(ar, &set_current_param);
> + if (ret)
> + ath12k_warn(ar->ab,
> + "failed set cc code for mac register: %d\n", ret);
> + }
> +
> return 0;
>
> err_unregister_hw:
>
> base-commit: 3f257461ab0ab19806bae2bfde4c3cd88dbf050e
> prerequisite-patch-id: 2ee4ca0fc2ff95861b978c44b2cb04771c927ee1
> prerequisite-patch-id: a341b369c2d9f319970dff05a117cc4c6c85c31c
> prerequisite-patch-id: 04c82a480f25fa06001c9ff3fb1d30630f9ec82a
> prerequisite-patch-id: 9ba56bba555d7c1b7dea4ad394d39d8397e79754
> prerequisite-patch-id: 7c1c0cda8e48fee003376e035ac2b472d22cbae9