wifi: rtw89: regd: handle policy of 6 GHz SP according to BIOS
authorZong-Zhe Yang <kevin_yang@realtek.com>
Fri, 12 Apr 2024 11:57:29 +0000 (19:57 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Thu, 18 Apr 2024 01:11:19 +0000 (09:11 +0800)
According to BIOS configuration of Realtek ACPI DSM function 7,
RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, we handle the regd policy of 6 GHz SP.

If BIOS indicates to override driver settings, we only allow the countries,
which are enabled by BIOS, to use 6 GHz SP power. Other countries will be
applied to select default power when recalculating 6 GHz regulatory power
selection.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://msgid.link/20240412115729.8316-9-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/regd.c

index 7cd6b31797133a5cf48337e744d5be2369aab65e..1fb960af0a85f5373514f6ae8d6fe4b806834750 100644 (file)
@@ -4760,6 +4760,7 @@ struct rtw89_regulatory_info {
        enum rtw89_reg_6ghz_power reg_6ghz_power;
        DECLARE_BITMAP(block_unii4, RTW89_REGD_MAX_COUNTRY_NUM);
        DECLARE_BITMAP(block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM);
+       DECLARE_BITMAP(block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM);
 };
 
 enum rtw89_ifs_clm_application {
index 47384615e18c1465fa6e139b090edc140182f78a..1a133914f673ce91ba0d6e016bf92f7cacaa9fc6 100644 (file)
@@ -468,6 +468,51 @@ out:
        kfree(ptr);
 }
 
+static void rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
+       const struct rtw89_acpi_policy_6ghz_sp *ptr;
+       struct rtw89_acpi_dsm_result res = {};
+       bool enable_by_us;
+       int ret;
+       int i;
+
+       ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, &res);
+       if (ret) {
+               rtw89_debug(rtwdev, RTW89_DBG_REGD,
+                           "acpi: cannot eval policy 6ghz-sp: %d\n", ret);
+               return;
+       }
+
+       ptr = res.u.policy_6ghz_sp;
+
+       switch (ptr->override) {
+       default:
+               rtw89_debug(rtwdev, RTW89_DBG_REGD,
+                           "%s: unknown override case: %d\n", __func__,
+                           ptr->override);
+               fallthrough;
+       case 0:
+               goto out;
+       case 1:
+               break;
+       }
+
+       bitmap_fill(regulatory->block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM);
+
+       enable_by_us = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_US);
+
+       for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) {
+               const struct rtw89_regd *tmp = &rtw89_regd_map[i];
+
+               if (enable_by_us && memcmp(tmp->alpha2, "US", 2) == 0)
+                       clear_bit(i, regulatory->block_6ghz_sp);
+       }
+
+out:
+       kfree(ptr);
+}
+
 static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
 {
        const struct rtw89_chip_info *chip = rtwdev->chip;
@@ -510,6 +555,7 @@ bottom:
 
        if (regd_allow_6ghz) {
                rtw89_regd_setup_policy_6ghz(rtwdev);
+               rtw89_regd_setup_policy_6ghz_sp(rtwdev);
                return;
        }
 
@@ -671,10 +717,12 @@ exit:
 static void __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
 {
        struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
+       const struct rtw89_regd *regd = regulatory->regd;
        enum rtw89_reg_6ghz_power sel;
        const struct rtw89_chan *chan;
        struct rtw89_vif *rtwvif;
        int count = 0;
+       u8 index;
 
        rtw89_for_each_rtwvif(rtwdev, rtwvif) {
                chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
@@ -691,6 +739,17 @@ static void __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
        if (count != 1)
                sel = RTW89_REG_6GHZ_POWER_DFLT;
 
+       if (sel == RTW89_REG_6GHZ_POWER_STD) {
+               index = rtw89_regd_get_index(regd);
+               if (index == RTW89_REGD_MAX_COUNTRY_NUM ||
+                   test_bit(index, regulatory->block_6ghz_sp)) {
+                       rtw89_debug(rtwdev, RTW89_DBG_REGD,
+                                   "%c%c 6 GHz SP is blocked by policy\n",
+                                   regd->alpha2[0], regd->alpha2[1]);
+                       sel = RTW89_REG_6GHZ_POWER_DFLT;
+               }
+       }
+
        if (regulatory->reg_6ghz_power == sel)
                return;