git: 6d67aabd6355 - main - rtw89: update Realtek's rtw89 driver.

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Mon, 28 Oct 2024 14:49:47 UTC
The branch main has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=6d67aabd63555ab62a2f2b7f52a75ef100a2fe75

commit 6d67aabd63555ab62a2f2b7f52a75ef100a2fe75
Merge: 11c53278a8a3 5b760eaecd6c
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2024-10-04 00:00:23 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2024-10-28 14:42:36 +0000

    rtw89: update Realtek's rtw89 driver.
    
    This adds support for the Realtek 8922AE PCI
    wireless network (Wi-Fi 7) adapter.
    
    This version is based on
    git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    98f7e32f20d28ec452afb208f9cffc08448a2652 ( tag: v6.11 ).
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      14 days

 share/man/man4/rtw89.4                      |   11 +-
 sys/contrib/dev/rtw89/Kconfig               |   19 +
 sys/contrib/dev/rtw89/Makefile              |   18 +-
 sys/contrib/dev/rtw89/acpi.c                |  131 +-
 sys/contrib/dev/rtw89/acpi.h                |   53 +-
 sys/contrib/dev/rtw89/cam.c                 |  277 +-
 sys/contrib/dev/rtw89/cam.h                 |  180 +-
 sys/contrib/dev/rtw89/chan.c                | 2305 +++++++++++++-
 sys/contrib/dev/rtw89/chan.h                |   48 +
 sys/contrib/dev/rtw89/coex.c                | 2996 +++++++++++++++---
 sys/contrib/dev/rtw89/coex.h                |  176 ++
 sys/contrib/dev/rtw89/core.c                | 1233 ++++++--
 sys/contrib/dev/rtw89/core.h                | 1468 ++++++++-
 sys/contrib/dev/rtw89/debug.c               |  440 ++-
 sys/contrib/dev/rtw89/debug.h               |   19 +-
 sys/contrib/dev/rtw89/efuse.c               |   11 +-
 sys/contrib/dev/rtw89/efuse.h               |   18 +-
 sys/contrib/dev/rtw89/efuse_be.c            |  562 ++++
 sys/contrib/dev/rtw89/fw.c                  | 4264 ++++++++++++++++++++++---
 sys/contrib/dev/rtw89/fw.h                  | 2637 ++++++++++------
 sys/contrib/dev/rtw89/mac.c                 | 1738 ++++++++---
 sys/contrib/dev/rtw89/mac.h                 |  377 ++-
 sys/contrib/dev/rtw89/mac80211.c            |  138 +-
 sys/contrib/dev/rtw89/mac_be.c              | 2606 ++++++++++++++++
 sys/contrib/dev/rtw89/pci.c                 |  794 ++++-
 sys/contrib/dev/rtw89/pci.h                 |  623 +++-
 sys/contrib/dev/rtw89/pci_be.c              |  618 ++++
 sys/contrib/dev/rtw89/phy.c                 | 2610 ++++++++++++++--
 sys/contrib/dev/rtw89/phy.h                 |  429 ++-
 sys/contrib/dev/rtw89/phy_be.c              | 1002 ++++++
 sys/contrib/dev/rtw89/ps.c                  |   97 +-
 sys/contrib/dev/rtw89/ps.h                  |    8 +
 sys/contrib/dev/rtw89/reg.h                 | 4292 ++++++++++++++++++++++++-
 sys/contrib/dev/rtw89/regd.c                |  522 +++-
 sys/contrib/dev/rtw89/rtw8851b.c            |  243 +-
 sys/contrib/dev/rtw89/rtw8851b_table.c      | 1409 +++++----
 sys/contrib/dev/rtw89/rtw8851b_table.h      |    3 -
 sys/contrib/dev/rtw89/rtw8851be.c           |    7 +
 sys/contrib/dev/rtw89/rtw8852a.c            |  158 +-
 sys/contrib/dev/rtw89/rtw8852a_table.c      |    2 +
 sys/contrib/dev/rtw89/rtw8852a_table.h      |    1 -
 sys/contrib/dev/rtw89/rtw8852ae.c           |    7 +
 sys/contrib/dev/rtw89/rtw8852b.c            | 1988 +-----------
 sys/contrib/dev/rtw89/rtw8852b.h            |  122 -
 sys/contrib/dev/rtw89/rtw8852b_common.c     | 2053 ++++++++++++
 sys/contrib/dev/rtw89/rtw8852b_common.h     |  388 +++
 sys/contrib/dev/rtw89/rtw8852b_rfk.c        |   25 +-
 sys/contrib/dev/rtw89/rtw8852b_table.c      |  459 +--
 sys/contrib/dev/rtw89/rtw8852b_table.h      |    3 -
 sys/contrib/dev/rtw89/rtw8852be.c           |    7 +
 sys/contrib/dev/rtw89/rtw8852bt.h           |   13 +
 sys/contrib/dev/rtw89/rtw8852bt_rfk.c       | 4019 ++++++++++++++++++++++++
 sys/contrib/dev/rtw89/rtw8852bt_rfk.h       |   22 +
 sys/contrib/dev/rtw89/rtw8852bt_rfk_table.c |  490 +++
 sys/contrib/dev/rtw89/rtw8852bt_rfk_table.h |   38 +
 sys/contrib/dev/rtw89/rtw8852c.c            |  231 +-
 sys/contrib/dev/rtw89/rtw8852c.h            |   20 +-
 sys/contrib/dev/rtw89/rtw8852c_rfk.c        |   93 +-
 sys/contrib/dev/rtw89/rtw8852c_rfk.h        |    3 +
 sys/contrib/dev/rtw89/rtw8852c_rfk_table.c  |   42 +-
 sys/contrib/dev/rtw89/rtw8852c_table.c      | 4488 +++++++++++++++------------
 sys/contrib/dev/rtw89/rtw8852c_table.h      |    3 -
 sys/contrib/dev/rtw89/rtw8852ce.c           |   29 +
 sys/contrib/dev/rtw89/rtw8922a.c            | 2639 ++++++++++++++++
 sys/contrib/dev/rtw89/rtw8922a.h            |   73 +
 sys/contrib/dev/rtw89/rtw8922a_rfk.c        |  391 +++
 sys/contrib/dev/rtw89/rtw8922a_rfk.h        |   18 +
 sys/contrib/dev/rtw89/rtw8922ae.c           |   94 +
 sys/contrib/dev/rtw89/sar.c                 |  222 +-
 sys/contrib/dev/rtw89/sar.h                 |   14 +-
 sys/contrib/dev/rtw89/ser.c                 |   44 +-
 sys/contrib/dev/rtw89/txrx.h                |  279 ++
 sys/contrib/dev/rtw89/util.c                |  106 +
 sys/contrib/dev/rtw89/util.h                |    5 +
 sys/contrib/dev/rtw89/wow.c                 |  787 ++++-
 sys/contrib/dev/rtw89/wow.h                 |   87 +
 sys/modules/rtw89/Makefile                  |   11 +-
 77 files changed, 45379 insertions(+), 8477 deletions(-)

