* [PATCH 0/1] wifi: rtw89: usb: Support switching to USB 3 mode
@ 2026-05-08 5:44 Lucid Duck
2026-05-08 5:44 ` [PATCH 1/1] " Lucid Duck
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Lucid Duck @ 2026-05-08 5:44 UTC (permalink / raw)
To: linux-wireless
Cc: Ping-Ke Shih, Bitterblue Smith, linux-kernel, Devin Wittmayer
From: Devin Wittmayer <lucid_duck@justthetip.ca>
This patch adds USB 2 to USB 3 mode switching for the AX-generation
chips in the rtw89 USB driver (8852AU, 8852BU, 8852CU and helper
variants). Without it, those adapters enumerate at USB 2.0
high-speed on first plug and stay there, capping real-world
throughput around 260 Mbps TCP regardless of radio capability.
It is Bitterblue Smith's morrownr/rtw89 commit cd287ccf544b
(2025-07-16) rebased onto wireless-next without code changes:
author's Signed-off-by preserved, my Signed-off-by added as
relayer, Tested-by per chip based on the matrix below.
The bug
=======
These chips present as USB 2 devices on first plug. The driver is
expected to send a switch-mode register write to make them disappear
and re-enumerate as USB 3 SuperSpeed. Mainline rtw89 does not issue
these commands anywhere. Every user with one of these adapters on
a mainline-derived distribution sits at the USB 2.0 ceiling for
the life of the plug, regardless of negotiated radio rate.
The fix
=======
The patch covers AX-generation chips (8852AU, 8852BU, 8852CU and
helper variants) via R_AX_PAD_CTRL2. It also adds the
switch_usb_mode module parameter (default on) for users who
experience 2.4 GHz interference under USB 3.
Mainline precedent
==================
The same mechanism is in mainline rtw88 across three commits
between July 2024 and April 2025, all authored by Bitterblue Smith:
commit 315c23a64e99 ("wifi: rtw88: usb: Support USB 3 with RTL8822CU/RTL8822BU")
commit 82a35723a67c ("wifi: rtw88: usb: Support USB 3 with RTL8812AU")
commit bf1103654df9 ("wifi: rtw88: usb: Enable switching the RTL8814AU to USB 3")
Reviewer of record: Ping-Ke Shih, current rtw89 maintainer.
Test results
============
60 plug-cycles + 30+ gated throughput cells captured 2026-04-11
to 2026-05-07. Both x86_64 (Tiger Lake xHCI) and aarch64
(Broadcom RP1 xHCI) reproductions confirm the bug and the fix.
Hosts: Framework 13 (x86_64, Fedora 43 / 6.19.13, Tiger Lake xHCI)
NucBox K8 Plus (x86_64, Arch Linux / 6.17.9, AMD F19h USB)
Raspberry Pi 5 (aarch64, Pi OS / 6.12.47, BCM2712 + RP1)
Banana Pi BPi-R4 Pro (aarch64, OpenWrt / 6.6.93, MT7988A;
also used as a controlled lab AP)
Adapters: D-Link DWA-X1850 A1 / B1 (RTL8852AU)
BrosTrend AX1L compact / AX4L high-gain (RTL8852BU)
BrosTrend AX8L AXE5400 / EDUP AXE5400 (RTL8852CU)
APs: consumer multi-band router (WPA3-SAE / WPA2-PSK)
BPi-R4 Pro single-band lab AP (WPA3-SAE)
Server: Linux iperf3 host on 2.5 GbE wired Ethernet
Full per-cell evidence (raw iperf3 stdout, dmesg captures, sysfs
snapshots, iw link snapshots, byte-counter deltas, per-host detail)
at https://github.com/Lucid-Duck/rtw89-usb3-gap.
Plug-cycle. N=10 cycles per (chip, host) cell. Pass = post-plug
/sys/bus/usb/devices/<id>/speed reads 5000 (USB 3 SuperSpeed),
zero WARN/BUG/Oops in cycle-bracketed dmesg, non-empty association
BSSID after settle.
Adapter (chip) FW13 6.19 K8 Plus 6.17
--------------------------- ------------- --------------
DWA-X1850 A1 (RTL8852AU) 10/10 PASS 10/10 PASS
BrosTrend AX1L (RTL8852BU) 10/10 PASS 10/10 PASS
FW13: Fedora 43, 6.19.13, wireless-next + this patch
K8 Plus: Arch Linux, 6.17.9-arch1-1, morrownr/rtw89 (upstream
fork; identical AX-gen behavior to this patch)
Throughput. TCP iperf3, N=10 30-second iterations per sub-cell,
four sub-cells per cell (P=8 and P=1, each direction), to a Linux
2.5 GbE host. Per-cell /32 host route forces traffic onto the WiFi
adapter; per-iteration byte-counter cross-check on every cited cell
shows wireless tx/rx delta at 103-108% of iperf3 reported bytes
(excess is normal TCP/IP framing), so wired-NIC bleed is ruled out.
Linux tuning applied (rmem 32 MB, RPS=ff on the WiFi RX queue).
FW13 stock (in-kernel rtw89, USB 2 stuck) vs patched (USB 3
SuperSpeed), same adapter / AP / kernel / capture script, P=8 mean
Mbps, AP is the consumer multi-band router:
Adapter (chip) Band, width UL stock UL patched DL stock DL patched
-------------------------- --------------- -------- ---------- -------- ----------
EDUP AXE5400 (RTL8852CU) 6 GHz, 160 MHz 269 1364 327 579
AX8L AXE5400 (RTL8852CU) 6 GHz, 160 MHz 269 1440 324 510
AX4L AX1800 (RTL8852BU) 5 GHz, 80 MHz 208 597 293 695
AX1L AX1800 (RTL8852BU) 5 GHz, 80 MHz 235 608 273 843
DWA-X1850 A1 (RTL8852AU) 5 GHz, 80 MHz 254 748 264 707
DWA-X1850 B1 (RTL8852AU) 5 GHz, 80 MHz 248 706 265 679
USB enumeration verified at SuperSpeed (5000 Mbps) on every
patched cell, both pre and post.
K8 Plus second-rig spot check, kernel 6.17.9-arch1-1, consumer
multi-band router, single-link 5 GHz 80 MHz, TCP P=1, N=10:
DWA-X1850 A1 (RTL8852AU) 788 UL / 693 DL Mbps (sigma 16 / 54)
For comparison, every stock cell above caps at 208-327 Mbps, the
USB 2.0 ceiling.
Future work: BE-generation (RTL8922AU) USB switch-mode
======================================================
The same mechanism applies to BE-generation chips (RTL8922AU) via
R_BE_PAD_CTRL2.
The implementation is in morrownr/rtw89 commit c8a8ac49996b
("wifi: rtw89: usb: USB 3 switching for RTL8922AU", 2025-08-07)
by Bitterblue Smith, but that commit has no Signed-off-by; the
public two-week notice in
https://github.com/morrownr/rtw89/issues/82 (2026-04-21,
deadline 2026-05-05) did not produce one. checkpatch --strict
rejects third-party submission on the missing trailer.
I tested c8a8ac49996b on a BrosTrend BE6500 (RTL8922AU): plug-
cycle 10/10 PASS on both FW13 and K8 Plus; consumer-router MLO
3-link 1430 UL / 995 DL Mbps P=8; BPi-R4 Pro single-link 5 GHz
160 MHz EHT 1335 UL / 1058 DL Mbps P=8; switch_usb_mode=N forces
USB 2 at 255 UL / 311 DL Mbps. Detail in the rtw89-usb3-gap repo
above.
Adding the BE-gen switch-mode to mainline today cannot yet help
RTL8922AU users on its own, because mainline rtw89 has no
in-kernel rtw89_8922au USB driver: RTL8922AU adapters do not
attach to mainline at all. Switch-mode becomes load-bearing for
BE-gen the moment the rtw89_8922au USB driver lands upstream;
until then it would sit as dormant code. The path upstream for
the switch-mode itself is either Bitterblue's Signed-off-by on
c8a8ac49996b, or a Realtek developer carrying it as part of the
broader 8922au USB enablement.
(The AX-gen gap that this patch fixes does affect every mainline
user with an RTL8852AU/BU/CU adapter today. BE-gen is a separate,
strictly forward-looking concern.)
Submission notes
================
Applies cleanly on wireless-next HEAD 7baf5857e15d.
checkpatch.pl --strict: zero errors, zero warnings, zero checks.
Bitterblue Smith (1):
wifi: rtw89: usb: Support switching to USB 3 mode
drivers/net/wireless/realtek/rtw89/reg.h | 4 +++
drivers/net/wireless/realtek/rtw89/usb.c | 41 ++++++++++++++++++++++++
2 files changed, 45 insertions(+)
--
2.53.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/1] wifi: rtw89: usb: Support switching to USB 3 mode
2026-05-08 5:44 [PATCH 0/1] wifi: rtw89: usb: Support switching to USB 3 mode Lucid Duck
@ 2026-05-08 5:44 ` Lucid Duck
2026-05-08 6:59 ` Zenm Chen
2026-05-11 10:55 ` [PATCH 0/1] " Bitterblue Smith
2026-05-11 16:08 ` [PATCH rtw-next v2 " Devin Wittmayer
2 siblings, 1 reply; 10+ messages in thread
From: Lucid Duck @ 2026-05-08 5:44 UTC (permalink / raw)
To: linux-wireless
Cc: Ping-Ke Shih, Bitterblue Smith, linux-kernel, Devin Wittmayer
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
The Realtek wifi 6/7 devices which support USB 3 are weird: when first
plugged in, they pretend to be USB 2. The driver needs to send some
commands to the device, which make it disappear and come back as a
USB 3 device.
Implement the required commands in rtw89.
When a USB 3 device is plugged into a USB 2 port, rtw89 will try to
switch it to USB 3 mode only once. The device will disappear and come
back still in USB 2 mode, of course.
Some people experience heavy interference in the 2.4 GHz band in
USB 3 mode, so add a module parameter switch_usb_mode with the
default value 1 to let people disable the switching.
Tested with RTL8832BU and RTL8832CU.
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Signed-off-by: Devin Wittmayer <lucid_duck@justthetip.ca>
Tested-by: Devin Wittmayer <lucid_duck@justthetip.ca>
---
drivers/net/wireless/realtek/rtw89/reg.h | 4 +++
drivers/net/wireless/realtek/rtw89/usb.c | 41 ++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 42ffe83931a3..7d4c085d9fb2 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -164,6 +164,10 @@
#define R_AX_DBG_PORT_SEL 0x00C0
#define B_AX_DEBUG_ST_MASK GENMASK(31, 0)
+#define R_AX_PAD_CTRL2 0x00C4
+#define U2SWITCHU3 0xB
+#define USB_SWITCH_DELAY 0xF
+
#define R_AX_PMC_DBG_CTRL2 0x00CC
#define B_AX_SYSON_DIS_PMCR_AX_WRMSK BIT(2)
diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
index 767a95f759b1..4fb25791d118 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.c
+++ b/drivers/net/wireless/realtek/rtw89/usb.c
@@ -9,6 +9,11 @@
#include "txrx.h"
#include "usb.h"
+static bool rtw89_switch_usb_mode = true;
+module_param_named(switch_usb_mode, rtw89_switch_usb_mode, bool, 0644);
+MODULE_PARM_DESC(switch_usb_mode,
+ "Set to N to disable switching to USB 3 mode to avoid potential interference in the 2.4 GHz band (default: Y)");
+
static void rtw89_usb_read_port_complete(struct urb *urb);
static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
@@ -1027,6 +1032,35 @@ static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev,
usb_set_intfdata(intf, NULL);
}
+static int rtw89_usb_switch_mode(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
+
+ if (!rtw89_switch_usb_mode)
+ return 0;
+
+ /* No known USB 3 devices with this chip. */
+ if (rtwdev->chip->chip_id == RTL8851B)
+ return 0;
+
+ if (rtwusb->udev->speed == USB_SPEED_SUPER)
+ return 0;
+
+ rtw89_debug(rtwdev, RTW89_DBG_HCI, "%s: pad_ctrl2: %#x %#x\n",
+ __func__,
+ rtw89_read8(rtwdev, R_AX_PAD_CTRL2 + 1),
+ rtw89_read8(rtwdev, R_AX_PAD_CTRL2 + 2));
+
+ /* Already tried to switch but it's a USB 2 port. */
+ if (rtw89_read8(rtwdev, R_AX_PAD_CTRL2 + 1) == USB_SWITCH_DELAY)
+ return 0;
+
+ rtw89_write8(rtwdev, R_AX_PAD_CTRL2 + 1, USB_SWITCH_DELAY);
+ rtw89_write8(rtwdev, R_AX_PAD_CTRL2 + 2, U2SWITCHU3);
+
+ return 1;
+}
+
int rtw89_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1059,6 +1093,13 @@ int rtw89_usb_probe(struct usb_interface *intf,
goto err_free_hw;
}
+ ret = rtw89_usb_switch_mode(rtwdev);
+ if (ret) {
+ /* Not a fail, but we do need to skip rtw89_core_register. */
+ ret = 0;
+ goto err_intf_deinit;
+ }
+
if (rtwusb->udev->speed == USB_SPEED_SUPER)
rtwdev->hci.dle_type = RTW89_HCI_DLE_TYPE_USB3;
else
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* RE: [PATCH 1/1] wifi: rtw89: usb: Support switching to USB 3 mode
2026-05-08 5:44 ` [PATCH 1/1] " Lucid Duck
@ 2026-05-08 6:59 ` Zenm Chen
0 siblings, 0 replies; 10+ messages in thread
From: Zenm Chen @ 2026-05-08 6:59 UTC (permalink / raw)
To: lucid_duck; +Cc: linux-kernel, linux-wireless, pkshih, rtl8821cerfe2
I don't remember Bitterblue allows you to upstream his work.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/1] wifi: rtw89: usb: Support switching to USB 3 mode
2026-05-08 5:44 [PATCH 0/1] wifi: rtw89: usb: Support switching to USB 3 mode Lucid Duck
2026-05-08 5:44 ` [PATCH 1/1] " Lucid Duck
@ 2026-05-11 10:55 ` Bitterblue Smith
2026-05-11 16:08 ` [PATCH rtw-next v2 " Devin Wittmayer
2 siblings, 0 replies; 10+ messages in thread
From: Bitterblue Smith @ 2026-05-11 10:55 UTC (permalink / raw)
To: Lucid Duck, linux-wireless; +Cc: Ping-Ke Shih, linux-kernel
On 08/05/2026 08:44, Lucid Duck wrote:
> From: Devin Wittmayer <lucid_duck@justthetip.ca>
>
> This patch adds USB 2 to USB 3 mode switching for the AX-generation
> chips in the rtw89 USB driver (8852AU, 8852BU, 8852CU and helper
> variants). Without it, those adapters enumerate at USB 2.0
> high-speed on first plug and stay there, capping real-world
> throughput around 260 Mbps TCP regardless of radio capability.
>
> It is Bitterblue Smith's morrownr/rtw89 commit cd287ccf544b
> (2025-07-16) rebased onto wireless-next without code changes:
> author's Signed-off-by preserved, my Signed-off-by added as
> relayer, Tested-by per chip based on the matrix below.
>
> The bug
> =======
>
> These chips present as USB 2 devices on first plug. The driver is
> expected to send a switch-mode register write to make them disappear
> and re-enumerate as USB 3 SuperSpeed. Mainline rtw89 does not issue
> these commands anywhere. Every user with one of these adapters on
> a mainline-derived distribution sits at the USB 2.0 ceiling for
> the life of the plug, regardless of negotiated radio rate.
>
> The fix
> =======
>
> The patch covers AX-generation chips (8852AU, 8852BU, 8852CU and
> helper variants) via R_AX_PAD_CTRL2. It also adds the
> switch_usb_mode module parameter (default on) for users who
> experience 2.4 GHz interference under USB 3.
>
> Mainline precedent
> ==================
>
> The same mechanism is in mainline rtw88 across three commits
> between July 2024 and April 2025, all authored by Bitterblue Smith:
>
> commit 315c23a64e99 ("wifi: rtw88: usb: Support USB 3 with RTL8822CU/RTL8822BU")
> commit 82a35723a67c ("wifi: rtw88: usb: Support USB 3 with RTL8812AU")
> commit bf1103654df9 ("wifi: rtw88: usb: Enable switching the RTL8814AU to USB 3")
>
> Reviewer of record: Ping-Ke Shih, current rtw89 maintainer.
>
> Test results
> ============
>
> 60 plug-cycles + 30+ gated throughput cells captured 2026-04-11
> to 2026-05-07. Both x86_64 (Tiger Lake xHCI) and aarch64
> (Broadcom RP1 xHCI) reproductions confirm the bug and the fix.
>
> Hosts: Framework 13 (x86_64, Fedora 43 / 6.19.13, Tiger Lake xHCI)
> NucBox K8 Plus (x86_64, Arch Linux / 6.17.9, AMD F19h USB)
> Raspberry Pi 5 (aarch64, Pi OS / 6.12.47, BCM2712 + RP1)
> Banana Pi BPi-R4 Pro (aarch64, OpenWrt / 6.6.93, MT7988A;
> also used as a controlled lab AP)
> Adapters: D-Link DWA-X1850 A1 / B1 (RTL8852AU)
> BrosTrend AX1L compact / AX4L high-gain (RTL8852BU)
> BrosTrend AX8L AXE5400 / EDUP AXE5400 (RTL8852CU)
> APs: consumer multi-band router (WPA3-SAE / WPA2-PSK)
> BPi-R4 Pro single-band lab AP (WPA3-SAE)
> Server: Linux iperf3 host on 2.5 GbE wired Ethernet
>
> Full per-cell evidence (raw iperf3 stdout, dmesg captures, sysfs
> snapshots, iw link snapshots, byte-counter deltas, per-host detail)
> at https://github.com/Lucid-Duck/rtw89-usb3-gap.
>
> Plug-cycle. N=10 cycles per (chip, host) cell. Pass = post-plug
> /sys/bus/usb/devices/<id>/speed reads 5000 (USB 3 SuperSpeed),
> zero WARN/BUG/Oops in cycle-bracketed dmesg, non-empty association
> BSSID after settle.
>
> Adapter (chip) FW13 6.19 K8 Plus 6.17
> --------------------------- ------------- --------------
> DWA-X1850 A1 (RTL8852AU) 10/10 PASS 10/10 PASS
> BrosTrend AX1L (RTL8852BU) 10/10 PASS 10/10 PASS
>
> FW13: Fedora 43, 6.19.13, wireless-next + this patch
> K8 Plus: Arch Linux, 6.17.9-arch1-1, morrownr/rtw89 (upstream
> fork; identical AX-gen behavior to this patch)
>
> Throughput. TCP iperf3, N=10 30-second iterations per sub-cell,
> four sub-cells per cell (P=8 and P=1, each direction), to a Linux
> 2.5 GbE host. Per-cell /32 host route forces traffic onto the WiFi
> adapter; per-iteration byte-counter cross-check on every cited cell
> shows wireless tx/rx delta at 103-108% of iperf3 reported bytes
> (excess is normal TCP/IP framing), so wired-NIC bleed is ruled out.
> Linux tuning applied (rmem 32 MB, RPS=ff on the WiFi RX queue).
>
> FW13 stock (in-kernel rtw89, USB 2 stuck) vs patched (USB 3
> SuperSpeed), same adapter / AP / kernel / capture script, P=8 mean
> Mbps, AP is the consumer multi-band router:
>
> Adapter (chip) Band, width UL stock UL patched DL stock DL patched
> -------------------------- --------------- -------- ---------- -------- ----------
> EDUP AXE5400 (RTL8852CU) 6 GHz, 160 MHz 269 1364 327 579
> AX8L AXE5400 (RTL8852CU) 6 GHz, 160 MHz 269 1440 324 510
> AX4L AX1800 (RTL8852BU) 5 GHz, 80 MHz 208 597 293 695
> AX1L AX1800 (RTL8852BU) 5 GHz, 80 MHz 235 608 273 843
> DWA-X1850 A1 (RTL8852AU) 5 GHz, 80 MHz 254 748 264 707
> DWA-X1850 B1 (RTL8852AU) 5 GHz, 80 MHz 248 706 265 679
>
> USB enumeration verified at SuperSpeed (5000 Mbps) on every
> patched cell, both pre and post.
>
> K8 Plus second-rig spot check, kernel 6.17.9-arch1-1, consumer
> multi-band router, single-link 5 GHz 80 MHz, TCP P=1, N=10:
>
> DWA-X1850 A1 (RTL8852AU) 788 UL / 693 DL Mbps (sigma 16 / 54)
>
> For comparison, every stock cell above caps at 208-327 Mbps, the
> USB 2.0 ceiling.
>
> Future work: BE-generation (RTL8922AU) USB switch-mode
> ======================================================
>
> The same mechanism applies to BE-generation chips (RTL8922AU) via
> R_BE_PAD_CTRL2.
> The implementation is in morrownr/rtw89 commit c8a8ac49996b
> ("wifi: rtw89: usb: USB 3 switching for RTL8922AU", 2025-08-07)
> by Bitterblue Smith, but that commit has no Signed-off-by; the
> public two-week notice in
> https://github.com/morrownr/rtw89/issues/82 (2026-04-21,
> deadline 2026-05-05) did not produce one. checkpatch --strict
> rejects third-party submission on the missing trailer.
>
This is what's stopping you? Haha.
> I tested c8a8ac49996b on a BrosTrend BE6500 (RTL8922AU): plug-
> cycle 10/10 PASS on both FW13 and K8 Plus; consumer-router MLO
> 3-link 1430 UL / 995 DL Mbps P=8; BPi-R4 Pro single-link 5 GHz
> 160 MHz EHT 1335 UL / 1058 DL Mbps P=8; switch_usb_mode=N forces
> USB 2 at 255 UL / 311 DL Mbps. Detail in the rtw89-usb3-gap repo
> above.
>
> Adding the BE-gen switch-mode to mainline today cannot yet help
> RTL8922AU users on its own, because mainline rtw89 has no
> in-kernel rtw89_8922au USB driver: RTL8922AU adapters do not
> attach to mainline at all. Switch-mode becomes load-bearing for
> BE-gen the moment the rtw89_8922au USB driver lands upstream;
> until then it would sit as dormant code. The path upstream for
> the switch-mode itself is either Bitterblue's Signed-off-by on
> c8a8ac49996b, or a Realtek developer carrying it as part of the
> broader 8922au USB enablement.
>
> (The AX-gen gap that this patch fixes does affect every mainline
> user with an RTL8852AU/BU/CU adapter today. BE-gen is a separate,
> strictly forward-looking concern.)
>
> Submission notes
> ================
>
> Applies cleanly on wireless-next HEAD 7baf5857e15d.
> checkpatch.pl --strict: zero errors, zero warnings, zero checks.
>
Realtek wifi patches should be based on rtw-next (or rtw if it's an
urgent bug fix):
https://github.com/pkshih/rtw/
The subject should include the tree: "[PATCH rtw-next 0/1]"
> Bitterblue Smith (1):
> wifi: rtw89: usb: Support switching to USB 3 mode
>
> drivers/net/wireless/realtek/rtw89/reg.h | 4 +++
> drivers/net/wireless/realtek/rtw89/usb.c | 41 ++++++++++++++++++++++++
> 2 files changed, 45 insertions(+)
>
> --
> 2.53.0
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH rtw-next v2 0/1] wifi: rtw89: usb: Support switching to USB 3 mode
2026-05-08 5:44 [PATCH 0/1] wifi: rtw89: usb: Support switching to USB 3 mode Lucid Duck
2026-05-08 5:44 ` [PATCH 1/1] " Lucid Duck
2026-05-11 10:55 ` [PATCH 0/1] " Bitterblue Smith
@ 2026-05-11 16:08 ` Devin Wittmayer
2026-05-11 16:08 ` [PATCH rtw-next v2 1/1] " Devin Wittmayer
2 siblings, 1 reply; 10+ messages in thread
From: Devin Wittmayer @ 2026-05-11 16:08 UTC (permalink / raw)
To: linux-wireless; +Cc: pkshih, rtl8821cerfe2, linux-kernel, Devin Wittmayer
This patch adds USB 2 to USB 3 mode switching for the AX-generation
chips in the rtw89 USB driver (8852AU, 8852BU, 8852CU and helper
variants). Without it, those adapters enumerate at USB 2.0
high-speed on first plug and stay there, capping real-world
throughput around 260 Mbps TCP regardless of radio capability.
It is Bitterblue Smith's morrownr/rtw89 commit cd287ccf544b
(2025-07-16) rebased onto rtw-next without code changes:
author's Signed-off-by preserved, my Signed-off-by added as
relayer, Tested-by per chip based on the matrix below.
Changes since v1
================
- Rebased onto pkshih/rtw rtw-next (HEAD c1ed02655f91) per
maintainer feedback. The patch diff is unchanged from v1; the
test matrix below carries forward.
- Cover letter tightened to AX-generation scope only.
The bug
=======
These chips present as USB 2 devices on first plug. The driver is
expected to send a switch-mode register write to make them disappear
and re-enumerate as USB 3 SuperSpeed. Mainline rtw89 does not issue
these commands anywhere. Every user with one of these adapters on
a mainline-derived distribution sits at the USB 2.0 ceiling for
the life of the plug, regardless of negotiated radio rate.
The fix
=======
The patch covers AX-generation chips (8852AU, 8852BU, 8852CU and
helper variants) via R_AX_PAD_CTRL2. It also adds the
switch_usb_mode module parameter (default on) for users who
experience 2.4 GHz interference under USB 3.
Mainline precedent
==================
The same mechanism is in mainline rtw88 across three commits
between July 2024 and April 2025, all authored by Bitterblue Smith:
commit 315c23a64e99 ("wifi: rtw88: usb: Support USB 3 with RTL8822CU/RTL8822BU")
commit 82a35723a67c ("wifi: rtw88: usb: Support USB 3 with RTL8812AU")
commit bf1103654df9 ("wifi: rtw88: usb: Enable switching the RTL8814AU to USB 3")
Test results
============
60 plug-cycles + 30+ gated throughput cells captured 2026-04-11
to 2026-05-07. Both x86_64 (Tiger Lake xHCI) and aarch64
(Broadcom RP1 xHCI) reproductions confirm the bug and the fix.
Hosts: Framework 13 (x86_64, Fedora 43 / 6.19.13, Tiger Lake xHCI)
NucBox K8 Plus (x86_64, Arch Linux / 6.17.9, AMD F19h USB)
Raspberry Pi 5 (aarch64, Pi OS / 6.12.47, BCM2712 + RP1)
Banana Pi BPi-R4 Pro (aarch64, OpenWrt / 6.6.93, MT7988A;
also used as a controlled lab AP)
Adapters: D-Link DWA-X1850 A1 / B1 (RTL8852AU)
BrosTrend AX1L compact / AX4L high-gain (RTL8852BU)
BrosTrend AX8L AXE5400 / EDUP AXE5400 (RTL8852CU)
APs: consumer multi-band router (WPA3-SAE / WPA2-PSK)
BPi-R4 Pro single-band lab AP (WPA3-SAE)
Server: Linux iperf3 host on 2.5 GbE wired Ethernet
Full per-cell evidence (raw iperf3 stdout, dmesg captures, sysfs
snapshots, iw link snapshots, byte-counter deltas, per-host detail)
at https://github.com/Lucid-Duck/rtw89-usb3-gap.
Plug-cycle. N=10 cycles per (chip, host) cell. Pass = post-plug
/sys/bus/usb/devices/<id>/speed reads 5000 (USB 3 SuperSpeed),
zero WARN/BUG/Oops in cycle-bracketed dmesg, non-empty association
BSSID after settle.
Adapter (chip) FW13 6.19 K8 Plus 6.17
--------------------------- ------------- --------------
DWA-X1850 A1 (RTL8852AU) 10/10 PASS 10/10 PASS
BrosTrend AX1L (RTL8852BU) 10/10 PASS 10/10 PASS
FW13: Fedora 43, 6.19.13, wireless-next + this patch
K8 Plus: Arch Linux, 6.17.9-arch1-1, morrownr/rtw89 (upstream
fork; identical AX-gen behavior to this patch)
Throughput. TCP iperf3, N=10 30-second iterations per sub-cell,
four sub-cells per cell (P=8 and P=1, each direction), to a Linux
2.5 GbE host. Per-cell /32 host route forces traffic onto the WiFi
adapter; per-iteration byte-counter cross-check on every cited cell
shows wireless tx/rx delta at 103-108% of iperf3 reported bytes
(excess is normal TCP/IP framing), so wired-NIC bleed is ruled out.
Linux tuning applied (rmem 32 MB, RPS=ff on the WiFi RX queue).
FW13 stock (in-kernel rtw89, USB 2 stuck) vs patched (USB 3
SuperSpeed), same adapter / AP / kernel / capture script, P=8 mean
Mbps, AP is the consumer multi-band router:
Adapter (chip) Band, width UL stock UL patched DL stock DL patched
-------------------------- --------------- -------- ---------- -------- ----------
EDUP AXE5400 (RTL8852CU) 6 GHz, 160 MHz 269 1364 327 579
AX8L AXE5400 (RTL8852CU) 6 GHz, 160 MHz 269 1440 324 510
AX4L AX1800 (RTL8852BU) 5 GHz, 80 MHz 208 597 293 695
AX1L AX1800 (RTL8852BU) 5 GHz, 80 MHz 235 608 273 843
DWA-X1850 A1 (RTL8852AU) 5 GHz, 80 MHz 254 748 264 707
DWA-X1850 B1 (RTL8852AU) 5 GHz, 80 MHz 248 706 265 679
USB enumeration verified at SuperSpeed (5000 Mbps) on every
patched cell, both pre and post.
K8 Plus second-rig spot check, kernel 6.17.9-arch1-1, consumer
multi-band router, single-link 5 GHz 80 MHz, TCP P=1, N=10:
DWA-X1850 A1 (RTL8852AU) 788 UL / 693 DL Mbps (sigma 16 / 54)
For comparison, every stock cell above caps at 208-327 Mbps, the
USB 2.0 ceiling.
Submission notes
================
Applies cleanly on pkshih/rtw rtw-next HEAD c1ed02655f91.
checkpatch.pl --strict: zero errors, zero warnings, zero checks.
Bitterblue Smith (1):
wifi: rtw89: usb: Support switching to USB 3 mode
drivers/net/wireless/realtek/rtw89/reg.h | 4 +++
drivers/net/wireless/realtek/rtw89/usb.c | 41 ++++++++++++++++++++++++
2 files changed, 45 insertions(+)
--
2.53.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH rtw-next v2 1/1] wifi: rtw89: usb: Support switching to USB 3 mode
2026-05-11 16:08 ` [PATCH rtw-next v2 " Devin Wittmayer
@ 2026-05-11 16:08 ` Devin Wittmayer
2026-05-11 17:26 ` Johannes Berg
2026-05-11 18:14 ` Bitterblue Smith
0 siblings, 2 replies; 10+ messages in thread
From: Devin Wittmayer @ 2026-05-11 16:08 UTC (permalink / raw)
To: linux-wireless; +Cc: pkshih, rtl8821cerfe2, linux-kernel, Devin Wittmayer
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
The Realtek wifi 6/7 devices which support USB 3 are weird: when first
plugged in, they pretend to be USB 2. The driver needs to send some
commands to the device, which make it disappear and come back as a
USB 3 device.
Implement the required commands in rtw89.
When a USB 3 device is plugged into a USB 2 port, rtw89 will try to
switch it to USB 3 mode only once. The device will disappear and come
back still in USB 2 mode, of course.
Some people experience heavy interference in the 2.4 GHz band in
USB 3 mode, so add a module parameter switch_usb_mode with the
default value 1 to let people disable the switching.
Tested with RTL8832BU and RTL8832CU.
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Signed-off-by: Devin Wittmayer <lucid_duck@justthetip.ca>
Tested-by: Devin Wittmayer <lucid_duck@justthetip.ca>
---
drivers/net/wireless/realtek/rtw89/reg.h | 4 +++
drivers/net/wireless/realtek/rtw89/usb.c | 41 ++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 42ffe83931a3..7d4c085d9fb2 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -164,6 +164,10 @@
#define R_AX_DBG_PORT_SEL 0x00C0
#define B_AX_DEBUG_ST_MASK GENMASK(31, 0)
+#define R_AX_PAD_CTRL2 0x00C4
+#define U2SWITCHU3 0xB
+#define USB_SWITCH_DELAY 0xF
+
#define R_AX_PMC_DBG_CTRL2 0x00CC
#define B_AX_SYSON_DIS_PMCR_AX_WRMSK BIT(2)
diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
index 767a95f759b1..4fb25791d118 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.c
+++ b/drivers/net/wireless/realtek/rtw89/usb.c
@@ -9,6 +9,11 @@
#include "txrx.h"
#include "usb.h"
+static bool rtw89_switch_usb_mode = true;
+module_param_named(switch_usb_mode, rtw89_switch_usb_mode, bool, 0644);
+MODULE_PARM_DESC(switch_usb_mode,
+ "Set to N to disable switching to USB 3 mode to avoid potential interference in the 2.4 GHz band (default: Y)");
+
static void rtw89_usb_read_port_complete(struct urb *urb);
static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
@@ -1027,6 +1032,35 @@ static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev,
usb_set_intfdata(intf, NULL);
}
+static int rtw89_usb_switch_mode(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
+
+ if (!rtw89_switch_usb_mode)
+ return 0;
+
+ /* No known USB 3 devices with this chip. */
+ if (rtwdev->chip->chip_id == RTL8851B)
+ return 0;
+
+ if (rtwusb->udev->speed == USB_SPEED_SUPER)
+ return 0;
+
+ rtw89_debug(rtwdev, RTW89_DBG_HCI, "%s: pad_ctrl2: %#x %#x\n",
+ __func__,
+ rtw89_read8(rtwdev, R_AX_PAD_CTRL2 + 1),
+ rtw89_read8(rtwdev, R_AX_PAD_CTRL2 + 2));
+
+ /* Already tried to switch but it's a USB 2 port. */
+ if (rtw89_read8(rtwdev, R_AX_PAD_CTRL2 + 1) == USB_SWITCH_DELAY)
+ return 0;
+
+ rtw89_write8(rtwdev, R_AX_PAD_CTRL2 + 1, USB_SWITCH_DELAY);
+ rtw89_write8(rtwdev, R_AX_PAD_CTRL2 + 2, U2SWITCHU3);
+
+ return 1;
+}
+
int rtw89_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1059,6 +1093,13 @@ int rtw89_usb_probe(struct usb_interface *intf,
goto err_free_hw;
}
+ ret = rtw89_usb_switch_mode(rtwdev);
+ if (ret) {
+ /* Not a fail, but we do need to skip rtw89_core_register. */
+ ret = 0;
+ goto err_intf_deinit;
+ }
+
if (rtwusb->udev->speed == USB_SPEED_SUPER)
rtwdev->hci.dle_type = RTW89_HCI_DLE_TYPE_USB3;
else
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH rtw-next v2 1/1] wifi: rtw89: usb: Support switching to USB 3 mode
2026-05-11 16:08 ` [PATCH rtw-next v2 1/1] " Devin Wittmayer
@ 2026-05-11 17:26 ` Johannes Berg
2026-05-11 18:03 ` Devin Wittmayer
2026-05-11 18:14 ` Bitterblue Smith
1 sibling, 1 reply; 10+ messages in thread
From: Johannes Berg @ 2026-05-11 17:26 UTC (permalink / raw)
To: Devin Wittmayer, linux-wireless; +Cc: pkshih, rtl8821cerfe2, linux-kernel
On Mon, 2026-05-11 at 09:08 -0700, Devin Wittmayer wrote:
>
> +static bool rtw89_switch_usb_mode = true;
> +module_param_named(switch_usb_mode, rtw89_switch_usb_mode, bool, 0644);
> +MODULE_PARM_DESC(switch_usb_mode,
> + "Set to N to disable switching to USB 3 mode to avoid potential interference in the 2.4 GHz band (default: Y)");
We shouldn't really add new module parameters.
johannes
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH rtw-next v2 1/1] wifi: rtw89: usb: Support switching to USB 3 mode
2026-05-11 17:26 ` Johannes Berg
@ 2026-05-11 18:03 ` Devin Wittmayer
0 siblings, 0 replies; 10+ messages in thread
From: Devin Wittmayer @ 2026-05-11 18:03 UTC (permalink / raw)
To: johannes, linux-wireless
Cc: pkshih, rtl8821cerfe2, linux-kernel, Devin Wittmayer
On Mon, 2026-05-11 at 19:26 +0200, Johannes Berg wrote:
> > +static bool rtw89_switch_usb_mode = true;
> > +module_param_named(switch_usb_mode, rtw89_switch_usb_mode, bool, 0644);
> > +MODULE_PARM_DESC(switch_usb_mode,
> > + "Set to N to disable switching to USB 3 mode to avoid potential interference in the 2.4 GHz band (default: Y)");
>
> We shouldn't really add new module parameters.
This module parameter follows the pattern Bitterblue established for
rtw88: same user-facing name (switch_usb_mode), same description, same
default. Commit 315c23a64e99 "wifi: rtw88: usb: Support USB 3 with
RTL8822CU/RTL8822BU" (2024-07-10) added it to rtw88/usb.c and it
remains in-tree.
Three v3 paths I see:
1. Drop the param. Users hitting USB3 2.4 GHz harmonic interference
would need to use a USB 2 port instead.
2. Move the escape hatch behind a sysfs or nl80211 control. New UABI
surface; open to design suggestions on that.
3. Keep it for rtw89/rtw88 symmetry on the same USB3 / 2.4 GHz
harmonic interference issue.
Any of the three works on my side. If the rtw88 param is grandfathered
and we should not add new module parameters even in this case, I will
respin without it in v3.
Devin
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH rtw-next v2 1/1] wifi: rtw89: usb: Support switching to USB 3 mode
2026-05-11 16:08 ` [PATCH rtw-next v2 1/1] " Devin Wittmayer
2026-05-11 17:26 ` Johannes Berg
@ 2026-05-11 18:14 ` Bitterblue Smith
2026-05-11 20:03 ` Devin Wittmayer
1 sibling, 1 reply; 10+ messages in thread
From: Bitterblue Smith @ 2026-05-11 18:14 UTC (permalink / raw)
To: Devin Wittmayer, linux-wireless; +Cc: pkshih, linux-kernel
On 11/05/2026 19:08, Devin Wittmayer wrote:
> From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>
> The Realtek wifi 6/7 devices which support USB 3 are weird: when first
> plugged in, they pretend to be USB 2. The driver needs to send some
> commands to the device, which make it disappear and come back as a
> USB 3 device.
>
> Implement the required commands in rtw89.
>
> When a USB 3 device is plugged into a USB 2 port, rtw89 will try to
> switch it to USB 3 mode only once. The device will disappear and come
> back still in USB 2 mode, of course.
>
> Some people experience heavy interference in the 2.4 GHz band in
> USB 3 mode, so add a module parameter switch_usb_mode with the
> default value 1 to let people disable the switching.
>
> Tested with RTL8832BU and RTL8832CU.
>
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> Signed-off-by: Devin Wittmayer <lucid_duck@justthetip.ca>
> Tested-by: Devin Wittmayer <lucid_duck@justthetip.ca>
Are you quite sure you tested this?
> ---
> drivers/net/wireless/realtek/rtw89/reg.h | 4 +++
> drivers/net/wireless/realtek/rtw89/usb.c | 41 ++++++++++++++++++++++++
> 2 files changed, 45 insertions(+)
>
> diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
> index 42ffe83931a3..7d4c085d9fb2 100644
> --- a/drivers/net/wireless/realtek/rtw89/reg.h
> +++ b/drivers/net/wireless/realtek/rtw89/reg.h
> @@ -164,6 +164,10 @@
> #define R_AX_DBG_PORT_SEL 0x00C0
> #define B_AX_DEBUG_ST_MASK GENMASK(31, 0)
>
> +#define R_AX_PAD_CTRL2 0x00C4
> +#define U2SWITCHU3 0xB
> +#define USB_SWITCH_DELAY 0xF
> +
> #define R_AX_PMC_DBG_CTRL2 0x00CC
> #define B_AX_SYSON_DIS_PMCR_AX_WRMSK BIT(2)
>
> diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
> index 767a95f759b1..4fb25791d118 100644
> --- a/drivers/net/wireless/realtek/rtw89/usb.c
> +++ b/drivers/net/wireless/realtek/rtw89/usb.c
> @@ -9,6 +9,11 @@
> #include "txrx.h"
> #include "usb.h"
>
> +static bool rtw89_switch_usb_mode = true;
> +module_param_named(switch_usb_mode, rtw89_switch_usb_mode, bool, 0644);
> +MODULE_PARM_DESC(switch_usb_mode,
> + "Set to N to disable switching to USB 3 mode to avoid potential interference in the 2.4 GHz band (default: Y)");
> +
> static void rtw89_usb_read_port_complete(struct urb *urb);
>
> static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
> @@ -1027,6 +1032,35 @@ static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev,
> usb_set_intfdata(intf, NULL);
> }
>
> +static int rtw89_usb_switch_mode(struct rtw89_dev *rtwdev)
> +{
> + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
> +
> + if (!rtw89_switch_usb_mode)
> + return 0;
> +
> + /* No known USB 3 devices with this chip. */
> + if (rtwdev->chip->chip_id == RTL8851B)
> + return 0;
> +
> + if (rtwusb->udev->speed == USB_SPEED_SUPER)
> + return 0;
> +
> + rtw89_debug(rtwdev, RTW89_DBG_HCI, "%s: pad_ctrl2: %#x %#x\n",
> + __func__,
> + rtw89_read8(rtwdev, R_AX_PAD_CTRL2 + 1),
> + rtw89_read8(rtwdev, R_AX_PAD_CTRL2 + 2));
> +
> + /* Already tried to switch but it's a USB 2 port. */
> + if (rtw89_read8(rtwdev, R_AX_PAD_CTRL2 + 1) == USB_SWITCH_DELAY)
> + return 0;
> +
> + rtw89_write8(rtwdev, R_AX_PAD_CTRL2 + 1, USB_SWITCH_DELAY);
> + rtw89_write8(rtwdev, R_AX_PAD_CTRL2 + 2, U2SWITCHU3);
> +
> + return 1;
> +}
> +
> int rtw89_usb_probe(struct usb_interface *intf,
> const struct usb_device_id *id)
> {
> @@ -1059,6 +1093,13 @@ int rtw89_usb_probe(struct usb_interface *intf,
> goto err_free_hw;
> }
>
> + ret = rtw89_usb_switch_mode(rtwdev);
> + if (ret) {
> + /* Not a fail, but we do need to skip rtw89_core_register. */
> + ret = 0;
> + goto err_intf_deinit;
> + }
> +
> if (rtwusb->udev->speed == USB_SPEED_SUPER)
> rtwdev->hci.dle_type = RTW89_HCI_DLE_TYPE_USB3;
> else
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH rtw-next v2 1/1] wifi: rtw89: usb: Support switching to USB 3 mode
2026-05-11 18:14 ` Bitterblue Smith
@ 2026-05-11 20:03 ` Devin Wittmayer
0 siblings, 0 replies; 10+ messages in thread
From: Devin Wittmayer @ 2026-05-11 20:03 UTC (permalink / raw)
To: rtl8821cerfe2, linux-wireless
Cc: pkshih, johannes, linux-kernel, Devin Wittmayer
On Mon, 2026-05-11 at 21:14 +0300, Bitterblue Smith wrote:
> Are you quite sure you tested this?
Yes. Full test matrix is in the v2 cover letter (PATCH 0/1) of
this series:
- DWA-X1850 A1 / B1 (RTL8852AU)
- BrosTrend AX1L / AX4L (RTL8852BU)
- BrosTrend AX8L / EDUP AXE5400 (RTL8852CU)
Six adapters, x86_64 Tiger Lake xHCI + aarch64 BCM2712 / RP1 hosts.
60 plug-cycles + 30+ throughput cells captured 2026-04-11 to
2026-05-07. USB enumeration verified at SuperSpeed (5000 Mbps) on
every patched cell.
Per-cell raw evidence for the May 2026 expanded matrix (40 iperf3
JSON files per cell, byte-counter deltas, pre/post link state,
pre/post USB enumeration speeds, per-iteration timestamps) at:
https://github.com/Lucid-Duck/rtw89-usb3-gap/tree/main/evidence/may-2026-laptop
Per-adapter summaries:
https://github.com/Lucid-Duck/rtw89-usb3-gap/tree/main/adapters
If the Tested-by trailer should be annotated with the specific chip
list, I will add that when, and if, a v3 is needed.
Devin
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-05-11 20:04 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-08 5:44 [PATCH 0/1] wifi: rtw89: usb: Support switching to USB 3 mode Lucid Duck
2026-05-08 5:44 ` [PATCH 1/1] " Lucid Duck
2026-05-08 6:59 ` Zenm Chen
2026-05-11 10:55 ` [PATCH 0/1] " Bitterblue Smith
2026-05-11 16:08 ` [PATCH rtw-next v2 " Devin Wittmayer
2026-05-11 16:08 ` [PATCH rtw-next v2 1/1] " Devin Wittmayer
2026-05-11 17:26 ` Johannes Berg
2026-05-11 18:03 ` Devin Wittmayer
2026-05-11 18:14 ` Bitterblue Smith
2026-05-11 20:03 ` Devin Wittmayer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox