Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Apr 2026 20:59:56 +0000
From:      Bjoern A. Zeeb <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 422e9c5d878e - main - rtw89: update Realtek's rtw89 driver
Message-ID:  <69e3f0cc.2451c.5399c3c9@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=422e9c5d878e14ec16bb89ef6df65d964d5ce2f1

commit 422e9c5d878e14ec16bb89ef6df65d964d5ce2f1
Merge: 9ed3331fb582 777767fb72f8
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-04-18 20:48:44 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-04-18 20:48:44 +0000

    rtw89: update Realtek's rtw89 driver
    
    This version is based on
    git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    028ef9c96e96197026887c0f092424679298aae8 ( tag: v7.0 ).
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days

 sys/contrib/dev/rtw89/acpi.c            |    2 +-
 sys/contrib/dev/rtw89/cam.c             |  136 +++-
 sys/contrib/dev/rtw89/cam.h             |  129 ++++
 sys/contrib/dev/rtw89/chan.c            |   69 +-
 sys/contrib/dev/rtw89/chan.h            |    2 +
 sys/contrib/dev/rtw89/core.c            |  241 +++++-
 sys/contrib/dev/rtw89/core.h            |  198 ++++-
 sys/contrib/dev/rtw89/debug.c           |  165 ++++-
 sys/contrib/dev/rtw89/debug.h           |    1 +
 sys/contrib/dev/rtw89/efuse.c           |    4 -
 sys/contrib/dev/rtw89/efuse.h           |    6 +
 sys/contrib/dev/rtw89/efuse_be.c        |   26 +
 sys/contrib/dev/rtw89/fw.c              | 1227 ++++++++++++++++++++++++++++---
 sys/contrib/dev/rtw89/fw.h              |  521 +++++++++++--
 sys/contrib/dev/rtw89/mac.c             |  199 ++++-
 sys/contrib/dev/rtw89/mac.h             |  102 ++-
 sys/contrib/dev/rtw89/mac80211.c        |   46 +-
 sys/contrib/dev/rtw89/mac_be.c          |  696 ++++++++++++++++--
 sys/contrib/dev/rtw89/pci.c             |   22 +-
 sys/contrib/dev/rtw89/pci.h             |   57 +-
 sys/contrib/dev/rtw89/pci_be.c          |  138 +++-
 sys/contrib/dev/rtw89/phy.c             |  430 +++++++++--
 sys/contrib/dev/rtw89/phy.h             |   36 +-
 sys/contrib/dev/rtw89/phy_be.c          |  563 +++++++++++++-
 sys/contrib/dev/rtw89/ps.c              |    4 +-
 sys/contrib/dev/rtw89/reg.h             |  934 ++++++++++++++++++++++-
 sys/contrib/dev/rtw89/regd.c            |   21 +-
 sys/contrib/dev/rtw89/rtw8851b.c        |   10 +-
 sys/contrib/dev/rtw89/rtw8852a.c        |   10 +-
 sys/contrib/dev/rtw89/rtw8852au.c       |    4 +
 sys/contrib/dev/rtw89/rtw8852b.c        |   32 +-
 sys/contrib/dev/rtw89/rtw8852b_common.c |    2 -
 sys/contrib/dev/rtw89/rtw8852bt.c       |    8 +
 sys/contrib/dev/rtw89/rtw8852bu.c       |    2 +
 sys/contrib/dev/rtw89/rtw8852c.c        |   10 +-
 sys/contrib/dev/rtw89/rtw8852cu.c       |    2 +
 sys/contrib/dev/rtw89/rtw8922a.c        |   89 ++-
 sys/contrib/dev/rtw89/rtw8922a_rfk.c    |   48 +-
 sys/contrib/dev/rtw89/sar.c             |    2 +-
 sys/contrib/dev/rtw89/ser.c             |   12 +-
 sys/contrib/dev/rtw89/txrx.h            |   22 +
 sys/contrib/dev/rtw89/usb.c             |    7 +-
 sys/contrib/dev/rtw89/wow.c             |   16 +-
 sys/contrib/dev/rtw89/wow.h             |    1 +
 44 files changed, 5696 insertions(+), 556 deletions(-)

diff --cc sys/contrib/dev/rtw89/acpi.c
index fdba1ea46ec6,000000000000..86e5cf1825ba
mode 100644,000000..100644
--- a/sys/contrib/dev/rtw89/acpi.c
+++ b/sys/contrib/dev/rtw89/acpi.c
@@@ -1,1289 -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);
++	data = kzalloc_flex(*data, buf, len);
 +	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)
 +{
 +#if defined(__linux__)
 +	const struct rtw89_acpi_data *data;
 +#elif defined(__FreeBSD__)
 +	struct rtw89_acpi_data *data;
 +#endif
 +	u32 buf_len;
 +	int ret = 0;
 +
 +	data = rtw89_acpi_evaluate_method(rtwdev, "RTAG");
 +	if (!data)
 +		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;
 +	}
 +
 +	*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,
 +			    "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 =
 +		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;
 +		case RTW89_BAND_6G:
 +			ptr_ent_val = &ptr_ent->val_6ghz;
 +			break;
 +		default:
 +			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_rt_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_rt_legacy *ptr = content;
 +	const struct rtw89_acpi_geo_sar_rt_legacy_entry *ptr_ent;
 +	const struct rtw89_acpi_geo_sar_rt_val *ptr_ent_val;
 +	enum rtw89_acpi_geo_sar_regd_rt geo_idx =
 +		rtw89_acpi_geo_sar_regd_convert_rt_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_rt(rtwdev, ptr_ent_val,
 +						      &ent->v[subband][path]);
 +	}
 +}
 +
 +static
 +void rtw89_acpi_geo_sar_load_rt_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_rt_has_6ghz *ptr = content;
 +	const struct rtw89_acpi_geo_sar_rt_has_6ghz_entry *ptr_ent;
 +	const struct rtw89_acpi_geo_sar_rt_val *ptr_ent_val;
 +	enum rtw89_acpi_geo_sar_regd_rt geo_idx =
 +		rtw89_acpi_geo_sar_regd_convert_rt_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;
 +		case RTW89_BAND_6G:
 +			ptr_ent_val = &ptr_ent->val_6ghz;
 +			break;
 +		default:
 +			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_rt(rtwdev, ptr_ent_val,
 +						      &ent->v[subband][path]);
 +	}
 +}
 +
 +#define RTW89_ACPI_GEO_SAR_DECL_HANDLER(type) \
 +static const struct rtw89_acpi_geo_sar_handler \
 +rtw89_acpi_geo_sar_handler_ ## type = { \
 +	.data_size = RTW89_ACPI_GEO_SAR_SIZE_OF(type), \
 +	.load = rtw89_acpi_geo_sar_load_ ## type, \
 +}
 +
 +RTW89_ACPI_GEO_SAR_DECL_HANDLER(hp_legacy);
 +RTW89_ACPI_GEO_SAR_DECL_HANDLER(hp_has_6ghz);
 +RTW89_ACPI_GEO_SAR_DECL_HANDLER(rt_legacy);
 +RTW89_ACPI_GEO_SAR_DECL_HANDLER(rt_has_6ghz);
 +
 +static const struct rtw89_acpi_sar_recognition rtw89_acpi_sar_recs[] = {
 +	{
 +		.id = {
 +			.cid = RTW89_ACPI_SAR_CID_HP,
*** 57505 LINES SKIPPED ***


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e3f0cc.2451c.5399c3c9>