diff --cc share/man/man4/rtw89.4
index 2e1f2676eb8e,000000000000..14259ae5e077
mode 100644,000000..100644
--- a/share/man/man4/rtw89.4
+++ b/share/man/man4/rtw89.4
@@@ -1,126 -1,0 +1,127 @@@
 +.\"-
 +.\" Copyright (c) 2023-2024 Bjoern A. Zeeb
 +.\"
 +.\" Redistribution and use in source and binary forms, with or without
 +.\" modification, are permitted provided that the following conditions
 +.\" are met:
 +.\" 1. Redistributions of source code must retain the above copyright
 +.\"    notice, this list of conditions and the following disclaimer.
 +.\" 2. Redistributions in binary form must reproduce the above copyright
 +.\"    notice, this list of conditions and the following disclaimer in the
 +.\"    documentation and/or other materials provided with the distribution.
 +.\"
 +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 +.\" SUCH DAMAGE.
 +.\"
 +.\" $FreeBSD$
 +.\"
- .Dd October 10, 2024
++.Dd October 12, 2024
 +.Dt RTW89 4
 +.Os
 +.Sh NAME
 +.Nm rtw89
 +.Nd Realtek IEEE 802.11ax wireless network driver
 +.Sh SYNOPSIS
 +The driver will auto-load without any user interaction using
 +.Xr devmatch 8
 +if enabled in
 +.Xr rc.conf 5 .
 +.Pp
 +Only if auto-loading is explicitly disabled, place the following
 +lines in
 +.Xr rc.conf 5
 +to manually load the driver as a module at boot time:
 +.Bd -literal -offset indent
 +kld_list="${kld_list} if_rtw89"
 +.Ed
 +.Pp
 +It is discouraged to load the driver from
 +.Xr loader 8 .
 +.Sh DESCRIPTION
 +The
 +.Nm
 +driver is derived from Realtek's Linux rtw89 driver.
 +.Pp
 +This driver requires firmware to be loaded before it will work.
 +The package
 +.Pa wifi-firmware-rtw89-kmod
 +from the
 +.Pa ports/net/wifi-firmware-rtw89-kmod
 +port needs to be installed before the driver is loaded.
 +Otherwise no
 +.Xr wlan 4
 +interface can be created using
 +.Xr ifconfig 8 .
 +One should use
 +.Xr fwget 8
 +to install the correct firmware package.
 +.Pp
 +The driver uses the
 +.\" No LinuxKPI man pages so no .Xr here.
 +.Em linuxkpi_wlan
 +and
 +.Em linuxkpi
 +compat framework to bridge between the Linux and
 +native
 +.Fx
 +driver code as well as to the native
 +.Xr net80211 4
 +wireless stack.
 +.Pp
 +While
 +.Nm
 +supports all 802.11 a/b/g/n/ac and ax
 +the compatibility code currently only supports 802.11 a/b/g modes.
 +Support for 802.11 n/ac is to come.
 +.Sh LOADER TUNABLES
 +.Bl -tag -width indent
 +.It Va compat.linuxkpi.skb.mem_limit
 +If you are running a 64bit system with more than 4GB of main memory
 +you need to set this tunable to
 +.Sy 1
 +in
 +.Xr loader.conf 5
 +and reboot once to make it effective.
 +This tunable will work around a problem with DMA and limit allocations
 +for network buffer memory to the lower 32bit of physical memory and
 +make the driver work.
 +.El
 +.Sh HARDWARE
 +The
 +.Nm
 +driver supports PCIe devices with the following chipsets:
 +.Pp
 +.Bl -tag -width Ds -offset indent -compact
- .It Realtek 802.11ax wireless 8851be (RTL8851BE)
- .It Realtek 802.11ax wireless 8852ae (RTL8852AE)
- .It Realtek 802.11ax wireless 8852be (RTL8852BE)
- .It Realtek 802.11ax wireless 8852ce (RTL8852CE)
++.It Realtek 8851BE Wi-Fi 6  (RTL8851BE)
++.It Realtek 8852AE Wi-Fi 6  (RTL8852AE)
++.It Realtek 8852BE Wi-Fi 6  (RTL8852BE)
++.It Realtek 8852CE Wi-Fi 6E (RTL8852CE)
++.It Realtek 8922AE Wi-Fi 7  (RTL8922AE)
 +.El
 +.Sh BUGS
 +Certainly.
 +.Pp
 +Does not seem to work (reliably) on machines with more than 4GB of
 +main memory.
 +See in the
 +.Sx LOADER TUNABLES
 +section above.
 +.Sh SEE ALSO
 +.Xr wlan 4 ,
 +.Xr fwget 8 ,
 +.Xr ifconfig 8 ,
 +.Xr wpa_supplicant 8
 +.Sh HISTORY
 +The
 +.Nm
 +driver first appeared in
 +.Fx 14.2 .
diff --cc sys/contrib/dev/rtw89/Makefile
index 41940099af1b,000000000000..1f1050a7a89d
mode 100644,000000..100644
--- a/sys/contrib/dev/rtw89/Makefile
+++ b/sys/contrib/dev/rtw89/Makefile
@@@ -1,61 -1,0 +1,75 @@@
 +# 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
++		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_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_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
++rtw89_pci-y := pci.o pci_be.o
 +
diff --cc sys/contrib/dev/rtw89/acpi.c
index 83252c861c82,000000000000..272795188f99
mode 100644,000000..100644
--- a/sys/contrib/dev/rtw89/acpi.c
+++ b/sys/contrib/dev/rtw89/acpi.c
@@@ -1,60 -1,0 +1,159 @@@
 +// 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"
 +
 +#if defined(__linux__)
 +static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
 +					   0x82, 0xBD, 0xFE, 0x86,
 +					   0x07, 0x80, 0x3A, 0xA7);
 +
- static int rtw89_acpi_dsm_get(struct rtw89_dev *rtwdev, union acpi_object *obj,
- 			      u8 *value)
++static
++int rtw89_acpi_dsm_get_value(struct rtw89_dev *rtwdev, union acpi_object *obj,
++			     u8 *value)
 +{
- 	switch (obj->type) {
- 	case ACPI_TYPE_INTEGER:
- 		*value = (u8)obj->integer.value;
- 		break;
- 	case ACPI_TYPE_BUFFER:
- 		*value = obj->buffer.pointer[0];
- 		break;
- 	default:
- 		rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
- 			    "acpi dsm return unhandled type: %d\n", obj->type);
++	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;
 +}
 +
 +int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
- 			    enum rtw89_acpi_dsm_func func, u8 *value)
++			    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_UNEXP,
++		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
 +			    "acpi dsm fail to evaluate func: %d\n", func);
 +		return -ENOENT;
 +	}
 +
- 	ret = rtw89_acpi_dsm_get(rtwdev, obj, value);
++	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);
 +
 +	ACPI_FREE(obj);
 +	return ret;
 +}
 +#elif defined(__FreeBSD__)
 +int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
