mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
wifi: rtw89: regd/acpi: support regulatory rules via ACPI DSM and parse rule of regd_UK
ACPI DSM function 10 is defined for the enablement for Realtek regulatory rules. The first rule is whether to allow regd_UK regulatory settings or not. If not, the strict one, i.e. regd_ETSI, regulatory settings will be used on country GB. Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://patch.msgid.link/20250709065006.32028-4-pkshih@realtek.com
This commit is contained in:
parent
01186c303b
commit
08fbc2b688
|
|
@ -279,6 +279,51 @@ static int rtw89_acpi_dsm_get_policy_tas(struct rtw89_dev *rtwdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
bool chk_acpi_policy_reg_rules_sig(const struct rtw89_acpi_policy_reg_rules *p)
|
||||
{
|
||||
return p->signature[0] == 0x52 &&
|
||||
p->signature[1] == 0x54 &&
|
||||
p->signature[2] == 0x4B &&
|
||||
p->signature[3] == 0x0A;
|
||||
}
|
||||
|
||||
static
|
||||
int rtw89_acpi_dsm_get_policy_reg_rules(struct rtw89_dev *rtwdev,
|
||||
union acpi_object *obj,
|
||||
struct rtw89_acpi_policy_reg_rules **policy)
|
||||
{
|
||||
const struct rtw89_acpi_policy_reg_rules *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_reg_rules_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_reg_rules: ", *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)
|
||||
|
|
@ -302,6 +347,9 @@ int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
|
|||
&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 if (func == RTW89_ACPI_DSM_FUNC_REG_RULES_EN)
|
||||
ret = rtw89_acpi_dsm_get_policy_reg_rules(rtwdev, obj,
|
||||
&res->u.policy_reg_rules);
|
||||
else
|
||||
ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ enum rtw89_acpi_dsm_func {
|
|||
RTW89_ACPI_DSM_FUNC_TAS_EN = 5,
|
||||
RTW89_ACPI_DSM_FUNC_UNII4_SUP = 6,
|
||||
RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP = 7,
|
||||
RTW89_ACPI_DSM_FUNC_REG_RULES_EN = 10,
|
||||
};
|
||||
|
||||
enum rtw89_acpi_conf_unii4 {
|
||||
|
|
@ -75,6 +76,17 @@ struct rtw89_acpi_policy_tas {
|
|||
u8 rsvd[3];
|
||||
} __packed;
|
||||
|
||||
enum rtw89_acpi_conf_reg_rules {
|
||||
RTW89_ACPI_CONF_REG_RULE_REGD_UK = BIT(0),
|
||||
};
|
||||
|
||||
struct rtw89_acpi_policy_reg_rules {
|
||||
u8 signature[4];
|
||||
u8 revision;
|
||||
u8 conf;
|
||||
u8 rsvd[3];
|
||||
} __packed;
|
||||
|
||||
struct rtw89_acpi_dsm_result {
|
||||
union {
|
||||
u8 value;
|
||||
|
|
@ -82,6 +94,7 @@ struct rtw89_acpi_dsm_result {
|
|||
struct rtw89_acpi_policy_6ghz *policy_6ghz;
|
||||
struct rtw89_acpi_policy_6ghz_sp *policy_6ghz_sp;
|
||||
struct rtw89_acpi_policy_tas *policy_tas;
|
||||
struct rtw89_acpi_policy_reg_rules *policy_reg_rules;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -608,6 +608,30 @@ const char *rtw89_regd_get_string(enum rtw89_regulation_type regd)
|
|||
return rtw89_regd_string[regd];
|
||||
}
|
||||
|
||||
static void rtw89_regd_setup_reg_rules(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
|
||||
const struct rtw89_acpi_policy_reg_rules *ptr;
|
||||
struct rtw89_acpi_dsm_result res = {};
|
||||
int ret;
|
||||
|
||||
regulatory->txpwr_uk_follow_etsi = true;
|
||||
|
||||
ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_REG_RULES_EN, &res);
|
||||
if (ret) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_REGD,
|
||||
"acpi: cannot eval policy reg-rules: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = res.u.policy_reg_rules;
|
||||
|
||||
regulatory->txpwr_uk_follow_etsi =
|
||||
!u8_get_bits(ptr->conf, RTW89_ACPI_CONF_REG_RULE_REGD_UK);
|
||||
|
||||
kfree(ptr);
|
||||
}
|
||||
|
||||
int rtw89_regd_setup(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
|
||||
|
|
@ -624,7 +648,8 @@ int rtw89_regd_setup(struct rtw89_dev *rtwdev)
|
|||
}
|
||||
|
||||
regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
|
||||
regulatory->txpwr_uk_follow_etsi = true;
|
||||
|
||||
rtw89_regd_setup_reg_rules(rtwdev);
|
||||
|
||||
if (!wiphy)
|
||||
return -EINVAL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user