git: 354a030185c6 - main - rtw89: update Realtek's rtw89 driver
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 23 Oct 2025 21:28:27 UTC
The branch main has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=354a030185c650d1465ed2035a83636b8f825d72
commit 354a030185c650d1465ed2035a83636b8f825d72
Merge: eb15fdb1b72d b35044b38f74
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-10-17 20:46:45 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-10-23 21:26:04 +0000
rtw89: update Realtek's rtw89 driver
This version is based on
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
e5f0a698b34ed76002dc5cff3804a61c80233a7a ( tag: v6.17 ).
MFC after: 3 days
sys/contrib/dev/rtw89/Kconfig | 28 +-
sys/contrib/dev/rtw89/Makefile | 9 +
sys/contrib/dev/rtw89/acpi.c | 1140 +++++++-
sys/contrib/dev/rtw89/acpi.h | 223 +-
sys/contrib/dev/rtw89/cam.c | 13 +
sys/contrib/dev/rtw89/chan.c | 993 +++++--
sys/contrib/dev/rtw89/chan.h | 92 +-
sys/contrib/dev/rtw89/coex.c | 4128 +++++++++++++++++-----------
sys/contrib/dev/rtw89/coex.h | 25 +-
sys/contrib/dev/rtw89/core.c | 1019 +++++--
sys/contrib/dev/rtw89/core.h | 572 +++-
sys/contrib/dev/rtw89/debug.c | 2232 ++++++++-------
sys/contrib/dev/rtw89/fw.c | 1464 ++++++++--
sys/contrib/dev/rtw89/fw.h | 305 +-
sys/contrib/dev/rtw89/mac.c | 316 ++-
sys/contrib/dev/rtw89/mac.h | 63 +-
sys/contrib/dev/rtw89/mac80211.c | 420 +--
sys/contrib/dev/rtw89/mac_be.c | 12 +-
sys/contrib/dev/rtw89/pci.c | 78 +-
sys/contrib/dev/rtw89/pci.h | 57 +-
sys/contrib/dev/rtw89/pci_be.c | 2 +-
sys/contrib/dev/rtw89/phy.c | 1209 +++++---
sys/contrib/dev/rtw89/phy.h | 40 +-
sys/contrib/dev/rtw89/phy_be.c | 2 +-
sys/contrib/dev/rtw89/ps.c | 207 +-
sys/contrib/dev/rtw89/ps.h | 6 +
sys/contrib/dev/rtw89/reg.h | 95 +-
sys/contrib/dev/rtw89/regd.c | 780 ++++--
sys/contrib/dev/rtw89/rtw8851b.c | 199 +-
sys/contrib/dev/rtw89/rtw8851b_rfk.c | 156 +-
sys/contrib/dev/rtw89/rtw8851b_rfk_table.c | 77 +-
sys/contrib/dev/rtw89/rtw8851b_rfk_table.h | 2 +-
sys/contrib/dev/rtw89/rtw8851b_table.c | 501 ++--
sys/contrib/dev/rtw89/rtw8851be.c | 1 +
sys/contrib/dev/rtw89/rtw8851bu.c | 39 +
sys/contrib/dev/rtw89/rtw8852a.c | 35 +-
sys/contrib/dev/rtw89/rtw8852ae.c | 1 +
sys/contrib/dev/rtw89/rtw8852b.c | 128 +-
sys/contrib/dev/rtw89/rtw8852b_common.c | 46 +-
sys/contrib/dev/rtw89/rtw8852b_rfk.c | 95 +-
sys/contrib/dev/rtw89/rtw8852b_rfk.h | 3 +
sys/contrib/dev/rtw89/rtw8852be.c | 1 +
sys/contrib/dev/rtw89/rtw8852bt.c | 47 +-
sys/contrib/dev/rtw89/rtw8852bt_rfk.c | 87 +-
sys/contrib/dev/rtw89/rtw8852bt_rfk.h | 3 +
sys/contrib/dev/rtw89/rtw8852bte.c | 1 +
sys/contrib/dev/rtw89/rtw8852bu.c | 55 +
sys/contrib/dev/rtw89/rtw8852c.c | 65 +-
sys/contrib/dev/rtw89/rtw8852ce.c | 1 +
sys/contrib/dev/rtw89/rtw8922a.c | 157 +-
sys/contrib/dev/rtw89/rtw8922a_rfk.c | 57 +-
sys/contrib/dev/rtw89/rtw8922ae.c | 1 +
sys/contrib/dev/rtw89/sar.c | 677 ++++-
sys/contrib/dev/rtw89/sar.h | 27 +-
sys/contrib/dev/rtw89/ser.c | 34 +-
sys/contrib/dev/rtw89/txrx.h | 32 +
sys/contrib/dev/rtw89/usb.c | 1042 +++++++
sys/contrib/dev/rtw89/usb.h | 65 +
sys/contrib/dev/rtw89/util.c | 220 +-
sys/contrib/dev/rtw89/util.h | 13 +-
sys/contrib/dev/rtw89/wow.c | 28 +-
sys/contrib/dev/rtw89/wow.h | 14 +-
sys/modules/rtw89/Makefile | 8 +-
63 files changed, 14320 insertions(+), 5128 deletions(-)
diff --cc sys/contrib/dev/rtw89/Makefile
index c751013e811e,000000000000..23e43c444f69
mode 100644,000000..100644
--- a/sys/contrib/dev/rtw89/Makefile
+++ b/sys/contrib/dev/rtw89/Makefile
@@@ -1,83 -1,0 +1,92 @@@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+obj-$(CONFIG_RTW89_CORE) += rtw89_core.o
+rtw89_core-y += core.o \
+ mac80211.o \
+ mac.o \
+ mac_be.o \
+ phy.o \
+ phy_be.o \
+ fw.o \
+ cam.o \
+ efuse.o \
+ efuse_be.o \
+ regd.o \
+ sar.o \
+ coex.o \
+ ps.o \
+ chan.o \
+ ser.o \
+ acpi.o \
+ util.o
+
+rtw89_core-$(CONFIG_PM) += wow.o
+
+obj-$(CONFIG_RTW89_8851B) += rtw89_8851b.o
+rtw89_8851b-objs := rtw8851b.o \
+ rtw8851b_table.o \
+ rtw8851b_rfk.o \
+ rtw8851b_rfk_table.o
+
+obj-$(CONFIG_RTW89_8851BE) += rtw89_8851be.o
+rtw89_8851be-objs := rtw8851be.o
+
++obj-$(CONFIG_RTW89_8851BU) += rtw89_8851bu.o
++rtw89_8851bu-objs := rtw8851bu.o
++
+obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o
+rtw89_8852a-objs := rtw8852a.o \
+ rtw8852a_table.o \
+ rtw8852a_rfk.o \
+ rtw8852a_rfk_table.o
+
+obj-$(CONFIG_RTW89_8852AE) += rtw89_8852ae.o
+rtw89_8852ae-objs := rtw8852ae.o
+
+obj-$(CONFIG_RTW89_8852B_COMMON) += rtw89_8852b_common.o
+rtw89_8852b_common-objs := rtw8852b_common.o
+
+obj-$(CONFIG_RTW89_8852B) += rtw89_8852b.o
+rtw89_8852b-objs := rtw8852b.o \
+ rtw8852b_table.o \
+ rtw8852b_rfk.o \
+ rtw8852b_rfk_table.o
+
+obj-$(CONFIG_RTW89_8852BE) += rtw89_8852be.o
+rtw89_8852be-objs := rtw8852be.o
+
++obj-$(CONFIG_RTW89_8852BU) += rtw89_8852bu.o
++rtw89_8852bu-objs := rtw8852bu.o
++
+obj-$(CONFIG_RTW89_8852BT) += rtw89_8852bt.o
+rtw89_8852bt-objs := rtw8852bt.o \
+ rtw8852bt_rfk.o \
+ rtw8852bt_rfk_table.o
+
+obj-$(CONFIG_RTW89_8852BTE) += rtw89_8852bte.o
+rtw89_8852bte-objs := rtw8852bte.o
+
+obj-$(CONFIG_RTW89_8852C) += rtw89_8852c.o
+rtw89_8852c-objs := rtw8852c.o \
+ rtw8852c_table.o \
+ rtw8852c_rfk.o \
+ rtw8852c_rfk_table.o
+
+obj-$(CONFIG_RTW89_8852CE) += rtw89_8852ce.o
+rtw89_8852ce-objs := rtw8852ce.o
+
+obj-$(CONFIG_RTW89_8922A) += rtw89_8922a.o
+rtw89_8922a-objs := rtw8922a.o \
+ rtw8922a_rfk.o
+
+obj-$(CONFIG_RTW89_8922AE) += rtw89_8922ae.o
+rtw89_8922ae-objs := rtw8922ae.o
+
+rtw89_core-$(CONFIG_RTW89_DEBUG) += debug.o
+
+obj-$(CONFIG_RTW89_PCI) += rtw89_pci.o
+rtw89_pci-y := pci.o pci_be.o
+
++obj-$(CONFIG_RTW89_USB) += rtw89_usb.o
++rtw89_usb-y := usb.o
++
diff --cc sys/contrib/dev/rtw89/acpi.c
index f5dedb12c129,000000000000..fdba1ea46ec6
mode 100644,000000..100644
--- a/sys/contrib/dev/rtw89/acpi.c
+++ b/sys/contrib/dev/rtw89/acpi.c
@@@ -1,197 -1,0 +1,1289 @@@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2021-2023 Realtek Corporation
+ */
+
+#include <linux/acpi.h>
+#include <linux/uuid.h>
+
+#include "acpi.h"
+#include "debug.h"
+
+static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
+ 0x82, 0xBD, 0xFE, 0x86,
+ 0x07, 0x80, 0x3A, 0xA7);
+
++static u32 rtw89_acpi_traversal_object(struct rtw89_dev *rtwdev,
++ const union acpi_object *obj, u8 *pos)
++{
++ const union acpi_object *elm;
++ unsigned int i;
++ u32 sub_len;
++ u32 len = 0;
++ u8 *tmp;
++
++ switch (obj->type) {
++ case ACPI_TYPE_INTEGER:
++ if (pos)
++ pos[len] = obj->integer.value;
++
++ len++;
++ break;
++ case ACPI_TYPE_BUFFER:
++ if (unlikely(obj->buffer.length == 0)) {
++ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
++ "%s: invalid buffer type\n", __func__);
++ goto err;
++ }
++
++ if (pos)
++ memcpy(pos, obj->buffer.pointer, obj->buffer.length);
++
++ len += obj->buffer.length;
++ break;
++ case ACPI_TYPE_PACKAGE:
++ if (unlikely(obj->package.count == 0)) {
++ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
++ "%s: invalid package type\n", __func__);
++ goto err;
++ }
++
++ for (i = 0; i < obj->package.count; i++) {
++ elm = &obj->package.elements[i];
++ tmp = pos ? pos + len : NULL;
++
++ sub_len = rtw89_acpi_traversal_object(rtwdev, elm, tmp);
++ if (unlikely(sub_len == 0))
++ goto err;
++
++ len += sub_len;
++ }
++ break;
++ default:
++ rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: unhandled type: %d\n",
++ __func__, obj->type);
++ goto err;
++ }
++
++ return len;
++
++err:
++ return 0;
++}
++
++static u32 rtw89_acpi_calculate_object_length(struct rtw89_dev *rtwdev,
++ const union acpi_object *obj)
++{
++ return rtw89_acpi_traversal_object(rtwdev, obj, NULL);
++}
++
++static struct rtw89_acpi_data *
++rtw89_acpi_evaluate_method(struct rtw89_dev *rtwdev, const char *method)
++{
++ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
++ struct rtw89_acpi_data *data = NULL;
++ acpi_handle root, handle;
++ union acpi_object *obj;
++ acpi_status status;
++ u32 len;
++
++ root = ACPI_HANDLE(rtwdev->dev);
++ if (!root) {
++ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
++ "acpi (%s): failed to get root\n", method);
++ return NULL;
++ }
++
++#if defined(__linux__)
++ status = acpi_get_handle(root, (acpi_string)method, &handle);
++#elif defined(__FreeBSD__)
++ status = acpi_get_handle(root, method, &handle);
++#endif
++ if (ACPI_FAILURE(status)) {
++ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
++ "acpi (%s): failed to get handle\n", method);
++ return NULL;
++ }
++
++ status = acpi_evaluate_object(handle, NULL, NULL, &buf);
++ if (ACPI_FAILURE(status)) {
++ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
++ "acpi (%s): failed to evaluate object\n", method);
++ return NULL;
++ }
++
++ obj = buf.pointer;
++ len = rtw89_acpi_calculate_object_length(rtwdev, obj);
++ if (unlikely(len == 0)) {
++ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
++ "acpi (%s): failed to traversal obj len\n", method);
++ goto out;
++ }
++
++ data = kzalloc(struct_size(data, buf, len), GFP_KERNEL);
++ if (!data)
++ goto out;
++
++ data->len = len;
++ rtw89_acpi_traversal_object(rtwdev, obj, data->buf);
++
++out:
++ ACPI_FREE(obj);
++ return data;
++}
++
+static
+int rtw89_acpi_dsm_get_value(struct rtw89_dev *rtwdev, union acpi_object *obj,
+ u8 *value)
+{
+ if (obj->type != ACPI_TYPE_INTEGER) {
+ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+ "acpi: expect integer but type: %d\n", obj->type);
+ return -EINVAL;
+ }
+
+ *value = (u8)obj->integer.value;
+ return 0;
+}
+
+static bool chk_acpi_policy_6ghz_sig(const struct rtw89_acpi_policy_6ghz *p)
+{
+ return p->signature[0] == 0x00 &&
+ p->signature[1] == 0xE0 &&
+ p->signature[2] == 0x4C;
+}
+
+static
+int rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev *rtwdev,
+ union acpi_object *obj,
+ struct rtw89_acpi_policy_6ghz **policy_6ghz)
+{
+ const struct rtw89_acpi_policy_6ghz *ptr;
+ u32 expect_len;
+ u32 len;
+
+ if (obj->type != ACPI_TYPE_BUFFER) {
+ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+ "acpi: expect buffer but type: %d\n", obj->type);
+ return -EINVAL;
+ }
+
+ len = obj->buffer.length;
+ if (len < sizeof(*ptr)) {
+ rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
+ __func__, len);
+ return -EINVAL;
+ }
+
+ ptr = (typeof(ptr))obj->buffer.pointer;
+ if (!chk_acpi_policy_6ghz_sig(ptr)) {
+ rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
+ return -EINVAL;
+ }
+
+ expect_len = struct_size(ptr, country_list, ptr->country_count);
+ if (len < expect_len) {
+ rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: expect %u but length: %u\n",
+ __func__, expect_len, len);
+ return -EINVAL;
+ }
+
+ *policy_6ghz = kmemdup(ptr, expect_len, GFP_KERNEL);
+ if (!*policy_6ghz)
+ return -ENOMEM;
+
+ rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz: ", *policy_6ghz,
+ expect_len);
+ 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;
+}
+
++static bool chk_acpi_policy_6ghz_vlp_sig(const struct rtw89_acpi_policy_6ghz_vlp *p)
++{
++ return p->signature[0] == 0x52 &&
++ p->signature[1] == 0x54 &&
++ p->signature[2] == 0x4B &&
++ p->signature[3] == 0x0B;
++}
++
++static
++int rtw89_acpi_dsm_get_policy_6ghz_vlp(struct rtw89_dev *rtwdev,
++ union acpi_object *obj,
++ struct rtw89_acpi_policy_6ghz_vlp **policy)
++{
++ const struct rtw89_acpi_policy_6ghz_vlp *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_vlp_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_vlp: ", *policy,
++ sizeof(*ptr));
++ 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;
++}
++
++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)
+{
+ union acpi_object *obj;
+ int ret;
+
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid,
+ 0, func, NULL);
+ if (!obj) {
+ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+ "acpi dsm fail to evaluate func: %d\n", func);
+ return -ENOENT;
+ }
+
+ 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 if (func == RTW89_ACPI_DSM_FUNC_6GHZ_VLP_SUP)
++ ret = rtw89_acpi_dsm_get_policy_6ghz_vlp(rtwdev, obj,
++ &res->u.policy_6ghz_vlp);
++ 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);
+
+ ACPI_FREE(obj);
+ return ret;
+}
+
+int rtw89_acpi_evaluate_rtag(struct rtw89_dev *rtwdev,
+ struct rtw89_acpi_rtag_result *res)
+{
- struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
- acpi_handle root, handle;
- union acpi_object *obj;
- acpi_status status;
++#if defined(__linux__)
++ const struct rtw89_acpi_data *data;
++#elif defined(__FreeBSD__)
++ struct rtw89_acpi_data *data;
++#endif
+ u32 buf_len;
+ int ret = 0;
+
- root = ACPI_HANDLE(rtwdev->dev);
- if (!root)
- return -EOPNOTSUPP;
-
- status = acpi_get_handle(root, (acpi_string)"RTAG", &handle);
- if (ACPI_FAILURE(status))
++ data = rtw89_acpi_evaluate_method(rtwdev, "RTAG");
++ if (!data)
+ return -EIO;
+
- status = acpi_evaluate_object(handle, NULL, NULL, &buf);
- if (ACPI_FAILURE(status))
- return -EIO;
++ buf_len = data->len;
++ if (buf_len != sizeof(*res)) {
++ rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
++ __func__, buf_len);
++ ret = -EINVAL;
++ goto out;
++ }
+
- obj = buf.pointer;
- if (obj->type != ACPI_TYPE_BUFFER) {
++ *res = *(struct rtw89_acpi_rtag_result *)data->buf;
++
++ rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "antenna_gain: ", res, sizeof(*res));
++
++out:
++ kfree(data);
++ return ret;
++}
++
++enum rtw89_acpi_sar_subband rtw89_acpi_sar_get_subband(struct rtw89_dev *rtwdev,
++ u32 center_freq)
++{
++ switch (center_freq) {
++ default:
+ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
- "acpi: expect buffer but type: %d\n", obj->type);
- ret = -EINVAL;
++ "center freq %u to ACPI SAR subband is unhandled\n",
++ center_freq);
++ fallthrough;
++ case 2412 ... 2484:
++ return RTW89_ACPI_SAR_2GHZ_SUBBAND;
++ case 5180 ... 5240:
++ return RTW89_ACPI_SAR_5GHZ_SUBBAND_1;
++ case 5250 ... 5320:
++ return RTW89_ACPI_SAR_5GHZ_SUBBAND_2;
++ case 5500 ... 5720:
++ return RTW89_ACPI_SAR_5GHZ_SUBBAND_2E;
++ case 5745 ... 5885:
++ return RTW89_ACPI_SAR_5GHZ_SUBBAND_3_4;
++ case 5955 ... 6155:
++ return RTW89_ACPI_SAR_6GHZ_SUBBAND_5_L;
++ case 6175 ... 6415:
++ return RTW89_ACPI_SAR_6GHZ_SUBBAND_5_H;
++ case 6435 ... 6515:
++ return RTW89_ACPI_SAR_6GHZ_SUBBAND_6;
++ case 6535 ... 6695:
++ return RTW89_ACPI_SAR_6GHZ_SUBBAND_7_L;
++ case 6715 ... 6855:
++ return RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H;
++
++ /* freq 6875 (ch 185, 20MHz) spans RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H
++ * and RTW89_ACPI_SAR_6GHZ_SUBBAND_8, so directly describe it with
++ * struct rtw89_6ghz_span.
++ */
++
++ case 6895 ... 7115:
++ return RTW89_ACPI_SAR_6GHZ_SUBBAND_8;
++ }
++}
++
++enum rtw89_band rtw89_acpi_sar_subband_to_band(struct rtw89_dev *rtwdev,
++ enum rtw89_acpi_sar_subband subband)
++{
++ switch (subband) {
++ default:
++ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
++ "ACPI SAR subband %u to band is unhandled\n", subband);
++ fallthrough;
++ case RTW89_ACPI_SAR_2GHZ_SUBBAND:
++ return RTW89_BAND_2G;
++ case RTW89_ACPI_SAR_5GHZ_SUBBAND_1:
++ return RTW89_BAND_5G;
++ case RTW89_ACPI_SAR_5GHZ_SUBBAND_2:
++ return RTW89_BAND_5G;
++ case RTW89_ACPI_SAR_5GHZ_SUBBAND_2E:
++ return RTW89_BAND_5G;
++ case RTW89_ACPI_SAR_5GHZ_SUBBAND_3_4:
++ return RTW89_BAND_5G;
++ case RTW89_ACPI_SAR_6GHZ_SUBBAND_5_L:
++ return RTW89_BAND_6G;
++ case RTW89_ACPI_SAR_6GHZ_SUBBAND_5_H:
++ return RTW89_BAND_6G;
++ case RTW89_ACPI_SAR_6GHZ_SUBBAND_6:
++ return RTW89_BAND_6G;
++ case RTW89_ACPI_SAR_6GHZ_SUBBAND_7_L:
++ return RTW89_BAND_6G;
++ case RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H:
++ return RTW89_BAND_6G;
++ case RTW89_ACPI_SAR_6GHZ_SUBBAND_8:
++ return RTW89_BAND_6G;
++ }
++}
++
++static u8 rtw89_acpi_sar_rfpath_to_hp_antidx(enum rtw89_rf_path rfpath)
++{
++ switch (rfpath) {
++ default:
++ case RF_PATH_B:
++ return 0;
++ case RF_PATH_A:
++ return 1;
++ }
++}
++
++static u8 rtw89_acpi_sar_rfpath_to_rt_antidx(enum rtw89_rf_path rfpath)
++{
++ switch (rfpath) {
++ default:
++ case RF_PATH_A:
++ return 0;
++ case RF_PATH_B:
++ return 1;
++ }
++}
++
++static s16 rtw89_acpi_sar_normalize_hp_val(u8 v)
++{
++ static const u8 bias = 10;
++ static const u8 fct = 1;
++ u16 res;
++
++ BUILD_BUG_ON(fct > TXPWR_FACTOR_OF_RTW89_ACPI_SAR);
++
++ res = (bias << TXPWR_FACTOR_OF_RTW89_ACPI_SAR) +
++ (v << (TXPWR_FACTOR_OF_RTW89_ACPI_SAR - fct));
++
++ return min_t(s32, res, MAX_VAL_OF_RTW89_ACPI_SAR);
++}
++
++static s16 rtw89_acpi_sar_normalize_rt_val(u8 v)
++{
++ static const u8 fct = 3;
++ u16 res;
++
++ BUILD_BUG_ON(fct > TXPWR_FACTOR_OF_RTW89_ACPI_SAR);
++
++ res = v << (TXPWR_FACTOR_OF_RTW89_ACPI_SAR - fct);
++
++ return min_t(s32, res, MAX_VAL_OF_RTW89_ACPI_SAR);
++}
++
++static
++void rtw89_acpi_sar_load_std_legacy(struct rtw89_dev *rtwdev,
++ const struct rtw89_acpi_sar_recognition *rec,
++ const void *content,
++ struct rtw89_sar_entry_from_acpi *ent)
++{
++ const struct rtw89_acpi_sar_std_legacy *ptr = content;
++ enum rtw89_acpi_sar_subband subband;
++ enum rtw89_rf_path path;
++
++ for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
++ for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
++ u8 antidx = rec->rfpath_to_antidx(path);
++
++ if (subband < RTW89_ACPI_SAR_SUBBAND_NR_LEGACY)
++ ent->v[subband][path] =
++ rec->normalize(ptr->v[antidx][subband]);
++ else
++ ent->v[subband][path] = MAX_VAL_OF_RTW89_ACPI_SAR;
++ }
++ }
++}
++
++static
++void rtw89_acpi_sar_load_std_has_6ghz(struct rtw89_dev *rtwdev,
++ const struct rtw89_acpi_sar_recognition *rec,
++ const void *content,
++ struct rtw89_sar_entry_from_acpi *ent)
++{
++ const struct rtw89_acpi_sar_std_has_6ghz *ptr = content;
++ enum rtw89_acpi_sar_subband subband;
++ enum rtw89_rf_path path;
++
++ BUILD_BUG_ON(RTW89_ACPI_SAR_SUBBAND_NR_HAS_6GHZ != NUM_OF_RTW89_ACPI_SAR_SUBBAND);
++
++ for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
++ for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
++ u8 antidx = rec->rfpath_to_antidx(path);
++
++ ent->v[subband][path] = rec->normalize(ptr->v[antidx][subband]);
++ }
++ }
++}
++
++static
++void rtw89_acpi_sar_load_sml_legacy(struct rtw89_dev *rtwdev,
++ const struct rtw89_acpi_sar_recognition *rec,
++ const void *content,
++ struct rtw89_sar_entry_from_acpi *ent)
++{
++ const struct rtw89_acpi_sar_sml_legacy *ptr = content;
++ enum rtw89_acpi_sar_subband subband;
++ enum rtw89_rf_path path;
++
++ for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
++ for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
++ u8 antidx = rec->rfpath_to_antidx(path);
++
++ if (subband < RTW89_ACPI_SAR_SUBBAND_NR_LEGACY)
++ ent->v[subband][path] =
++ rec->normalize(ptr->v[antidx][subband]);
++ else
++ ent->v[subband][path] = MAX_VAL_OF_RTW89_ACPI_SAR;
++ }
++ }
++}
++
++static
++void rtw89_acpi_sar_load_sml_has_6ghz(struct rtw89_dev *rtwdev,
++ const struct rtw89_acpi_sar_recognition *rec,
++ const void *content,
++ struct rtw89_sar_entry_from_acpi *ent)
++{
++ const struct rtw89_acpi_sar_sml_has_6ghz *ptr = content;
++ enum rtw89_acpi_sar_subband subband;
++ enum rtw89_rf_path path;
++
++ BUILD_BUG_ON(RTW89_ACPI_SAR_SUBBAND_NR_HAS_6GHZ != NUM_OF_RTW89_ACPI_SAR_SUBBAND);
++
++ for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
++ for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
++ u8 antidx = rec->rfpath_to_antidx(path);
++
++ ent->v[subband][path] = rec->normalize(ptr->v[antidx][subband]);
++ }
++ }
++}
++
++static s16 rtw89_acpi_geo_sar_normalize_delta(s8 delta)
++{
++ static const u8 fct = 1;
++
++ BUILD_BUG_ON(fct > TXPWR_FACTOR_OF_RTW89_ACPI_SAR);
++
++ return delta << (TXPWR_FACTOR_OF_RTW89_ACPI_SAR - fct);
++}
++
++static enum rtw89_acpi_geo_sar_regd_hp
++rtw89_acpi_geo_sar_regd_convert_hp_idx(enum rtw89_regulation_type regd)
++{
++ switch (regd) {
++ case RTW89_FCC:
++ case RTW89_IC:
++ case RTW89_NCC:
++ case RTW89_CHILE:
++ case RTW89_MEXICO:
++ return RTW89_ACPI_GEO_SAR_REGD_HP_FCC;
++ case RTW89_ETSI:
++ case RTW89_MKK:
++ case RTW89_ACMA:
++ return RTW89_ACPI_GEO_SAR_REGD_HP_ETSI;
++ default:
++ case RTW89_WW:
++ case RTW89_NA:
++ case RTW89_KCC:
++ return RTW89_ACPI_GEO_SAR_REGD_HP_WW;
++ }
++}
++
++static enum rtw89_acpi_geo_sar_regd_rt
++rtw89_acpi_geo_sar_regd_convert_rt_idx(enum rtw89_regulation_type regd)
++{
++ switch (regd) {
++ case RTW89_FCC:
++ case RTW89_NCC:
++ case RTW89_CHILE:
++ case RTW89_MEXICO:
++ return RTW89_ACPI_GEO_SAR_REGD_RT_FCC;
++ case RTW89_ETSI:
++ case RTW89_ACMA:
++ return RTW89_ACPI_GEO_SAR_REGD_RT_ETSI;
++ case RTW89_MKK:
++ return RTW89_ACPI_GEO_SAR_REGD_RT_MKK;
++ case RTW89_IC:
++ return RTW89_ACPI_GEO_SAR_REGD_RT_IC;
++ case RTW89_KCC:
++ return RTW89_ACPI_GEO_SAR_REGD_RT_KCC;
++ default:
++ case RTW89_WW:
++ case RTW89_NA:
++ return RTW89_ACPI_GEO_SAR_REGD_RT_WW;
++ }
++}
++
++static
++void rtw89_acpi_geo_sar_load_by_hp(struct rtw89_dev *rtwdev,
++ const struct rtw89_acpi_geo_sar_hp_val *ptr,
++ enum rtw89_rf_path path, s16 *val)
++{
++ u8 antidx = rtw89_acpi_sar_rfpath_to_hp_antidx(path);
++ s16 delta = rtw89_acpi_geo_sar_normalize_delta(ptr->delta[antidx]);
++ s16 max = rtw89_acpi_sar_normalize_hp_val(ptr->max);
++
++ *val = clamp_t(s32, (*val) + delta, MIN_VAL_OF_RTW89_ACPI_SAR, max);
++}
++
++static
++void rtw89_acpi_geo_sar_load_by_rt(struct rtw89_dev *rtwdev,
++ const struct rtw89_acpi_geo_sar_rt_val *ptr,
++ s16 *val)
++{
++ s16 delta = rtw89_acpi_geo_sar_normalize_delta(ptr->delta);
++ s16 max = rtw89_acpi_sar_normalize_rt_val(ptr->max);
++
++ *val = clamp_t(s32, (*val) + delta, MIN_VAL_OF_RTW89_ACPI_SAR, max);
++}
++
++static
++void rtw89_acpi_geo_sar_load_hp_legacy(struct rtw89_dev *rtwdev,
++ const void *content,
++ enum rtw89_regulation_type regd,
++ struct rtw89_sar_entry_from_acpi *ent)
++{
++ const struct rtw89_acpi_geo_sar_hp_legacy *ptr = content;
++ const struct rtw89_acpi_geo_sar_hp_legacy_entry *ptr_ent;
++ const struct rtw89_acpi_geo_sar_hp_val *ptr_ent_val;
++ enum rtw89_acpi_geo_sar_regd_hp geo_idx =
++ rtw89_acpi_geo_sar_regd_convert_hp_idx(regd);
++ enum rtw89_acpi_sar_subband subband;
++ enum rtw89_rf_path path;
++ enum rtw89_band band;
++
++ ptr_ent = &ptr->entries[geo_idx];
++
++ for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
++ band = rtw89_acpi_sar_subband_to_band(rtwdev, subband);
++ switch (band) {
++ case RTW89_BAND_2G:
++ ptr_ent_val = &ptr_ent->val_2ghz;
++ break;
++ case RTW89_BAND_5G:
++ ptr_ent_val = &ptr_ent->val_5ghz;
++ break;
++ default:
++ case RTW89_BAND_6G:
++ ptr_ent_val = NULL;
++ break;
++ }
++
++ if (!ptr_ent_val)
++ continue;
++
++ for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++)
++ rtw89_acpi_geo_sar_load_by_hp(rtwdev, ptr_ent_val, path,
++ &ent->v[subband][path]);
++ }
++}
++
++static
++void rtw89_acpi_geo_sar_load_hp_has_6ghz(struct rtw89_dev *rtwdev,
++ const void *content,
++ enum rtw89_regulation_type regd,
++ struct rtw89_sar_entry_from_acpi *ent)
++{
++ const struct rtw89_acpi_geo_sar_hp_has_6ghz *ptr = content;
++ const struct rtw89_acpi_geo_sar_hp_has_6ghz_entry *ptr_ent;
++ const struct rtw89_acpi_geo_sar_hp_val *ptr_ent_val;
++ enum rtw89_acpi_geo_sar_regd_hp geo_idx =
*** 60416 LINES SKIPPED ***