- 			    enum rtw89_acpi_dsm_func func, u8 *value)
++			    enum rtw89_acpi_dsm_func func,
++			    struct rtw89_acpi_dsm_result *res)
 +{
 +	return -ENOENT;
 +}
 +#endif
diff --cc sys/contrib/dev/rtw89/core.c
index fff00da406e2,000000000000..d1f82bfad4a9
mode 100644,000000..100644
--- a/sys/contrib/dev/rtw89/core.c
+++ b/sys/contrib/dev/rtw89/core.c
@@@ -1,4040 -1,0 +1,4779 @@@
 +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 +/* Copyright(c) 2019-2020  Realtek Corporation
 + */
 +
 +#if defined(__FreeBSD__)
 +#define	LINUXKPI_PARAM_PREFIX	rtw89_
 +#endif
 +
 +#include <linux/ip.h>
 +#include <linux/udp.h>
 +
 +#include "cam.h"
 +#include "chan.h"
 +#include "coex.h"
 +#include "core.h"
 +#include "efuse.h"
 +#include "fw.h"
 +#include "mac.h"
 +#include "phy.h"
 +#include "ps.h"
 +#include "reg.h"
 +#include "sar.h"
 +#include "ser.h"
 +#include "txrx.h"
 +#include "util.h"
++#include "wow.h"
 +
 +static bool rtw89_disable_ps_mode;
 +module_param_named(disable_ps_mode, rtw89_disable_ps_mode, bool, 0644);
 +MODULE_PARM_DESC(disable_ps_mode, "Set Y to disable low power mode");
 +
 +#define RTW89_DEF_CHAN(_freq, _hw_val, _flags, _band)	\
 +	{ .center_freq = _freq, .hw_value = _hw_val, .flags = _flags, .band = _band, }
 +#define RTW89_DEF_CHAN_2G(_freq, _hw_val)	\
 +	RTW89_DEF_CHAN(_freq, _hw_val, 0, NL80211_BAND_2GHZ)
 +#define RTW89_DEF_CHAN_5G(_freq, _hw_val)	\
 +	RTW89_DEF_CHAN(_freq, _hw_val, 0, NL80211_BAND_5GHZ)
 +#define RTW89_DEF_CHAN_5G_NO_HT40MINUS(_freq, _hw_val)	\
 +	RTW89_DEF_CHAN(_freq, _hw_val, IEEE80211_CHAN_NO_HT40MINUS, NL80211_BAND_5GHZ)
 +#define RTW89_DEF_CHAN_6G(_freq, _hw_val)	\
 +	RTW89_DEF_CHAN(_freq, _hw_val, 0, NL80211_BAND_6GHZ)
 +
 +static struct ieee80211_channel rtw89_channels_2ghz[] = {
 +	RTW89_DEF_CHAN_2G(2412, 1),
 +	RTW89_DEF_CHAN_2G(2417, 2),
 +	RTW89_DEF_CHAN_2G(2422, 3),
 +	RTW89_DEF_CHAN_2G(2427, 4),
 +	RTW89_DEF_CHAN_2G(2432, 5),
 +	RTW89_DEF_CHAN_2G(2437, 6),
 +	RTW89_DEF_CHAN_2G(2442, 7),
 +	RTW89_DEF_CHAN_2G(2447, 8),
 +	RTW89_DEF_CHAN_2G(2452, 9),
 +	RTW89_DEF_CHAN_2G(2457, 10),
 +	RTW89_DEF_CHAN_2G(2462, 11),
 +	RTW89_DEF_CHAN_2G(2467, 12),
 +	RTW89_DEF_CHAN_2G(2472, 13),
 +	RTW89_DEF_CHAN_2G(2484, 14),
 +};
 +
 +static struct ieee80211_channel rtw89_channels_5ghz[] = {
 +	RTW89_DEF_CHAN_5G(5180, 36),
 +	RTW89_DEF_CHAN_5G(5200, 40),
 +	RTW89_DEF_CHAN_5G(5220, 44),
 +	RTW89_DEF_CHAN_5G(5240, 48),
 +	RTW89_DEF_CHAN_5G(5260, 52),
 +	RTW89_DEF_CHAN_5G(5280, 56),
 +	RTW89_DEF_CHAN_5G(5300, 60),
 +	RTW89_DEF_CHAN_5G(5320, 64),
 +	RTW89_DEF_CHAN_5G(5500, 100),
 +	RTW89_DEF_CHAN_5G(5520, 104),
 +	RTW89_DEF_CHAN_5G(5540, 108),
 +	RTW89_DEF_CHAN_5G(5560, 112),
 +	RTW89_DEF_CHAN_5G(5580, 116),
 +	RTW89_DEF_CHAN_5G(5600, 120),
 +	RTW89_DEF_CHAN_5G(5620, 124),
 +	RTW89_DEF_CHAN_5G(5640, 128),
 +	RTW89_DEF_CHAN_5G(5660, 132),
 +	RTW89_DEF_CHAN_5G(5680, 136),
 +	RTW89_DEF_CHAN_5G(5700, 140),
 +	RTW89_DEF_CHAN_5G(5720, 144),
 +	RTW89_DEF_CHAN_5G(5745, 149),
 +	RTW89_DEF_CHAN_5G(5765, 153),
 +	RTW89_DEF_CHAN_5G(5785, 157),
 +	RTW89_DEF_CHAN_5G(5805, 161),
 +	RTW89_DEF_CHAN_5G_NO_HT40MINUS(5825, 165),
 +	RTW89_DEF_CHAN_5G(5845, 169),
 +	RTW89_DEF_CHAN_5G(5865, 173),
 +	RTW89_DEF_CHAN_5G(5885, 177),
 +};
 +
