Message ID | 20250321090307.1397-1-quic_kangyang@quicinc.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Jeff Johnson |
Headers | show |
Series | [ath-next,v3] wifi: ath12k: read country code from SMBIOS for WCN7850 | expand |
Kang Yang <quic_kangyang@quicinc.com> wrote: > > 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. > > [...] > > 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, 0xff); > + ab->new_alpha2[1] = u16_get_bits(smbios->cc_code, 0xff); It seems that one of the masks is wrong. > + 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; > @@ -690,7 +712,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 116cf530621f..e2d300bd5972 100644 > --- a/drivers/net/wireless/ath/ath12k/core.h > +++ b/drivers/net/wireless/ath/ath12k/core.h > @@ -172,9 +172,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; > > [...] >
On 3/21/2025 7:06 PM, Zong-Zhe Yang wrote: > Kang Yang <quic_kangyang@quicinc.com> wrote: >> >> 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. >> >> [...] >> >> 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, 0xff); >> + ab->new_alpha2[1] = u16_get_bits(smbios->cc_code, 0xff); > > It seems that one of the masks is wrong. > Oh, yes. >> + 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; >> @@ -690,7 +712,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 116cf530621f..e2d300bd5972 100644 >> --- a/drivers/net/wireless/ath/ath12k/core.h >> +++ b/drivers/net/wireless/ath/ath12k/core.h >> @@ -172,9 +172,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/core.c b/drivers/net/wireless/ath/ath12k/core.c index 11c73fe45308..29a5b8f1fc0d 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -629,7 +629,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; @@ -651,6 +651,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, 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; @@ -690,7 +712,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 116cf530621f..e2d300bd5972 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -172,9 +172,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 ba9dd19b2e1d..4be937abe3ce 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -11619,6 +11619,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); }