From nobody Thu Oct 23 21:28:27 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4cszfh36J1z6DZg8; Thu, 23 Oct 2025 21:28:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4cszfh0p9vz4PMp; Thu, 23 Oct 2025 21:28:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1761254908; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=usrL5jmJMqYKULtC/5QmuxqhMRWAWXFtPf/cAQE0JU0=; b=u4zVJB6gjCXYwU4648eiXNIrbCl2x9s3GwpMI7aLmYW/PwlXmdPzzs2qqph383dehsqo9f CAjwnU6zYnGZ4um+ctSZCB4hYeYILMOXvhhqJzdYp82zpE/72ldVuvzNMWoYpOxnh7BR1q 1mCN2rODu11lIk4ljrp7r1BORhwAqivEtOdtQEcHG44sCOTLwPJ4I+w7fyNlZNCqi0qNTz njgARrKc1yqPoCvDPzy4dVAbkrv0V3oLc6lcJ8/SHYrZO+syG/0qzI4Sw96hgXCkGWKJvo q/qRGIKwEdtsKGAv0kdg7o44ksiErV+2kwxf8mmChi2NMWthvEtoVGVYX89WpA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1761254908; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=usrL5jmJMqYKULtC/5QmuxqhMRWAWXFtPf/cAQE0JU0=; b=iDnL7GPcc35kxUGwAXjHUej3h6CKnGSHwMTn6kTmbK1Tm/n/A765U7B+LFTKPyeSs+NYan ax600cLCTHHEEGUs1zU7qkA2nFfgOH68HcEr8dIdkO/hQGcF28Hu2dtSOV/3nATmutfd4d Qs7dN5R6LU+cXvFJA4YElNpaqa1p/Z7KqczEhggaaY4o1v3shoorX2QvbJl0yNwK2n+cfV Yd8neIx0o5YNqY6bLPgZYfg0NEp4HMewjXBqor6daV4JR4HZ3SUEkUSgiA63hlJjrptkSC 30CgxD3yX9Xby0ved5OTkuNA7nEDs2oZUsSM0YtjT75rUOrL7IAjxvku1l45aQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1761254908; a=rsa-sha256; cv=none; b=nNxVXQ9suJTMtvVonf06re2m/thP8XosWcAA899deV2HFUQmlMJqWS8HP0qWelM/nGUP02 MJsR7RltxC0TFroMpLCyw09ZEvf3+Fwq/jwVECJZXQmzWMoEQDhuLj0kY3YS3Xr9lV6iCI f0itzws4F50er8V4W+m6ObxILEe8dpbS3JYKvBldMOojTAjwGVPme3g38Th7t+ejSGoNPb txIFo1iN+MTWpN4B3vEehvB11BFi9qORtf54TI/aHjxxk+3LTynzN7c7xIn2kLkqv/AdVt dDVXsBnOlqfKEEVc9h7UvD6ZzCnhM5TDDpjlW3TkLbYtKG9Os0KFlDi60NY9vw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4cszfh0MVKzY9X; Thu, 23 Oct 2025 21:28:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 59NLSR1Z081557; Thu, 23 Oct 2025 21:28:27 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 59NLSRrb081551; Thu, 23 Oct 2025 21:28:27 GMT (envelope-from git) Date: Thu, 23 Oct 2025 21:28:27 GMT Message-Id: <202510232128.59NLSRrb081551@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: 354a030185c6 - main - rtw89: update Realtek's rtw89 driver List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 354a030185c650d1465ed2035a83636b8f825d72 Auto-Submitted: auto-generated 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 AuthorDate: 2025-10-17 20:46:45 +0000 Commit: Bjoern A. Zeeb 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 +#include + +#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 ***