++static_assert(RTW89_5GHZ_UNII4_START_INDEX + RTW89_5GHZ_UNII4_CHANNEL_NUM ==
++	      ARRAY_SIZE(rtw89_channels_5ghz));
++
 +static struct ieee80211_channel rtw89_channels_6ghz[] = {
 +	RTW89_DEF_CHAN_6G(5955, 1),
 +	RTW89_DEF_CHAN_6G(5975, 5),
 +	RTW89_DEF_CHAN_6G(5995, 9),
 +	RTW89_DEF_CHAN_6G(6015, 13),
 +	RTW89_DEF_CHAN_6G(6035, 17),
 +	RTW89_DEF_CHAN_6G(6055, 21),
 +	RTW89_DEF_CHAN_6G(6075, 25),
 +	RTW89_DEF_CHAN_6G(6095, 29),
 +	RTW89_DEF_CHAN_6G(6115, 33),
 +	RTW89_DEF_CHAN_6G(6135, 37),
 +	RTW89_DEF_CHAN_6G(6155, 41),
 +	RTW89_DEF_CHAN_6G(6175, 45),
 +	RTW89_DEF_CHAN_6G(6195, 49),
 +	RTW89_DEF_CHAN_6G(6215, 53),
 +	RTW89_DEF_CHAN_6G(6235, 57),
 +	RTW89_DEF_CHAN_6G(6255, 61),
 +	RTW89_DEF_CHAN_6G(6275, 65),
 +	RTW89_DEF_CHAN_6G(6295, 69),
 +	RTW89_DEF_CHAN_6G(6315, 73),
 +	RTW89_DEF_CHAN_6G(6335, 77),
 +	RTW89_DEF_CHAN_6G(6355, 81),
 +	RTW89_DEF_CHAN_6G(6375, 85),
 +	RTW89_DEF_CHAN_6G(6395, 89),
 +	RTW89_DEF_CHAN_6G(6415, 93),
 +	RTW89_DEF_CHAN_6G(6435, 97),
 +	RTW89_DEF_CHAN_6G(6455, 101),
 +	RTW89_DEF_CHAN_6G(6475, 105),
 +	RTW89_DEF_CHAN_6G(6495, 109),
 +	RTW89_DEF_CHAN_6G(6515, 113),
 +	RTW89_DEF_CHAN_6G(6535, 117),
 +	RTW89_DEF_CHAN_6G(6555, 121),
 +	RTW89_DEF_CHAN_6G(6575, 125),
 +	RTW89_DEF_CHAN_6G(6595, 129),
 +	RTW89_DEF_CHAN_6G(6615, 133),
 +	RTW89_DEF_CHAN_6G(6635, 137),
 +	RTW89_DEF_CHAN_6G(6655, 141),
 +	RTW89_DEF_CHAN_6G(6675, 145),
 +	RTW89_DEF_CHAN_6G(6695, 149),
 +	RTW89_DEF_CHAN_6G(6715, 153),
 +	RTW89_DEF_CHAN_6G(6735, 157),
 +	RTW89_DEF_CHAN_6G(6755, 161),
 +	RTW89_DEF_CHAN_6G(6775, 165),
 +	RTW89_DEF_CHAN_6G(6795, 169),
 +	RTW89_DEF_CHAN_6G(6815, 173),
 +	RTW89_DEF_CHAN_6G(6835, 177),
 +	RTW89_DEF_CHAN_6G(6855, 181),
 +	RTW89_DEF_CHAN_6G(6875, 185),
 +	RTW89_DEF_CHAN_6G(6895, 189),
 +	RTW89_DEF_CHAN_6G(6915, 193),
 +	RTW89_DEF_CHAN_6G(6935, 197),
 +	RTW89_DEF_CHAN_6G(6955, 201),
 +	RTW89_DEF_CHAN_6G(6975, 205),
 +	RTW89_DEF_CHAN_6G(6995, 209),
 +	RTW89_DEF_CHAN_6G(7015, 213),
 +	RTW89_DEF_CHAN_6G(7035, 217),
 +	RTW89_DEF_CHAN_6G(7055, 221),
 +	RTW89_DEF_CHAN_6G(7075, 225),
 +	RTW89_DEF_CHAN_6G(7095, 229),
 +	RTW89_DEF_CHAN_6G(7115, 233),
 +};
 +
 +static struct ieee80211_rate rtw89_bitrates[] = {
 +	{ .bitrate = 10,  .hw_value = 0x00, },
 +	{ .bitrate = 20,  .hw_value = 0x01, },
 +	{ .bitrate = 55,  .hw_value = 0x02, },
 +	{ .bitrate = 110, .hw_value = 0x03, },
 +	{ .bitrate = 60,  .hw_value = 0x04, },
 +	{ .bitrate = 90,  .hw_value = 0x05, },
 +	{ .bitrate = 120, .hw_value = 0x06, },
 +	{ .bitrate = 180, .hw_value = 0x07, },
 +	{ .bitrate = 240, .hw_value = 0x08, },
 +	{ .bitrate = 360, .hw_value = 0x09, },
 +	{ .bitrate = 480, .hw_value = 0x0a, },
 +	{ .bitrate = 540, .hw_value = 0x0b, },
 +};
 +
 +static const struct ieee80211_iface_limit rtw89_iface_limits[] = {
 +	{
 +		.max = 1,
 +		.types = BIT(NL80211_IFTYPE_STATION),
 +	},
 +	{
 +		.max = 1,
 +		.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
 +			 BIT(NL80211_IFTYPE_P2P_GO) |
 +			 BIT(NL80211_IFTYPE_AP),
 +	},
 +};
 +
++static const struct ieee80211_iface_limit rtw89_iface_limits_mcc[] = {
++	{
++		.max = 1,
++		.types = BIT(NL80211_IFTYPE_STATION),
++	},
++	{
++		.max = 1,
++		.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
++			 BIT(NL80211_IFTYPE_P2P_GO),
++	},
++};
++
 +static const struct ieee80211_iface_combination rtw89_iface_combs[] = {
 +	{
 +		.limits = rtw89_iface_limits,
 +		.n_limits = ARRAY_SIZE(rtw89_iface_limits),
 +		.max_interfaces = 2,
 +		.num_different_channels = 1,
- 	}
++	},
++	{
++		.limits = rtw89_iface_limits_mcc,
++		.n_limits = ARRAY_SIZE(rtw89_iface_limits_mcc),
++		.max_interfaces = 2,
++		.num_different_channels = 2,
++	},
 +};
 +
 +bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate)
 +{
 +	struct ieee80211_rate rate;
 +
 +	if (unlikely(rpt_rate >= ARRAY_SIZE(rtw89_bitrates))) {
 +		rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "invalid rpt rate %d\n", rpt_rate);
 +		return false;
 +	}
 +
 +	rate = rtw89_bitrates[rpt_rate];
 +	*bitrate = rate.bitrate;
 +
 +	return true;
 +}
 +
 +static const struct ieee80211_supported_band rtw89_sband_2ghz = {
 +	.band		= NL80211_BAND_2GHZ,
 +	.channels	= rtw89_channels_2ghz,
 +	.n_channels	= ARRAY_SIZE(rtw89_channels_2ghz),
 +	.bitrates	= rtw89_bitrates,
 +	.n_bitrates	= ARRAY_SIZE(rtw89_bitrates),
 +	.ht_cap		= {0},
 +	.vht_cap	= {0},
 +};
 +
 +static const struct ieee80211_supported_band rtw89_sband_5ghz = {
 +	.band		= NL80211_BAND_5GHZ,
 +	.channels	= rtw89_channels_5ghz,
 +	.n_channels	= ARRAY_SIZE(rtw89_channels_5ghz),
 +
 +	/* 5G has no CCK rates, 1M/2M/5.5M/11M */
 +	.bitrates	= rtw89_bitrates + 4,
 +	.n_bitrates	= ARRAY_SIZE(rtw89_bitrates) - 4,
 +	.ht_cap		= {0},
 +	.vht_cap	= {0},
 +};
 +
 +static const struct ieee80211_supported_band rtw89_sband_6ghz = {
 +	.band		= NL80211_BAND_6GHZ,
 +	.channels	= rtw89_channels_6ghz,
 +	.n_channels	= ARRAY_SIZE(rtw89_channels_6ghz),
 +
 +	/* 6G has no CCK rates, 1M/2M/5.5M/11M */
 +	.bitrates	= rtw89_bitrates + 4,
 +	.n_bitrates	= ARRAY_SIZE(rtw89_bitrates) - 4,
 +};
 +
 +static void rtw89_traffic_stats_accu(struct rtw89_dev *rtwdev,
 +				     struct rtw89_traffic_stats *stats,
 +				     struct sk_buff *skb, bool tx)
 +{
 +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 +
++	if (tx && ieee80211_is_assoc_req(hdr->frame_control))
++		rtw89_wow_parse_akm(rtwdev, skb);
++
 +	if (!ieee80211_is_data(hdr->frame_control))
 +		return;
 +
 +	if (is_broadcast_ether_addr(hdr->addr1) ||
 +	    is_multicast_ether_addr(hdr->addr1))
 +		return;
 +
 +	if (tx) {
 +		stats->tx_cnt++;
 +		stats->tx_unicast += skb->len;
 +	} else {
 +		stats->rx_cnt++;
 +		stats->rx_unicast += skb->len;
 +	}
 +}
 +
 +void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef)
 +{
 +	cfg80211_chandef_create(chandef, &rtw89_channels_2ghz[0],
 +				NL80211_CHAN_NO_HT);
 +}
 +
