]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: rtw89: acpi: introduce country specific TAS enabling
authorKuan-Chung Chen <damon.chen@realtek.com>
Tue, 22 Apr 2025 01:46:10 +0000 (09:46 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Mon, 28 Apr 2025 06:32:02 +0000 (14:32 +0800)
A new ACPI table entry format for TAS is defined, which includes
a "specific country" field. In this field, determine which
country can enable TAS.

Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250422014620.18421-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/acpi.c
drivers/net/wireless/realtek/rtw89/acpi.h
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/regd.c
drivers/net/wireless/realtek/rtw89/sar.c

index c97cc29cc66391dde0ef3ab2f8b655614de97aa8..581d6d4154d338d8ff3fcfdbe67f602e41901b30 100644 (file)
@@ -236,6 +236,49 @@ int rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev *rtwdev,
        return 0;
 }
 
+static bool chk_acpi_policy_tas_sig(const struct rtw89_acpi_policy_tas *p)
+{
+       return p->signature[0] == 0x52 &&
+              p->signature[1] == 0x54 &&
+              p->signature[2] == 0x4B &&
+              p->signature[3] == 0x05;
+}
+
+static int rtw89_acpi_dsm_get_policy_tas(struct rtw89_dev *rtwdev,
+                                        union acpi_object *obj,
+                                        struct rtw89_acpi_policy_tas **policy)
+{
+       const struct rtw89_acpi_policy_tas *ptr;
+       u32 buf_len;
+
+       if (obj->type != ACPI_TYPE_BUFFER) {
+               rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+                           "acpi: expect buffer but type: %d\n", obj->type);
+               return -EINVAL;
+       }
+
+       buf_len = obj->buffer.length;
+       if (buf_len < sizeof(*ptr)) {
+               rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
+                           __func__, buf_len);
+               return -EINVAL;
+       }
+
+       ptr = (typeof(ptr))obj->buffer.pointer;
+       if (!chk_acpi_policy_tas_sig(ptr)) {
+               rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
+               return -EINVAL;
+       }
+
+       *policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
+       if (!*policy)
+               return -ENOMEM;
+
+       rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_tas: ", *policy,
+                      sizeof(*ptr));
+       return 0;
+}
+
 int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
                            enum rtw89_acpi_dsm_func func,
                            struct rtw89_acpi_dsm_result *res)
@@ -257,6 +300,8 @@ int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
        else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP)
                ret = rtw89_acpi_dsm_get_policy_6ghz_sp(rtwdev, obj,
                                                        &res->u.policy_6ghz_sp);
+       else if (func == RTW89_ACPI_DSM_FUNC_TAS_EN)
+               ret = rtw89_acpi_dsm_get_policy_tas(rtwdev, obj, &res->u.policy_tas);
        else
                ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value);
 
index 8ec9011bfefbbf399b7e61424a4bb0330a1334fe..8c918ee02d2edbad8a8a04a137596f181d5bac5b 100644 (file)
@@ -31,6 +31,13 @@ enum rtw89_acpi_policy_mode {
        RTW89_ACPI_POLICY_ALLOW = 1,
 };
 
+enum rtw89_acpi_conf_tas {
+       RTW89_ACPI_CONF_TAS_US = BIT(0),
+       RTW89_ACPI_CONF_TAS_CA = BIT(1),
+       RTW89_ACPI_CONF_TAS_KR = BIT(2),
+       RTW89_ACPI_CONF_TAS_OTHERS = BIT(7),
+};
+
 struct rtw89_acpi_country_code {
        /* below are allowed:
         * * ISO alpha2 country code
@@ -59,12 +66,21 @@ struct rtw89_acpi_policy_6ghz_sp {
        u8 rsvd;
 } __packed;
 
+struct rtw89_acpi_policy_tas {
+       u8 signature[4];
+       u8 revision;
+       u8 enable;
+       u8 enabled_countries;
+       u8 rsvd[3];
+} __packed;
+
 struct rtw89_acpi_dsm_result {
        union {
                u8 value;
                /* caller needs to free it after using */
                struct rtw89_acpi_policy_6ghz *policy_6ghz;
                struct rtw89_acpi_policy_6ghz_sp *policy_6ghz_sp;
+               struct rtw89_acpi_policy_tas *policy_tas;
        } u;
 };
 
index 34626e255140e4980f9925a7728ab3a99e240995..b1fff57a748858925c5b93013cffac08c2efd124 100644 (file)
@@ -4753,6 +4753,7 @@ enum rtw89_tas_state {
 struct rtw89_tas_info {
        u16 tx_ratio_history[RTW89_TAS_TX_RATIO_WINDOW];
        u64 txpwr_history[RTW89_TAS_TXPWR_WINDOW];
+       u8 enabled_countries;
        u8 txpwr_head_idx;
        u8 txpwr_tail_idx;
        u8 tx_ratio_idx;
index 6dd37de59682801193a0145c0c41df1ceb0af3e6..3ad14cab1f587045d846c8a38e167ed885539257 100644 (file)
@@ -759,11 +759,22 @@ static void rtw89_regd_apply_policy_tas(struct rtw89_dev *rtwdev)
        struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
        const struct rtw89_regd *regd = regulatory->regd;
        struct rtw89_tas_info *tas = &rtwdev->tas;
+       u8 tas_country;
 
        if (!tas->enable)
                return;
 
-       tas->block_regd = !test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap);
+       if (memcmp("US", regd->alpha2, 2) == 0)
+               tas_country = RTW89_ACPI_CONF_TAS_US;
+       else if (memcmp("CA", regd->alpha2, 2) == 0)
+               tas_country = RTW89_ACPI_CONF_TAS_CA;
+       else if (memcmp("KR", regd->alpha2, 2) == 0)
+               tas_country = RTW89_ACPI_CONF_TAS_KR;
+       else
+               tas_country = RTW89_ACPI_CONF_TAS_OTHERS;
+
+       tas->block_regd = !(tas->enabled_countries & tas_country &&
+                           test_bit(RTW89_REGD_FUNC_TAS, regd->func_bitmap));
 }
 
 static void rtw89_regd_apply_policy_ant_gain(struct rtw89_dev *rtwdev)
index d15dafcae39b0a28b1c8def4a9c935ced8b9dba2..517b66022f18b6b1f7f7077a573ecfa0e5955910 100644 (file)
@@ -695,9 +695,9 @@ static void rtw89_tas_init(struct rtw89_dev *rtwdev)
 {
        const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_tas_info *tas = &rtwdev->tas;
+       const struct rtw89_acpi_policy_tas *ptr;
        struct rtw89_acpi_dsm_result res = {};
        int ret;
-       u8 val;
 
        if (!chip->support_tas)
                return;
@@ -709,8 +709,9 @@ static void rtw89_tas_init(struct rtw89_dev *rtwdev)
                return;
        }
 
-       val = res.u.value;
-       switch (val) {
+       ptr = res.u.policy_tas;
+
+       switch (ptr->enable) {
        case 0:
                tas->enable = false;
                break;
@@ -723,8 +724,13 @@ static void rtw89_tas_init(struct rtw89_dev *rtwdev)
 
        if (!tas->enable) {
                rtw89_debug(rtwdev, RTW89_DBG_SAR, "TAS not enable\n");
-               return;
+               goto out;
        }
+
+       tas->enabled_countries = ptr->enabled_countries;
+
+out:
+       kfree(ptr);
 }
 
 void rtw89_tas_reset(struct rtw89_dev *rtwdev, bool force)