From: Zong-Zhe Yang <kevin_yang@xxxxxxxxxxx> Realtek ACPI DSM func 7, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, accepts a format via ACPI buffer as below. | index | description | -------------------------------------------- | [0-3] | signature | | [4] | revision | | [5] | override driver settings, or not | | [6] | configuration if override | | [7] | reserved | where field of [6] is a bitmap by country, and for now, only define BIT(0) is for US. Through this function with overriding, BIOS can indicate to allow/block 6 GHz SP power by country. Signed-off-by: Zong-Zhe Yang <kevin_yang@xxxxxxxxxxx> Signed-off-by: Ping-Ke Shih <pkshih@xxxxxxxxxxx> --- drivers/net/wireless/realtek/rtw89/acpi.c | 47 +++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/acpi.h | 14 +++++++ 2 files changed, 61 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/acpi.c b/drivers/net/wireless/realtek/rtw89/acpi.c index 2e7326a8e3e4..908e980a4b72 100644 --- a/drivers/net/wireless/realtek/rtw89/acpi.c +++ b/drivers/net/wireless/realtek/rtw89/acpi.c @@ -77,6 +77,50 @@ int rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev *rtwdev, return 0; } +static bool chk_acpi_policy_6ghz_sp_sig(const struct rtw89_acpi_policy_6ghz_sp *p) +{ + return p->signature[0] == 0x52 && + p->signature[1] == 0x54 && + p->signature[2] == 0x4B && + p->signature[3] == 0x07; +} + +static +int rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev *rtwdev, + union acpi_object *obj, + struct rtw89_acpi_policy_6ghz_sp **policy) +{ + const struct rtw89_acpi_policy_6ghz_sp *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_6ghz_sp_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_6ghz_sp: ", *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) @@ -95,6 +139,9 @@ int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev, if (func == RTW89_ACPI_DSM_FUNC_6G_BP) ret = rtw89_acpi_dsm_get_policy_6ghz(rtwdev, obj, &res->u.policy_6ghz); + 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 ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value); diff --git a/drivers/net/wireless/realtek/rtw89/acpi.h b/drivers/net/wireless/realtek/rtw89/acpi.h index 5182797e68b6..d274be1775bf 100644 --- a/drivers/net/wireless/realtek/rtw89/acpi.h +++ b/drivers/net/wireless/realtek/rtw89/acpi.h @@ -13,6 +13,7 @@ enum rtw89_acpi_dsm_func { RTW89_ACPI_DSM_FUNC_6G_BP = 4, RTW89_ACPI_DSM_FUNC_TAS_EN = 5, RTW89_ACPI_DSM_FUNC_UNII4_SUP = 6, + RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP = 7, }; enum rtw89_acpi_conf_unii4 { @@ -41,11 +42,24 @@ struct rtw89_acpi_policy_6ghz { struct rtw89_acpi_country_code country_list[] __counted_by(country_count); } __packed; +enum rtw89_acpi_conf_6ghz_sp { + RTW89_ACPI_CONF_6GHZ_SP_US = BIT(0), +}; + +struct rtw89_acpi_policy_6ghz_sp { + u8 signature[4]; + u8 revision; + u8 override; + u8 conf; + u8 rsvd; +} __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; } u; }; -- 2.25.1