- static void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
- 				     struct rtw89_chan *chan)
++void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
++			      struct rtw89_chan *chan)
 +{
 +	struct ieee80211_channel *channel = chandef->chan;
 +	enum nl80211_chan_width width = chandef->width;
 +	u32 primary_freq, center_freq;
 +	u8 center_chan;
 +	u8 bandwidth = RTW89_CHANNEL_WIDTH_20;
 +	u32 offset;
 +	u8 band;
 +
 +	center_chan = channel->hw_value;
 +	primary_freq = channel->center_freq;
 +	center_freq = chandef->center_freq1;
 +
 +	switch (width) {
 +	case NL80211_CHAN_WIDTH_20_NOHT:
 +	case NL80211_CHAN_WIDTH_20:
 +		bandwidth = RTW89_CHANNEL_WIDTH_20;
 +		break;
 +	case NL80211_CHAN_WIDTH_40:
 +		bandwidth = RTW89_CHANNEL_WIDTH_40;
 +		if (primary_freq > center_freq) {
 +			center_chan -= 2;
 +		} else {
 +			center_chan += 2;
 +		}
 +		break;
 +	case NL80211_CHAN_WIDTH_80:
 +	case NL80211_CHAN_WIDTH_160:
 +		bandwidth = nl_to_rtw89_bandwidth(width);
 +		if (primary_freq > center_freq) {
 +			offset = (primary_freq - center_freq - 10) / 20;
 +			center_chan -= 2 + offset * 4;
 +		} else {
 +			offset = (center_freq - primary_freq - 10) / 20;
 +			center_chan += 2 + offset * 4;
 +		}
 +		break;
 +	default:
 +		center_chan = 0;
 +		break;
 +	}
 +
 +	switch (channel->band) {
 +	default:
 +	case NL80211_BAND_2GHZ:
 +		band = RTW89_BAND_2G;
 +		break;
 +	case NL80211_BAND_5GHZ:
 +		band = RTW89_BAND_5G;
 +		break;
 +	case NL80211_BAND_6GHZ:
 +		band = RTW89_BAND_6G;
 +		break;
 +	}
 +
 +	rtw89_chan_create(chan, center_chan, channel->hw_value, band, bandwidth);
 +}
 +
 +void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
 +{
++	struct rtw89_hal *hal = &rtwdev->hal;
 +	const struct rtw89_chip_info *chip = rtwdev->chip;
 +	const struct rtw89_chan *chan;
 +	enum rtw89_sub_entity_idx sub_entity_idx;
++	enum rtw89_sub_entity_idx roc_idx;
 +	enum rtw89_phy_idx phy_idx;
 +	enum rtw89_entity_mode mode;
 +	bool entity_active;
 +
 +	entity_active = rtw89_get_entity_state(rtwdev);
 +	if (!entity_active)
 +		return;
 +
 +	mode = rtw89_get_entity_mode(rtwdev);
- 	if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode))
++	switch (mode) {
++	case RTW89_ENTITY_MODE_SCC:
++	case RTW89_ENTITY_MODE_MCC:
++		sub_entity_idx = RTW89_SUB_ENTITY_0;
++		break;
++	case RTW89_ENTITY_MODE_MCC_PREPARE:
++		sub_entity_idx = RTW89_SUB_ENTITY_1;
++		break;
++	default:
++		WARN(1, "Invalid ent mode: %d\n", mode);
 +		return;
++	}
++
++	roc_idx = atomic_read(&hal->roc_entity_idx);
++	if (roc_idx != RTW89_SUB_ENTITY_IDLE)
++		sub_entity_idx = roc_idx;
 +
