wifi: rtw89: acpi: introduce country specific TAS enabling

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
This commit is contained in:
Kuan-Chung Chen 2025-04-22 09:46:10 +08:00 committed by Ping-Ke Shih
parent 74f754da76
commit df6da0b81e
5 changed files with 84 additions and 5 deletions

View 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);

View 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;
};

View 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;

View 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)

View 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)