git: 6d67aabd6355 - main - rtw89: update Realtek's rtw89 driver.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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 ***