- 	sub_entity_idx = RTW89_SUB_ENTITY_0;
 +	phy_idx = RTW89_PHY_0;
 +	chan = rtw89_chan_get(rtwdev, sub_entity_idx);
 +	chip->ops->set_txpwr(rtwdev, chan, phy_idx);
 +}
 +
- void rtw89_set_channel(struct rtw89_dev *rtwdev)
++int rtw89_set_channel(struct rtw89_dev *rtwdev)
 +{
++	struct rtw89_hal *hal = &rtwdev->hal;
 +	const struct rtw89_chip_info *chip = rtwdev->chip;
- 	const struct cfg80211_chan_def *chandef;
++	const struct rtw89_chan_rcd *chan_rcd;
++	const struct rtw89_chan *chan;
 +	enum rtw89_sub_entity_idx sub_entity_idx;
++	enum rtw89_sub_entity_idx roc_idx;
 +	enum rtw89_mac_idx mac_idx;
 +	enum rtw89_phy_idx phy_idx;
- 	struct rtw89_chan chan;
 +	struct rtw89_channel_help_params bak;
 +	enum rtw89_entity_mode mode;
- 	bool band_changed;
 +	bool entity_active;
 +
 +	entity_active = rtw89_get_entity_state(rtwdev);
 +
 +	mode = rtw89_entity_recalc(rtwdev);
- 	if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode))
- 		return;
++	switch (mode) {
++	case RTW89_ENTITY_MODE_SCC:
++	case RTW89_ENTITY_MODE_MCC:
++		sub_entity_idx = RTW89_SUB_ENTITY_0;
++		break;
++	case RTW89_ENTITY_MODE_MCC_PREPARE:
++		sub_entity_idx = RTW89_SUB_ENTITY_1;
++		break;
++	default:
++		WARN(1, "Invalid ent mode: %d\n", mode);
++		return -EINVAL;
++	}
++
++	roc_idx = atomic_read(&hal->roc_entity_idx);
++	if (roc_idx != RTW89_SUB_ENTITY_IDLE)
++		sub_entity_idx = roc_idx;
 +
- 	sub_entity_idx = RTW89_SUB_ENTITY_0;
 +	mac_idx = RTW89_MAC_0;
 +	phy_idx = RTW89_PHY_0;
- 	chandef = rtw89_chandef_get(rtwdev, sub_entity_idx);
- 	rtw89_get_channel_params(chandef, &chan);
- 	if (WARN(chan.channel == 0, "Invalid channel\n"))
- 		return;
 +
- 	band_changed = rtw89_assign_entity_chan(rtwdev, sub_entity_idx, &chan);
++	chan = rtw89_chan_get(rtwdev, sub_entity_idx);
++	chan_rcd = rtw89_chan_rcd_get(rtwdev, sub_entity_idx);
 +
- 	rtw89_chip_set_channel_prepare(rtwdev, &bak, &chan, mac_idx, phy_idx);
++	rtw89_chip_set_channel_prepare(rtwdev, &bak, chan, mac_idx, phy_idx);
 +
- 	chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx);
++	chip->ops->set_channel(rtwdev, chan, mac_idx, phy_idx);
 +
- 	chip->ops->set_txpwr(rtwdev, &chan, phy_idx);
++	chip->ops->set_txpwr(rtwdev, chan, phy_idx);
 +
- 	rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx);
++	rtw89_chip_set_channel_done(rtwdev, &bak, chan, mac_idx, phy_idx);
 +
- 	if (!entity_active || band_changed) {
- 		rtw89_btc_ntfy_switch_band(rtwdev, phy_idx, chan.band_type);
++	if (!entity_active || chan_rcd->band_changed) {
++		rtw89_btc_ntfy_switch_band(rtwdev, phy_idx, chan->band_type);
 +		rtw89_chip_rfk_band_changed(rtwdev, phy_idx);
 +	}
 +
 +	rtw89_set_entity_state(rtwdev, true);
++	return 0;
 +}
 +
 +void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
 +		       struct rtw89_chan *chan)
 +{
 +	const struct cfg80211_chan_def *chandef;
 +
 +	chandef = rtw89_chandef_get(rtwdev, rtwvif->sub_entity_idx);
 +	rtw89_get_channel_params(chandef, chan);
 +}
 +
 +static enum rtw89_core_tx_type
*** 50395 LINES SKIPPED ***