mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 03:24:19 +02:00
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:
parent
74f754da76
commit
df6da0b81e
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user