Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] wifi: ath11k: fix warning when unbinding
From: Jeff Johnson @ 2026-05-20 16:58 UTC (permalink / raw)
  To: jjohnson, Jose Ignacio Tornos Martinez
  Cc: linux-wireless, ath11k, linux-kernel, stable
In-Reply-To: <20260420110130.509670-1-jtornosm@redhat.com>


On Mon, 20 Apr 2026 13:01:29 +0200, Jose Ignacio Tornos Martinez wrote:
> If there is an error during some initialization related to firmware,
> the buffers dp->tx_ring[i].tx_status are released.
> However this is released again when the device is unbinded (ath11k_pci),
> and we get:
> WARNING: CPU: 0 PID: 6231 at mm/slub.c:4368 free_large_kmalloc+0x57/0x90
> Call Trace:
> free_large_kmalloc
> ath11k_dp_free
> ath11k_core_deinit
> ath11k_pci_remove
> ...
> 
> [...]

Applied, thanks!

[1/1] wifi: ath11k: fix warning when unbinding
      commit: 8b7a26b6681922a38cd5a7829ace61f8e54df9b7

Best regards,
-- 
Jeff Johnson <jeff.johnson@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH v6 00/16] firmware: qcom: Add OP-TEE PAS service support
From: Jeff Johnson @ 2026-05-20 16:27 UTC (permalink / raw)
  To: Sumit Garg, andersson
  Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
	netdev, linux-wireless, ath12k, linux-remoteproc, konradybcio,
	robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo, lumag,
	abhinav.kumar, jesszhan0024, marijn.suijten, airlied, simona,
	vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
	andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
	mathieu.poirier, trilokkumar.soni, mukesh.ojha, pavan.kondeti,
	jorge.ramirez, tonyh, vignesh.viswanathan, srinivas.kandagatla,
	amirreza.zarrabi, jens.wiklander, op-tee, apurupa, skare,
	linux-kernel, Sumit Garg
In-Reply-To: <20260518072856.22790-1-sumit.garg@kernel.org>

On 5/18/2026 12:28 AM, Sumit Garg wrote:
> From: Sumit Garg <sumit.garg@oss.qualcomm.com>
> 
> Qcom platforms has the legacy of using non-standard SCM calls
> splintered over the various kernel drivers. These SCM calls aren't
> compliant with the standard SMC calling conventions which is a
> prerequisite to enable migration to the FF-A specifications from Arm.
> 
> OP-TEE as an alternative trusted OS to Qualcomm TEE (QTEE) can't
> support these non-standard SCM calls. And even for newer architectures
> using S-EL2 with Hafnium support, QTEE won't be able to support SCM
> calls either with FF-A requirements coming in. And with both OP-TEE
> and QTEE drivers well integrated in the TEE subsystem, it makes further
> sense to reuse the TEE bus client drivers infrastructure.
> 
> The added benefit of TEE bus infrastructure is that there is support
> for discoverable/enumerable services. With that client drivers don't
> have to manually invoke a special SCM call to know the service status.
> 
> So enable the generic Peripheral Authentication Service (PAS) provided
> by the firmware. It acts as the common layer with different TZ
> backends plugged in whether it's an SCM implementation or a proper
> TEE bus based PAS service implementation.
> 
> The TEE PAS service ABI is designed to be extensible with additional API
> as PTA_QCOM_PAS_CAPABILITIES. This allows to accommodate any future
> extensions of the PAS service needed while still maintaining backwards
> compatibility.
> 
> Currently OP-TEE support is being added to provide the backend PAS
> service implementation which can be found as part of this PR [1].
> This implementation has been tested on Kodiak/RB3Gen2 board with lemans
> EVK board being the next target. In addition to that WIN/IPQ targets
> planning to use OP-TEE will use this service too. Surely the backwards
> compatibility is maintained and tested for SCM backend.
> 
> Note that kernel PAS service support while running in EL2 is at parity
> among OP-TEE vs QTEE. Especially the media (venus/iris) support depends
> on proper IOMMU support being worked out on the PAS client end.
> 
> Patch summary:
> - Patch #1: adds Kodiak EL2 overlay since boot stack with TF-A/OP-TEE
>   only allow UEFI and Linux to boot in EL2.
> - Patch #2: adds generic PAS service.
> - Patch #3: migrates SCM backend to generic PAS service.
> - Patch #4: adds TEE/OP-TEE backend for generic PAS service.
> - Patch #5-#14: migrates all client drivers to generic PAS service.
> - Patch #15: drops legacy PAS SCM exported APIs.
> 
> The patch-set is based on v7.1-rc4 tag and can be found in git tree here
> [2].
> 
> Merge strategy:
> 
> It is expected due to APIs dependency, the entire patch-set to go via
> the Qcom tree. All other subsystem maintainers, it will be great if I
> can get acks for the corresponding subsystem patches.
> 
> [1] https://github.com/OP-TEE/optee_os/pull/7721 (already merged)
> [2] https://git.kernel.org/pub/scm/linux/kernel/git/sumit.garg/linux.git/log/?h=qcom-pas-v6
> 
> ---
> Changes in v6:
> - Rebased to v7.1-rc4 tag.
> - Patch #14: fixed ret error print.
> - Add Kconfig descriptions for PAS symbols such that they are visible
>   in menuconfig to update.
> 
> Changes in v5:
> - Incorporated misc. comments from Mukesh.
> - Split up patch #11 into 2 to add an independent commit for passing
>   proper PAS ID to set_remote_state API.
> - Picked up tags.
> 
> Changes in v4:
> - Incorporate misc. comments on patch #4.
> - Picked up an ack for patch #10.
> - Clarify in cover letter about state of media support.
> 
> Changes in v3:
> - Incorporated some style and misc. comments for patch #2, #3 and #4.
> - Add QCOM_PAS Kconfig dependency for various subsystems.
> - Switch from pseudo TA to proper TA invoke commands.
> 
> Changes in v2:
> - Fixed kernel doc warnings.
> - Polish commit message and comments for patch #2.
> - Pass proper PAS ID in set_remote_state API for media firmware drivers.
> - Added Maintainer entry and dropped MODULE_AUTHOR.
> 
> Mukesh Ojha (1):
>   arm64: dts: qcom: kodiak: Add EL2 overlay
> 
> Sumit Garg (15):
>   firmware: qcom: Add a generic PAS service
>   firmware: qcom_scm: Migrate to generic PAS service
>   firmware: qcom: Add a PAS TEE service
>   remoteproc: qcom_q6v5_pas: Switch over to generic PAS TZ APIs
>   remoteproc: qcom_q6v5_mss: Switch to generic PAS TZ APIs
>   soc: qcom: mdtloader: Switch to generic PAS TZ APIs
>   remoteproc: qcom_wcnss: Switch to generic PAS TZ APIs
>   remoteproc: qcom: Select QCOM_PAS generic service
>   drm/msm: Switch to generic PAS TZ APIs
>   media: qcom: Switch to generic PAS TZ APIs
>   media: qcom: Pass proper PAS ID to set_remote_state API
>   net: ipa: Switch to generic PAS TZ APIs
>   wifi: ath12k: Switch to generic PAS TZ APIs
>   firmware: qcom_scm: Remove SCM PAS wrappers
>   MAINTAINERS: Add maintainer entry for Qualcomm PAS TZ service
> 
>  MAINTAINERS                                   |   9 +
>  arch/arm64/boot/dts/qcom/Makefile             |   2 +
>  arch/arm64/boot/dts/qcom/kodiak-el2.dtso      |  35 ++
>  drivers/firmware/qcom/Kconfig                 |  21 +-
>  drivers/firmware/qcom/Makefile                |   2 +
>  drivers/firmware/qcom/qcom_pas.c              | 291 +++++++++++
>  drivers/firmware/qcom/qcom_pas.h              |  50 ++
>  drivers/firmware/qcom/qcom_pas_tee.c          | 476 ++++++++++++++++++
>  drivers/firmware/qcom/qcom_scm.c              | 302 ++++-------
>  drivers/gpu/drm/msm/Kconfig                   |   1 +
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c         |   4 +-
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c       |  11 +-
>  drivers/media/platform/qcom/iris/Kconfig      |  25 +-
>  .../media/platform/qcom/iris/iris_firmware.c  |   9 +-
>  drivers/media/platform/qcom/venus/Kconfig     |   1 +
>  drivers/media/platform/qcom/venus/firmware.c  |  11 +-
>  drivers/net/ipa/Kconfig                       |   2 +-
>  drivers/net/ipa/ipa_main.c                    |  13 +-
>  drivers/net/wireless/ath/ath12k/Kconfig       |   2 +-
>  drivers/net/wireless/ath/ath12k/ahb.c         |  10 +-
>  drivers/remoteproc/Kconfig                    |   4 +-
>  drivers/remoteproc/qcom_q6v5_mss.c            |   5 +-
>  drivers/remoteproc/qcom_q6v5_pas.c            |  51 +-
>  drivers/remoteproc/qcom_wcnss.c               |  12 +-
>  drivers/soc/qcom/mdt_loader.c                 |  12 +-
>  include/linux/firmware/qcom/qcom_pas.h        |  43 ++
>  include/linux/firmware/qcom/qcom_scm.h        |  29 --
>  include/linux/soc/qcom/mdt_loader.h           |   6 +-
>  28 files changed, 1119 insertions(+), 320 deletions(-)
>  create mode 100644 arch/arm64/boot/dts/qcom/kodiak-el2.dtso
>  create mode 100644 drivers/firmware/qcom/qcom_pas.c
>  create mode 100644 drivers/firmware/qcom/qcom_pas.h
>  create mode 100644 drivers/firmware/qcom/qcom_pas_tee.c
>  create mode 100644 include/linux/firmware/qcom/qcom_pas.h
> 

In my automation I do bisection builds and it fails when I bisect.

At "remoteproc: qcom_q6v5_mss: Switch to generic PAS TZ APIs":

../drivers/remoteproc/qcom_q6v5_pas.c: In function 'qcom_pas_load':
../drivers/remoteproc/qcom_q6v5_pas.c:244:44: error: passing argument 1 of 'qcom_mdt_pas_load' from incompatible pointer type [-Wincompatible-pointer-types]
  244 |                 ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware,
      |                                         ~~~^~~~~~~~~~~~~
      |                                            |
      |                                            struct qcom_pas_context *
In file included from ../drivers/remoteproc/qcom_q6v5_pas.c:27:
../include/linux/soc/qcom/mdt_loader.h:23:52: note: expected 'struct qcom_scm_pas_context *' but argument is of type 'struct qcom_pas_context *'
   23 | int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw,
      |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
../drivers/remoteproc/qcom_q6v5_pas.c: In function 'qcom_pas_start':
../drivers/remoteproc/qcom_q6v5_pas.c:322:36: error: passing argument 1 of 'qcom_mdt_pas_load' from incompatible pointer type [-Wincompatible-pointer-types]
  322 |         ret = qcom_mdt_pas_load(pas->pas_ctx, pas->firmware, rproc->firmware,
      |                                 ~~~^~~~~~~~~
      |                                    |
      |                                    struct qcom_pas_context *
../include/linux/soc/qcom/mdt_loader.h:23:52: note: expected 'struct qcom_scm_pas_context *' but argument is of type 'struct qcom_pas_context *'
   23 | int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw,
      |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
make[5]: *** [../scripts/Makefile.build:289: drivers/remoteproc/qcom_q6v5_pas.o] Error 1


At "remoteproc: qcom_q6v5_pas: Switch over to generic PAS TZ APIs":

../drivers/remoteproc/qcom_q6v5_pas.c: In function 'qcom_pas_load':
../drivers/remoteproc/qcom_q6v5_pas.c:244:44: error: passing argument 1 of 'qcom_mdt_pas_load' from incompatible pointer type [-Wincompatible-pointer-types]
  244 |                 ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware,
      |                                         ~~~^~~~~~~~~~~~~
      |                                            |
      |                                            struct qcom_pas_context *
In file included from ../drivers/remoteproc/qcom_q6v5_pas.c:27:
../include/linux/soc/qcom/mdt_loader.h:23:52: note: expected 'struct qcom_scm_pas_context *' but argument is of type 'struct qcom_pas_context *'
   23 | int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw,
      |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
../drivers/remoteproc/qcom_q6v5_pas.c: In function 'qcom_pas_start':
../drivers/remoteproc/qcom_q6v5_pas.c:322:36: error: passing argument 1 of 'qcom_mdt_pas_load' from incompatible pointer type [-Wincompatible-pointer-types]
  322 |         ret = qcom_mdt_pas_load(pas->pas_ctx, pas->firmware, rproc->firmware,
      |                                 ~~~^~~~~~~~~
      |                                    |
      |                                    struct qcom_pas_context *
../include/linux/soc/qcom/mdt_loader.h:23:52: note: expected 'struct qcom_scm_pas_context *' but argument is of type 'struct qcom_pas_context *'
   23 | int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw,
      |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
make[5]: *** [../scripts/Makefile.build:289: drivers/remoteproc/qcom_q6v5_pas.o] Error 1


This is because the 5/16 patch depends upon changes in the 7/16 patch.

/jeff

^ permalink raw reply

* Re: [RESEND PATCH 1/2] genirq: export irq_can_set_affinity() for module drivers
From: Jeff Johnson @ 2026-05-20 16:00 UTC (permalink / raw)
  To: Hangtian Zhu, Thomas Gleixner, jjohnson
  Cc: linux-wireless, ath12k, linux-kernel
In-Reply-To: <b5870d83-6cc6-4b9e-bb4c-ee812d8b7727@oss.qualcomm.com>

On 5/19/2026 7:42 PM, Hangtian Zhu wrote:
> 
> 
> On 5/19/2026 22:30, Thomas Gleixner wrote:
>> eviewed-by: Thomas Gleixner <tglx@kernel.org>
>> On Tue, May 19 2026 at 09:16, Hangtian Zhu wrote:
>>> Export irq_can_set_affinity() for loadable drivers that need a runtime
>>> check for IRQ affinity capability.
>>>
>>> In hierarchical IRQ setups where the effective irqchip path lacks
>>> .irq_set_affinity(), drivers may need to switch to a fallback policy.
>>> Without this export, module drivers cannot use the core helper and have
>>> to open-code equivalent checks.
>>>
>>> Signed-off-by: Hangtian Zhu <hangtian.zhu@oss.qualcomm.com>
>> Assuming this goes through the wireless tree:
> yes, it's wireless tree.
>> Acked-by: Thomas Gleixner <tglx@kernel.org>
>>
>> If not, please let me know and I pick it up.
> 

Technically, it will first go into my ath tree, but yes, I'll pick it up.
Thanks for the Ack!

/jeff

^ permalink raw reply

* Re: [PATCH rtw-next v2] wifi: rtw88: Add more validation for the RX descriptor
From: Oleksandr Havrylov @ 2026-05-20 15:48 UTC (permalink / raw)
  To: Bitterblue Smith
  Cc: linux-wireless@vger.kernel.org, Ping-Ke Shih, Martin Blumenstingl,
	Fiona Klute, andrej.skvortzov, anarsoul, Zhen XIN
In-Reply-To: <5bfecba3-8a90-4e0f-9558-af5cd8a14975@gmail.com>

Tested-by: Oleksandr Havrylov <goainwo@gmail.com>

Tested on HP Notebook with RTL8821CE [10ec:c821] on openSUSE Slowroll,
running kernel 7.0.7-1-default.

Applied the v2 patch to the out-of-tree rtw88 driver. With the patch, the
driver successfully drops the corrupted RX frames without generating
mac80211 kernel warnings or causing connection instability.

Tested with a 10-minute continuous download stress test (peak speeds
around 200+ Mbit/s). Throughout the entire test, dmesg was continuously
monitored and showed zero VHT/descriptor warnings, zero connection
drops, and zero mac80211 errors.

^ permalink raw reply

* [PATCH rtw-next v4] wifi: rtw89: usb: Support switching to USB 3 mode
From: Bitterblue Smith @ 2026-05-20 14:44 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

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.

Add a new function rtw89_usb_write32_quiet() to avoid the warnings
when writing to R_{AX,BE}_PAD_CTRL2. Even though the write succeeds,
usb_control_msg() returns -EPROTO, probably because the USB device
disappears immediately. This results in some confusing warnings in
the kernel log.

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.

Tested with RTL8832AU, RTL8832BU, RTL8832CU, and RTL8912AU.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
v4:
 - Use a wrapper around rtw89_usb_vendorreq().
 - Add a warning message about 2.4 GHz interference.

v3:
 - Avoid crash when trying to switch.
 - Remove the unwanted module parameter.
 - Support RTL8922AU as well.
 - Use more bit names.
 - Hide the warnings when writing R_AX_PAD_CTRL2.
---
 drivers/net/wireless/realtek/rtw89/reg.h |  27 ++++++
 drivers/net/wireless/realtek/rtw89/usb.c | 104 ++++++++++++++++++++++-
 2 files changed, 128 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index c9bfb163c32e..76e107091d3b 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -164,6 +164,19 @@
 #define R_AX_DBG_PORT_SEL 0x00C0
 #define B_AX_DEBUG_ST_MASK GENMASK(31, 0)
 
+#define R_AX_PAD_CTRL2 0x00C4
+#define B_AX_FORCE_U3_CK BIT(23)
+#define B_AX_USB2_FORCE BIT(22)
+#define B_AX_USB3_FORCE BIT(21)
+#define B_AX_USB3_USB2_TRANSITION BIT(20)
+#define B_AX_USB23_SW_MODE_V1 GENMASK(19, 18)
+#define USB_MODE_U2 0x1
+#define USB_MODE_U3 0x2
+#define B_AX_NO_PDN_CHIPOFF_V1 BIT(17)
+#define B_AX_RSM_EN_V1 BIT(16)
+#define B_AX_MATCH_CNT GENMASK(15, 8)
+#define USB_SWITCH_DELAY 0xF
+
 #define R_AX_PMC_DBG_CTRL2 0x00CC
 #define B_AX_SYSON_DIS_PMCR_AX_WRMSK BIT(2)
 
@@ -4235,6 +4248,20 @@
 #define B_BE_TOGGLE BIT(31)
 #define B_BE_DATA_LINE_MASK GENMASK(30, 0)
 
+#define R_BE_PAD_CTRL2 0x00C4
+#define B_BE_USB23_SW_MODE BIT(31)
+#define B_BE_USB3_GEN_MODE BIT(30)
+#define B_BE_USB3_LANE_MODE BIT(29)
+#define B_BE_USB_AUTO_INSTALL_MASK BIT(28)
+#define B_BE_FORCE_CLK_U2 BIT(25)
+#define B_BE_FORCE_U2_CK BIT(24)
+#define B_BE_FORCE_U3_CK BIT(23)
+#define B_BE_USB2_FORCE BIT(22)
+#define B_BE_USB3_FORCE BIT(21)
+#define B_BE_NO_PDN_CHIPOFF_V1 BIT(17)
+#define B_BE_RSM_EN_V1 BIT(16)
+#define B_BE_MATCH_CNT GENMASK(15, 8)
+
 #define R_BE_PMC_DBG_CTRL2 0x00CC
 #define B_BE_EFUSE_BURN_GNT_MASK GENMASK(31, 24)
 #define B_BE_DIS_IOWRAP_TIMEOUT BIT(16)
diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
index c6d55e669776..198378018062 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.c
+++ b/drivers/net/wireless/realtek/rtw89/usb.c
@@ -11,8 +11,8 @@
 
 static void rtw89_usb_read_port_complete(struct urb *urb);
 
-static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
-				void *data, u16 len, u8 reqtype)
+static void __rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
+				  void *data, u16 len, u8 reqtype, bool warn)
 {
 	struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
 	struct usb_device *udev = rtwusb->udev;
@@ -52,7 +52,7 @@ static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
 
 		if (ret == -ESHUTDOWN || ret == -ENODEV)
 			set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
-		else if (ret < 0)
+		else if (ret < 0 && warn)
 			rtw89_warn(rtwdev,
 				   "usb %s%u 0x%x fail ret=%d value=0x%x attempt=%d\n",
 				   str_read_write(reqtype == RTW89_USB_VENQT_READ),
@@ -69,6 +69,12 @@ static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
 	}
 }
 
+static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
+				void *data, u16 len, u8 reqtype)
+{
+	__rtw89_usb_vendorreq(rtwdev, addr, data, len, reqtype, true);
+}
+
 static u32 rtw89_usb_read_cmac(struct rtw89_dev *rtwdev, u32 addr)
 {
 	u32 addr32, val32, shift;
@@ -157,6 +163,14 @@ static void rtw89_usb_ops_write32(struct rtw89_dev *rtwdev, u32 addr, u32 val)
 	rtw89_usb_vendorreq(rtwdev, addr, &data, 4, RTW89_USB_VENQT_WRITE);
 }
 
+static void rtw89_usb_write32_quiet(struct rtw89_dev *rtwdev, u32 addr, u32 val)
+{
+	__le32 data = cpu_to_le32(val);
+
+	__rtw89_usb_vendorreq(rtwdev, addr, &data, 4,
+			      RTW89_USB_VENQT_WRITE, false);
+}
+
 static u32
 rtw89_usb_ops_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev,
 					    u8 txch)
@@ -1059,6 +1073,83 @@ static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev,
 	usb_set_intfdata(intf, NULL);
 }
 
+static int rtw89_usb_switch_mode_ax(struct rtw89_dev *rtwdev)
+{
+	u32 pad_ctrl2;
+
+	/* No known USB 3 devices with this chip. */
+	if (rtwdev->chip->chip_id == RTL8851B)
+		return 0;
+
+	pad_ctrl2 = rtw89_usb_ops_read32(rtwdev, R_AX_PAD_CTRL2);
+
+	rtw89_debug(rtwdev, RTW89_DBG_HCI, "%s: pad_ctrl2: %#x\n",
+		    __func__, pad_ctrl2);
+
+	/* Already tried to switch but it's a USB 2 port. */
+	if (u32_get_bits(pad_ctrl2, B_AX_MATCH_CNT) == USB_SWITCH_DELAY)
+		return 0;
+
+	/* Add delay to prevent some platforms would not detect USB switch */
+	u32p_replace_bits(&pad_ctrl2, USB_SWITCH_DELAY, B_AX_MATCH_CNT);
+
+	pad_ctrl2 &= ~(B_AX_FORCE_U3_CK | B_AX_USB2_FORCE |
+		       B_AX_USB3_FORCE | B_AX_USB3_USB2_TRANSITION);
+
+	u32p_replace_bits(&pad_ctrl2, USB_MODE_U3, B_AX_USB23_SW_MODE_V1);
+
+	pad_ctrl2 |= B_AX_NO_PDN_CHIPOFF_V1 | B_AX_RSM_EN_V1;
+
+	rtw89_usb_write32_quiet(rtwdev, R_AX_PAD_CTRL2, pad_ctrl2);
+
+	return 1;
+}
+
+static int rtw89_usb_switch_mode_be(struct rtw89_dev *rtwdev)
+{
+	u32 pad_ctrl2;
+
+	pad_ctrl2 = rtw89_usb_ops_read32(rtwdev, R_BE_PAD_CTRL2);
+
+	rtw89_debug(rtwdev, RTW89_DBG_HCI, "%s: pad_ctrl2: %#x\n",
+		    __func__, pad_ctrl2);
+
+	/* Already tried to switch but it's a USB 2 port. */
+	if (u32_get_bits(pad_ctrl2, B_BE_MATCH_CNT) == USB_SWITCH_DELAY)
+		return 0;
+
+	/* Add delay to prevent some platforms would not detect USB switch */
+	u32p_replace_bits(&pad_ctrl2, USB_SWITCH_DELAY, B_BE_MATCH_CNT);
+
+	pad_ctrl2 |= B_BE_RSM_EN_V1 | B_BE_NO_PDN_CHIPOFF_V1 |
+		     B_BE_USB_AUTO_INSTALL_MASK | B_BE_USB23_SW_MODE;
+
+	pad_ctrl2 &= ~(B_BE_USB3_FORCE | B_BE_USB2_FORCE |
+		       B_BE_FORCE_U3_CK | B_BE_FORCE_U2_CK |
+		       B_BE_FORCE_CLK_U2 | B_BE_USB3_GEN_MODE |
+		       B_BE_USB3_LANE_MODE);
+
+	rtw89_usb_write32_quiet(rtwdev, R_BE_PAD_CTRL2, pad_ctrl2);
+
+	return 1;
+}
+
+static int rtw89_usb_switch_mode(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
+
+	if (rtwusb->udev->speed == USB_SPEED_SUPER) {
+		rtw89_info(rtwdev,
+			   "2.4 GHz performance may be better in a USB 2 port\n");
+		return 0;
+	}
+
+	if (rtwdev->chip->chip_gen == RTW89_CHIP_AX)
+		return rtw89_usb_switch_mode_ax(rtwdev);
+
+	return rtw89_usb_switch_mode_be(rtwdev);
+}
+
 int rtw89_usb_probe(struct usb_interface *intf,
 		    const struct usb_device_id *id)
 {
@@ -1091,6 +1182,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.54.0


^ permalink raw reply related

* [PATCH rtw-next v2] wifi: rtw88: Add more validation for the RX descriptor
From: Bitterblue Smith @ 2026-05-20 14:14 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org
  Cc: Ping-Ke Shih, LB F, Martin Blumenstingl, Fiona Klute,
	andrej.skvortzov, anarsoul, Zhen XIN

Some RTL8821CE cards can return frames with corrupted RX descriptor,
causing warnings and crashes if they are passed to the upper layers.

The PHY status size field is 4 bits wide, but in rtw88 its value should
only be 0 or 4. Checking this catches most of the corrupt frames.

If a PHY status is present, the PHY status size should not be 0.

The frame size should not be less than or equal to 4 and should not
exceed 11454.

The rate should not exceed 4SS MCS9.

Discard the frame if any of these checks fail.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221286
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
v2:
 - Also drop frames with invalid rate.
---
 drivers/net/wireless/realtek/rtw88/pci.c  | 16 +++++++-----
 drivers/net/wireless/realtek/rtw88/rx.c   | 31 +++++++++++++++--------
 drivers/net/wireless/realtek/rtw88/rx.h   |  6 ++---
 drivers/net/wireless/realtek/rtw88/sdio.c |  8 +++++-
 drivers/net/wireless/realtek/rtw88/usb.c  |  9 ++++---
 5 files changed, 47 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index c2bf44e880cf..a30467228912 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -1042,20 +1042,21 @@ static int rtw_pci_get_hw_rx_ring_nr(struct rtw_dev *rtwdev,
 static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
 			   u8 hw_queue, u32 limit)
 {
+	struct rtw_pci_rx_ring *ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU];
 	const struct rtw_chip_info *chip = rtwdev->chip;
 	struct napi_struct *napi = &rtwpci->napi;
-	struct rtw_pci_rx_ring *ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU];
-	struct rtw_rx_pkt_stat pkt_stat;
+	u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
+	u32 buf_desc_sz = chip->rx_buf_desc_sz;
 	struct ieee80211_rx_status rx_status;
+	struct rtw_rx_pkt_stat pkt_stat;
 	struct sk_buff *skb, *new;
 	u32 cur_rp = ring->r.rp;
 	u32 count, rx_done = 0;
 	u32 pkt_offset;
-	u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
-	u32 buf_desc_sz = chip->rx_buf_desc_sz;
+	dma_addr_t dma;
 	u32 new_len;
 	u8 *rx_desc;
-	dma_addr_t dma;
+	int ret;
 
 	count = rtw_pci_get_hw_rx_ring_nr(rtwdev, rtwpci);
 	count = min(count, limit);
@@ -1067,7 +1068,10 @@ static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
 		dma_sync_single_for_cpu(rtwdev->dev, dma, RTK_PCI_RX_BUF_SIZE,
 					DMA_FROM_DEVICE);
 		rx_desc = skb->data;
-		rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
+		ret = rtw_rx_query_rx_desc(rtwdev, rx_desc,
+					   &pkt_stat, &rx_status);
+		if (ret)
+			goto next_rp;
 
 		/* offset from rx_desc to payload */
 		pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c
index d9e11343d498..01fd299abb7f 100644
--- a/drivers/net/wireless/realtek/rtw88/rx.c
+++ b/drivers/net/wireless/realtek/rtw88/rx.c
@@ -3,6 +3,7 @@
  */
 
 #include "main.h"
+#include "mac.h"
 #include "rx.h"
 #include "ps.h"
 #include "debug.h"
@@ -261,9 +262,9 @@ static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
 	}
 }
 
-void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
-			  struct rtw_rx_pkt_stat *pkt_stat,
-			  struct ieee80211_rx_status *rx_status)
+int rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
+			 struct rtw_rx_pkt_stat *pkt_stat,
+			 struct ieee80211_rx_status *rx_status)
 {
 	u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
 	struct rtw_rx_desc *rx_desc = rx_desc8;
@@ -295,20 +296,28 @@ void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
 
 	pkt_stat->tsf_low = le32_get_bits(rx_desc->w5, RTW_RX_DESC_W5_TSFL);
 
-	if (unlikely(pkt_stat->rate >= DESC_RATE_MAX)) {
-		rtw_dbg(rtwdev, RTW_DBG_UNEXP,
-			"unexpected RX rate=0x%x\n", pkt_stat->rate);
+	if (unlikely(pkt_stat->rate >= DESC_RATE_MAX))
+		return -EINVAL;
 
-		pkt_stat->rate = DESC_RATE1M;
-		pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
-	}
+	if (unlikely(pkt_stat->drv_info_sz &&
+		     pkt_stat->drv_info_sz != PHY_STATUS_SIZE))
+		return -EINVAL;
+
+	if (unlikely(pkt_stat->phy_status && !pkt_stat->drv_info_sz))
+		return -EINVAL;
+
+	if (unlikely(pkt_stat->pkt_len > IEEE80211_MAX_MPDU_LEN_VHT_11454))
+		return -EINVAL;
 
 	/* drv_info_sz is in unit of 8-bytes */
 	pkt_stat->drv_info_sz *= 8;
 
 	/* c2h cmd pkt's rx/phy status is not interested */
 	if (pkt_stat->is_c2h)
-		return;
+		return 0;
+
+	if (unlikely(pkt_stat->pkt_len <= FCS_LEN))
+		return -EINVAL;
 
 	phy_status = rx_desc8 + desc_sz + pkt_stat->shift;
 	hdr = phy_status + pkt_stat->drv_info_sz;
@@ -318,5 +327,7 @@ void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
 		rtwdev->chip->ops->query_phy_status(rtwdev, phy_status, pkt_stat);
 
 	rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status);
+
+	return 0;
 }
 EXPORT_SYMBOL(rtw_rx_query_rx_desc);
diff --git a/drivers/net/wireless/realtek/rtw88/rx.h b/drivers/net/wireless/realtek/rtw88/rx.h
index 6b7dee245c0a..74359f641c76 100644
--- a/drivers/net/wireless/realtek/rtw88/rx.h
+++ b/drivers/net/wireless/realtek/rtw88/rx.h
@@ -45,9 +45,9 @@ struct rtw_rx_desc {
 
 void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
 		  struct sk_buff *skb);
-void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
-			  struct rtw_rx_pkt_stat *pkt_stat,
-			  struct ieee80211_rx_status *rx_status);
+int rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
+			 struct rtw_rx_pkt_stat *pkt_stat,
+			 struct ieee80211_rx_status *rx_status);
 void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
 				struct ieee80211_rx_status *rx_status,
 				struct rtw_rx_pkt_stat *pkt_stat);
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 1318e94f8524..5b40d74b16ee 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -995,7 +995,13 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len)
 
 	while (true) {
 		rx_desc = skb->data;
-		rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
+		ret = rtw_rx_query_rx_desc(rtwdev, rx_desc,
+					   &pkt_stat, &rx_status);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+			return;
+		}
+
 		pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
 			     pkt_stat.shift;
 
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 718940ebba31..6dd8ffedab9a 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -610,8 +610,8 @@ static void rtw_usb_rx_handler(struct work_struct *work)
 	u32 max_skb_len = pkt_desc_sz + PHY_STATUS_SIZE * 8 +
 			  IEEE80211_MAX_MPDU_LEN_VHT_11454;
 	u32 pkt_offset, next_pkt, skb_len;
+	int limit, ret;
 	u8 *rx_desc;
-	int limit;
 
 	for (limit = 0; limit < 200; limit++) {
 		rx_skb = skb_dequeue(&rtwusb->rx_queue);
@@ -627,8 +627,11 @@ static void rtw_usb_rx_handler(struct work_struct *work)
 		rx_desc = rx_skb->data;
 
 		do {
-			rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat,
-					     &rx_status);
+			ret = rtw_rx_query_rx_desc(rtwdev, rx_desc,
+						   &pkt_stat, &rx_status);
+			if (ret)
+				break;
+
 			pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
 				     pkt_stat.shift;
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH rtw-next 7/7] wifi: rtw89: 8922d: configure TX shape settings
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
  To: linux-wireless; +Cc: kevin_yang
In-Reply-To: <20260520123823.1792954-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

By default, BB enables triangular spectrum by a series of register
settings. According to band and regulation, RF parameters determine whether
TX shape needs to be restricted or not. So now, clear the corresponding
settings if it has no need to do.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/reg.h      |  4 ++
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 61 +++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index c0279e9e9bed..b704d3251e97 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -10622,6 +10622,8 @@
 #define R_RFSI_CT_OPT_0_BE4 0x11A94
 #define R_RFSI_CT_OPT_8_BE4 0x11A98
 #define R_QAM_COMP_TH0_BE4 0x11A9C
+#define B_QAM_COMP_TH_TRIANGULAR_L GENMASK(11, 10)
+#define B_QAM_COMP_TH_TRIANGULAR_H GENMASK(27, 26)
 #define R_QAM_COMP_TH1_BE4 0x11AA0
 #define R_QAM_COMP_TH2_BE4 0x11AA4
 #define R_QAM_COMP_TH3_BE4 0x11AA8
@@ -10645,6 +10647,8 @@
 #define B_QAM_COMP_TH6_2L GENMASK(9, 5)
 #define B_QAM_COMP_TH6_2M GENMASK(19, 15)
 #define R_OW_VAL_0_BE4 0x11AAC
+#define B_OW_VAL_TRIANGULAR_L GENMASK(11, 10)
+#define B_OW_VAL_TRIANGULAR_H GENMASK(27, 26)
 #define R_OW_VAL_1_BE4 0x11AB0
 #define R_OW_VAL_2_BE4 0x11AB4
 #define R_OW_VAL_3_BE4 0x11AB8
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 18af9211c2df..c38a38856398 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2680,6 +2680,66 @@ static void rtw8922d_set_txpwr_ref(struct rtw89_dev *rtwdev,
 				     B_BE_PWR_REF_CTRL_CCK, ref_cck);
 }
 
+static void rtw8922d_set_tx_shape(struct rtw89_dev *rtwdev,
+				  const struct rtw89_chan *chan,
+				  enum rtw89_phy_idx phy_idx)
+{
+	const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+	const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
+	const struct rtw89_tx_shape *tx_shape = &rfe_parms->tx_shape;
+	u8 tx_shape_idx;
+	u8 band, regd;
+	const u16 *th;
+
+	band = chan->band_type;
+	regd = rtw89_regd_get(rtwdev, band);
+	tx_shape_idx = (*tx_shape->lmt)[band][RTW89_RS_OFDM][regd];
+
+	if (tx_shape_idx == 0)
+		goto disable;
+
+	th = d->bands[chan->rfsi_band].qam_comp_th0;
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKLWORD, th[0], phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKHWORD, th[1], phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKLWORD, th[2], phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKHWORD, th[3], phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKLWORD, th[4], phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKHWORD, th[5], phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKLWORD, th[6], phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKHWORD, th[7], phy_idx);
+
+	th = d->bands[chan->rfsi_band].qam_comp_ow;
+	rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKLWORD, th[0], phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKHWORD, th[1], phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKLWORD, th[2], phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKHWORD, th[3], phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKLWORD, th[4], phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKHWORD, th[5], phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKLWORD, th[6], phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKHWORD, th[7], phy_idx);
+
+	return;
+
+disable:
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, B_QAM_COMP_TH_TRIANGULAR_L, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, B_QAM_COMP_TH_TRIANGULAR_H, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, B_QAM_COMP_TH_TRIANGULAR_L, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, B_QAM_COMP_TH_TRIANGULAR_H, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, B_QAM_COMP_TH_TRIANGULAR_L, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, B_QAM_COMP_TH_TRIANGULAR_H, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, B_QAM_COMP_TH_TRIANGULAR_L, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, B_QAM_COMP_TH_TRIANGULAR_H, 0, phy_idx);
+
+	rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, B_OW_VAL_TRIANGULAR_L, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, B_OW_VAL_TRIANGULAR_H, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, B_OW_VAL_TRIANGULAR_L, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, B_OW_VAL_TRIANGULAR_H, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, B_OW_VAL_TRIANGULAR_L, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, B_OW_VAL_TRIANGULAR_H, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, B_OW_VAL_TRIANGULAR_L, 0, phy_idx);
+	rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, B_OW_VAL_TRIANGULAR_H, 0, phy_idx);
+}
+
 static void rtw8922d_set_txpwr_sar_diff(struct rtw89_dev *rtwdev,
 					const struct rtw89_chan *chan,
 					enum rtw89_phy_idx phy_idx)
@@ -2711,6 +2771,7 @@ static void rtw8922d_set_txpwr(struct rtw89_dev *rtwdev,
 {
 	rtw89_phy_set_txpwr_byrate(rtwdev, chan, phy_idx);
 	rtw89_phy_set_txpwr_offset(rtwdev, chan, phy_idx);
+	rtw8922d_set_tx_shape(rtwdev, chan, phy_idx);
 	rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx);
 	rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
 	rtw8922d_set_txpwr_ref(rtwdev, chan, phy_idx);
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 6/7] wifi: rtw89: debug: show large MRU in txpwr_table dbgfs
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
  To: linux-wireless; +Cc: kevin_yang
In-Reply-To: <20260520123823.1792954-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

Read and print the CR settings of large MRU.
For now, only RTL8922D_CID7090 support it.

For example,

[TX power limit_large_mru]
RU484_242 1TX     	-  IDX_0   IDX_1   IDX_2   IDX_3 	|  17,   0,   0,   0,	dBm
RU484_242 2TX     	-  IDX_0   IDX_1   IDX_2   IDX_3 	|  16,   0,   0,   0,	dBm
RU996_484 1TX     	-  IDX_0   IDX_1 	|   0,   0,		dBm
RU996_484 2TX     	-  IDX_0   IDX_1 	|   0,   0,		dBm
RU996_484_242 1TX 	-  IDX_0   IDX_1 	|   0,   0,		dBm
RU996_484_242 2TX 	-  IDX_0   IDX_1 	|   0,   0,		dBm

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/debug.c | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 8ee800c76cfe..eb9106932187 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -767,6 +767,45 @@ static const struct txpwr_map __txpwr_map_lmt_ru_be = {
 	.addr_to_1ss = 0, /* not support */
 };
 
+static const struct txpwr_ent __txpwr_ent_lmt_ru484_242_be[] = {
+	__GEN_TXPWR_ENT4("RU484_242 1TX     ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 "),
+	__GEN_TXPWR_ENT4("RU484_242 2TX     ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 "),
+};
+
+static const struct txpwr_map __txpwr_map_lmt_ru484_242_be = {
+	.ent = __txpwr_ent_lmt_ru484_242_be,
+	.size = ARRAY_SIZE(__txpwr_ent_lmt_ru484_242_be),
+	.addr_from = R_BE_TXAGC_MAX_1TX_RU484_242_0,
+	.addr_to = R_BE_TXAGC_MAX_1TX_RU484_242_0 + 4,
+	.addr_to_1ss = 0, /* not support */
+};
+
+static const struct txpwr_ent __txpwr_ent_lmt_ru996_484_be[] = {
+	__GEN_TXPWR_ENT2("RU996_484 1TX     ", "IDX_0 ", "IDX_1 "),
+	__GEN_TXPWR_ENT2("RU996_484 2TX     ", "IDX_0 ", "IDX_1 "),
+};
+
+static const struct txpwr_map __txpwr_map_lmt_ru996_484_be = {
+	.ent = __txpwr_ent_lmt_ru996_484_be,
+	.size = ARRAY_SIZE(__txpwr_ent_lmt_ru996_484_be),
+	.addr_from = R_BE_TXAGC_MAX_1TX_RU996_484_0,
+	.addr_to = R_BE_TXAGC_MAX_1TX_RU996_484_0,
+	.addr_to_1ss = 0, /* not support */
+};
+
+static const struct txpwr_ent __txpwr_ent_lmt_ru996_484_242_be[] = {
+	__GEN_TXPWR_ENT2("RU996_484_242 1TX ", "IDX_0 ", "IDX_1 "),
+	__GEN_TXPWR_ENT2("RU996_484_242 2TX ", "IDX_0 ", "IDX_1 "),
+};
+
+static const struct txpwr_map __txpwr_map_lmt_ru996_484_242_be = {
+	.ent = __txpwr_ent_lmt_ru996_484_242_be,
+	.size = ARRAY_SIZE(__txpwr_ent_lmt_ru996_484_242_be),
+	.addr_from = R_BE_TXAGC_MAX_1TX_RU996_484_242_0,
+	.addr_to = R_BE_TXAGC_MAX_1TX_RU996_484_242_0,
+	.addr_to_1ss = 0, /* not support */
+};
+
 static unsigned int
 __print_txpwr_ent(char *buf, size_t bufsz, const struct txpwr_ent *ent,
 		  const s8 *bufp, const unsigned int cur, unsigned int *ate)
@@ -882,6 +921,9 @@ struct dbgfs_txpwr_table {
 	const struct txpwr_map *byr;
 	const struct txpwr_map *lmt;
 	const struct txpwr_map *lmt_ru;
+	const struct txpwr_map *lmt_ru484_242;
+	const struct txpwr_map *lmt_ru996_484;
+	const struct txpwr_map *lmt_ru996_484_242;
 };
 
 static const struct dbgfs_txpwr_table dbgfs_txpwr_table_ax = {
@@ -894,6 +936,9 @@ static const struct dbgfs_txpwr_table dbgfs_txpwr_table_be = {
 	.byr = &__txpwr_map_byr_be,
 	.lmt = &__txpwr_map_lmt_be,
 	.lmt_ru = &__txpwr_map_lmt_ru_be,
+	.lmt_ru484_242 = &__txpwr_map_lmt_ru484_242_be,
+	.lmt_ru996_484 = &__txpwr_map_lmt_ru996_484_be,
+	.lmt_ru996_484_242 = &__txpwr_map_lmt_ru996_484_242_be,
 };
 
 static const struct dbgfs_txpwr_table *dbgfs_txpwr_tables[RTW89_CHIP_GEN_NUM] = {
@@ -934,6 +979,8 @@ ssize_t rtw89_debug_priv_txpwr_table_get(struct rtw89_dev *rtwdev,
 					 char *buf, size_t bufsz)
 {
 	enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
+	const struct rtw89_chip_info *chip = rtwdev->chip;
+	struct rtw89_hal *hal = &rtwdev->hal;
 	struct rtw89_sar_parm sar_parm = {};
 	const struct dbgfs_txpwr_table *tbl;
 	const struct rtw89_chan *chan;
@@ -979,6 +1026,35 @@ ssize_t rtw89_debug_priv_txpwr_table_get(struct rtw89_dev *rtwdev,
 		return n;
 	p += n;
 
+	switch (chip_gen) {
+	case RTW89_CHIP_AX:
+		goto out;
+	case RTW89_CHIP_BE:
+		if (!(chip->chip_id == RTL8922D && hal->cid == RTL8922D_CID7090))
+			goto out;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	p += scnprintf(p, end - p, "\n[TX power limit_large_mru]\n");
+
+	n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt_ru484_242);
+	if (n < 0)
+		return n;
+	p += n;
+
+	n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt_ru996_484);
+	if (n < 0)
+		return n;
+	p += n;
+
+	n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt_ru996_484_242);
+	if (n < 0)
+		return n;
+	p += n;
+
+out:
 	return p - buf;
 }
 
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 5/7] wifi: rtw89: Wi-Fi 7 configure TX power limit for large MRU
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
  To: linux-wireless; +Cc: kevin_yang
In-Reply-To: <20260520123823.1792954-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

Support of Large MRU (Multiple Resource Unit) starts from RTL8922D_CID7090,
i.e. RTL8922A and RTL8922D-VS variant do not support it. There are the new
corresponding control registers. So, configure them.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.h   |   3 +
 drivers/net/wireless/realtek/rtw89/phy.h    |  10 ++
 drivers/net/wireless/realtek/rtw89/phy_be.c | 163 ++++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/reg.h    |   9 ++
 4 files changed, 185 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 4666e3041ef3..17f9a61686b7 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -998,6 +998,9 @@ enum rtw89_ru_bandwidth {
 	RTW89_RU106 = 2,
 	RTW89_RU52_26 = 3,
 	RTW89_RU106_26 = 4,
+	RTW89_RU484_242 = 5,
+	RTW89_RU996_484 = 6,
+	RTW89_RU996_484_242 = 7,
 	RTW89_RU_NUM,
 };
 
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 5af66656d0b8..532232892831 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -568,6 +568,16 @@ struct rtw89_txpwr_limit_ru_be {
 	s8 ru106_26[RTW89_RU_SEC_NUM_BE];
 };
 
+#define RTW89_RU484_242_SEC_NUM_BE 4
+#define RTW89_RU996_484_SEC_NUM_BE 2
+#define RTW89_RU996_484_242_SEC_NUM_BE 2
+
+struct rtw89_txpwr_limit_large_mru_be {
+	s8 ru484_242[RTW89_NSS_NUM][RTW89_RU484_242_SEC_NUM_BE];
+	s8 ru996_484[RTW89_NSS_NUM][RTW89_RU996_484_SEC_NUM_BE];
+	s8 ru996_484_242[RTW89_NSS_NUM][RTW89_RU996_484_242_SEC_NUM_BE];
+};
+
 struct rtw89_phy_rfk_log_fmt {
 	const struct rtw89_fw_element_hdr *elm[RTW89_PHY_C2H_RFK_LOG_FUNC_NUM];
 };
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index d0a6dfdbfea7..99263355e2f1 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -1699,11 +1699,168 @@ static void rtw89_phy_fill_limit_ru_be(struct rtw89_dev *rtwdev,
 	}
 }
 
+static
+void rtw89_phy_fill_limit_ru484_242_be(struct rtw89_dev *rtwdev,
+				       s8 (*lmt)[RTW89_RU484_242_SEC_NUM_BE],
+				       u8 ntx, u8 band, u8 ch, u8 bw)
+{
+	switch (bw) {
+	case RTW89_CHANNEL_WIDTH_80:
+		(*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU484_242,
+							  ntx, ch);
+		break;
+	case RTW89_CHANNEL_WIDTH_160:
+		(*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU484_242,
+							  ntx, ch - 8);
+		(*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU484_242,
+							  ntx, ch + 8);
+		break;
+	case RTW89_CHANNEL_WIDTH_320:
+		(*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU484_242,
+							  ntx, ch - 24);
+		(*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU484_242,
+							  ntx, ch - 8);
+		(*lmt)[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU484_242,
+							  ntx, ch + 8);
+		(*lmt)[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU484_242,
+							  ntx, ch + 24);
+		break;
+	}
+}
+
+static
+void rtw89_phy_fill_limit_ru996_484_be(struct rtw89_dev *rtwdev,
+				       s8 (*lmt)[RTW89_RU996_484_SEC_NUM_BE],
+				       u8 ntx, u8 band, u8 ch, u8 bw)
+{
+	switch (bw) {
+	case RTW89_CHANNEL_WIDTH_160:
+		(*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU996_484,
+							  ntx, ch);
+		break;
+	case RTW89_CHANNEL_WIDTH_320:
+		(*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU996_484,
+							  ntx, ch - 16);
+		(*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU996_484,
+							  ntx, ch + 16);
+		break;
+	}
+}
+
+static
+void rtw89_phy_fill_limit_ru996_484_242_be(struct rtw89_dev *rtwdev,
+					   s8 (*lmt)[RTW89_RU996_484_242_SEC_NUM_BE],
+					   u8 ntx, u8 band, u8 ch, u8 bw)
+{
+	switch (bw) {
+	case RTW89_CHANNEL_WIDTH_160:
+		(*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU996_484_242,
+							  ntx, ch);
+		break;
+	case RTW89_CHANNEL_WIDTH_320:
+		(*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU996_484_242,
+							  ntx, ch - 16);
+		(*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+							  RTW89_RU996_484_242,
+							  ntx, ch + 16);
+		break;
+	}
+}
+
+static
+void rtw89_phy_fill_limit_large_mru_be(struct rtw89_dev *rtwdev,
+				       const struct rtw89_chan *chan,
+				       struct rtw89_txpwr_limit_large_mru_be *lmt,
+				       bool has_bf)
+{
+	u8 band = chan->band_type;
+	u8 ch = chan->channel;
+	u8 bw = chan->band_width;
+	int i;
+
+	memset(lmt, 0, sizeof(*lmt));
+
+	if (has_bf)
+		return;
+
+	for (i = 0; i <= RTW89_NSS_2; i++) {
+		rtw89_phy_fill_limit_ru484_242_be(rtwdev, &lmt->ru484_242[i],
+						  i, band, ch, bw);
+		rtw89_phy_fill_limit_ru996_484_be(rtwdev, &lmt->ru996_484[i],
+						  i, band, ch, bw);
+		rtw89_phy_fill_limit_ru996_484_242_be(rtwdev, &lmt->ru996_484_242[i],
+						      i, band, ch, bw);
+	}
+}
+
+static
+void rtw89_phy_conf_limit_large_mru_be(struct rtw89_dev *rtwdev,
+				       const struct rtw89_chan *chan,
+				       enum rtw89_phy_idx phy_idx,
+				       bool has_bf)
+{
+	struct rtw89_txpwr_limit_large_mru_be lmt_lmru;
+	u32 addr, val;
+
+	rtw89_phy_fill_limit_large_mru_be(rtwdev, chan, &lmt_lmru, has_bf);
+
+	addr = has_bf ? R_BE_TXAGC_MAX_1TX_BF_RU484_242_0 :
+			R_BE_TXAGC_MAX_1TX_RU484_242_0;
+
+	val = u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][0], GENMASK(7, 0)) |
+	      u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][1], GENMASK(15, 8)) |
+	      u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][2], GENMASK(23, 16)) |
+	      u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][3], GENMASK(31, 24));
+
+	rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
+
+	val = u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][0], GENMASK(7, 0)) |
+	      u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][1], GENMASK(15, 8)) |
+	      u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][2], GENMASK(23, 16)) |
+	      u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][3], GENMASK(31, 24));
+
+	rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr + 4, val);
+
+	addr = has_bf ? R_BE_TXAGC_MAX_1TX_BF_RU996_484_0 :
+			R_BE_TXAGC_MAX_1TX_RU996_484_0;
+
+	val = u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_1][0], GENMASK(7, 0)) |
+	      u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_1][1], GENMASK(15, 8)) |
+	      u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_2][0], GENMASK(23, 16)) |
+	      u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_2][1], GENMASK(31, 24));
+
+	rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
+
+	addr = has_bf ? R_BE_TXAGC_MAX_1TX_BF_RU996_484_242_0 :
+			R_BE_TXAGC_MAX_1TX_RU996_484_242_0;
+
+	val = u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_1][0], GENMASK(7, 0)) |
+	      u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_1][1], GENMASK(15, 8)) |
+	      u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_2][0], GENMASK(23, 16)) |
+	      u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_2][1], GENMASK(31, 24));
+
+	rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
+}
+
 static void rtw89_phy_set_txpwr_limit_ru_be(struct rtw89_dev *rtwdev,
 					    const struct rtw89_chan *chan,
 					    enum rtw89_phy_idx phy_idx)
 {
+	const struct rtw89_chip_info *chip = rtwdev->chip;
 	struct rtw89_txpwr_limit_ru_be lmt_ru;
+	struct rtw89_hal *hal = &rtwdev->hal;
 	const s8 *ptr;
 	u32 addr, val;
 	u8 i, j;
@@ -1730,6 +1887,12 @@ static void rtw89_phy_set_txpwr_limit_ru_be(struct rtw89_dev *rtwdev,
 			rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
 		}
 	}
+
+	if (!(chip->chip_id == RTL8922D && hal->cid == RTL8922D_CID7090))
+		return;
+
+	rtw89_phy_conf_limit_large_mru_be(rtwdev, chan, phy_idx, false);
+	rtw89_phy_conf_limit_large_mru_be(rtwdev, chan, phy_idx, true);
 }
 
 const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index c9bfb163c32e..c0279e9e9bed 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -8358,6 +8358,11 @@
 #define R_BE_PWR_LISTEN_PATH 0x11988
 #define B_BE_PWR_LISTEN_PATH_EN GENMASK(31, 28)
 
+#define R_BE_TXAGC_MAX_1TX_RU484_242_0 0x11990
+#define R_BE_TXAGC_MAX_1TX_RU996_484_0 0x119A4
+#define R_BE_TXAGC_MAX_1TX_RU996_484_242_0 0x119AC
+#define R_BE_TXAGC_MAX_1TX_BF_RU484_242_0 0x119DC
+
 #define R_BE_PWR_REF_CTRL 0x11A20
 #define B_BE_PWR_REF_CTRL_OFDM GENMASK(9, 1)
 #define B_BE_PWR_REF_CTRL_CCK GENMASK(18, 10)
@@ -8395,6 +8400,8 @@
 	 B_BE_PWR_FORCE_MACID_EN_VAL | \
 	 B_BE_PWR_FORCE_MACID_EN_ON)
 
+#define R_BE_TXAGC_MAX_1TX_BF_RU996_484_0 0x11A4C
+
 #define R_BE_PWR_REG_CTRL 0x11A50
 #define B_BE_PWR_BT_EN BIT(23)
 
@@ -8408,6 +8415,8 @@
 #define R_BE_PWR_TH 0x11A78
 #define R_BE_PWR_RSSI_TARGET_LMT 0x11A84
 
+#define R_BE_TXAGC_MAX_1TX_BF_RU996_484_242_0 0x11ADC
+
 #define R_BE_PWR_OFST_SW 0x11AE8
 #define B_BE_PWR_OFST_SW_DB GENMASK(27, 24)
 
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 4/7] wifi: rtw89: fw: load TX compensation element by RFE type
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
  To: linux-wireless; +Cc: kevin_yang
In-Reply-To: <20260520123823.1792954-1-pkshih@realtek.com>

Originally driver uses TX compensation element by AID, and now tables are
by RFE type. Add the logic accordingly.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/fw.c | 6 ++++++
 drivers/net/wireless/realtek/rtw89/fw.h | 5 +++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 5d0b3ba9a358..47649079d7b5 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -1423,12 +1423,18 @@ int rtw89_build_tx_comp_from_elm(struct rtw89_dev *rtwdev,
 				 const union rtw89_fw_element_arg arg)
 {
 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
+	struct rtw89_efuse *efuse = &rtwdev->efuse;
 	struct rtw89_hal *hal = &rtwdev->hal;
+	u8 rfe_type;
 	u16 aid;
 
 	aid = le16_to_cpu(elm->aid);
+	rfe_type = elm->u.tx_comp.rfe_type;
+
 	if (aid && aid != hal->aid)
 		return 1; /* ignore if aid not matched */
+	else if (rfe_type && rfe_type != efuse->rfe_type)
+		return 1; /* ignore if rfe_type not matched */
 	else if (elm_info->tx_comp)
 		return 1; /* ignore if an element is existing */
 
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index cde8fd34723b..20721d5209aa 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -4548,6 +4548,11 @@ struct rtw89_fw_element_hdr {
 			u8 rsvd[4];
 			u8 rules_and_msgs[];
 		} __packed diag_mac;
+		struct {
+			u8 rfe_type;
+			u8 priv[7];
+			u8 contents[];
+		} __packed tx_comp;
 		struct __rtw89_fw_txpwr_element txpwr;
 		struct __rtw89_fw_regd_element regd;
 	} __packed u;
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 3/7] wifi: rtw89: 8922d: support new digital power compensation format
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
  To: linux-wireless; +Cc: kevin_yang
In-Reply-To: <20260520123823.1792954-1-pkshih@realtek.com>

The new format shared the base set (7 elements). As there are total 40
sets, save 7 * 39 elements.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index af2df4adfa85..18af9211c2df 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2127,6 +2127,12 @@ static void rtw8922d_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
 			__le32 vals[DIGITAL_PWR_COMP_VALS_NUM];
 		} sets[2][RTW89_TX_COMP_BAND_NR][BB_PATH_NUM_8922D];
 	} *pwr_comp_v0;
+	const struct {
+		__le32 base[DIGITAL_PWR_COMP_BASE_NUM];
+		struct {
+			__le32 vals[DIGITAL_PWR_COMP_VALS_NUM];
+		} sets[2][RTW89_TX_COMP_BAND_NR][BB_PATH_NUM_8922D];
+	} *pwr_comp;
 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
 	const struct rtw89_fw_element_hdr *txcomp_elm = elm_info->tx_comp;
 	const __le32 (*comp_base)[DIGITAL_PWR_COMP_BASE_NUM];
@@ -2134,7 +2140,11 @@ static void rtw8922d_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
 	u32 addr, val;
 	u32 i;
 
-	if (sizeof(*pwr_comp_v0) == le32_to_cpu(txcomp_elm->size)) {
+	if (sizeof(*pwr_comp) == le32_to_cpu(txcomp_elm->size)) {
+		pwr_comp = (const void *)txcomp_elm->u.common.contents;
+		comp_base = &pwr_comp->base;
+		comp_vals = &pwr_comp->sets[nss][chan->tx_comp_band][path].vals;
+	} else if (sizeof(*pwr_comp_v0) == le32_to_cpu(txcomp_elm->size)) {
 		pwr_comp_v0 = (const void *)txcomp_elm->u.common.contents;
 		comp_base = &pwr_comp_v0->sets[nss][chan->tx_comp_band][path].base;
 		comp_vals = &pwr_comp_v0->sets[nss][chan->tx_comp_band][path].vals;
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 2/7] wifi: rtw89: 8922d: refactor digital power compensation to support new format
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
  To: linux-wireless; +Cc: kevin_yang
In-Reply-To: <20260520123823.1792954-1-pkshih@realtek.com>

Because base settings of digital power compensation can be shared across
all bands, the settings are divided into two parts -- base and individual
values per bands. Refactor the code to be reuse with new format.

No change logic at all.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 31 +++++++++++++------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index c6c37e25e4c8..af2df4adfa85 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2118,29 +2118,42 @@ static void rtw8922d_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
 					  enum rtw89_rf_path path,
 					  enum rtw89_phy_idx phy_idx)
 {
-#define DIGITAL_PWR_COMP_REG_NUM 22
+#define DIGITAL_PWR_COMP_BASE_NUM 7
+#define DIGITAL_PWR_COMP_VALS_NUM 15
 	static const u32 pw_comp_cr[2] = {R_RX_PATH0_TBL0_BE4, R_RX_PATH1_TBL0_BE4};
-	const __le32 (*pwr_comp_val)[2][RTW89_TX_COMP_BAND_NR]
-				    [BB_PATH_NUM_8922D][DIGITAL_PWR_COMP_REG_NUM];
+	const struct {
+		struct {
+			__le32 base[DIGITAL_PWR_COMP_BASE_NUM];
+			__le32 vals[DIGITAL_PWR_COMP_VALS_NUM];
+		} sets[2][RTW89_TX_COMP_BAND_NR][BB_PATH_NUM_8922D];
+	} *pwr_comp_v0;
 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
 	const struct rtw89_fw_element_hdr *txcomp_elm = elm_info->tx_comp;
-	const __le32 *digital_pwr_comp;
+	const __le32 (*comp_base)[DIGITAL_PWR_COMP_BASE_NUM];
+	const __le32 (*comp_vals)[DIGITAL_PWR_COMP_VALS_NUM];
 	u32 addr, val;
 	u32 i;
 
-	if (sizeof(*pwr_comp_val) != le32_to_cpu(txcomp_elm->size)) {
+	if (sizeof(*pwr_comp_v0) == le32_to_cpu(txcomp_elm->size)) {
+		pwr_comp_v0 = (const void *)txcomp_elm->u.common.contents;
+		comp_base = &pwr_comp_v0->sets[nss][chan->tx_comp_band][path].base;
+		comp_vals = &pwr_comp_v0->sets[nss][chan->tx_comp_band][path].vals;
+	} else {
 		rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
 			    "incorrect power comp size %d\n",
 			    le32_to_cpu(txcomp_elm->size));
 		return;
 	}
 
-	pwr_comp_val = (const void *)txcomp_elm->u.common.contents;
-	digital_pwr_comp = (*pwr_comp_val)[nss][chan->tx_comp_band][path];
 	addr = pw_comp_cr[path];
 
-	for (i = 0; i < DIGITAL_PWR_COMP_REG_NUM; i++, addr += 4) {
-		val = le32_to_cpu(digital_pwr_comp[i]);
+	for (i = 0; i < ARRAY_SIZE(*comp_base); i++, addr += 4) {
+		val = le32_to_cpu((*comp_base)[i]);
+		rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(*comp_vals); i++, addr += 4) {
+		val = le32_to_cpu((*comp_vals)[i]);
 		rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx);
 	}
 }
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 1/7] wifi: rtw89: fw: load TX power track element according to AID
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
  To: linux-wireless; +Cc: kevin_yang
In-Reply-To: <20260520123823.1792954-1-pkshih@realtek.com>

From: Zong-Zhe Yang <kevin_yang@realtek.com>

RF parameters has different TX power track table for different AID.
FW elements may include multiple TX power track tables for different
AID. So, load the corresponding one.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/fw.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index ff3914a16b81..5d0b3ba9a358 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -1209,12 +1209,17 @@ int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev,
 {
 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
 	const struct rtw89_chip_info *chip = rtwdev->chip;
+	struct rtw89_hal *hal = &rtwdev->hal;
+	u16 aid = le16_to_cpu(elm->aid);
 	u32 needed_bitmap = 0;
 	u32 offset = 0;
 	int subband;
 	u32 bitmap;
 	int type;
 
+	if (aid && aid != hal->aid)
+		return 1;
+
 	if (chip->support_bands & BIT(NL80211_BAND_6GHZ))
 		needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_6GHZ;
 	if (chip->support_bands & BIT(NL80211_BAND_5GHZ))
-- 
2.25.1


^ permalink raw reply related

* [PATCH rtw-next 0/7] wifi: rtw89: update firmware elements formats of power track, compensation and MRU
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
  To: linux-wireless; +Cc: kevin_yang

First patch is to load power track table according to chip AID.

Patches 2-4 are related to power compensation, which format is changed to
share common part for sub-tables corresponding to operating bands. And
change to load table by RFE type instead of AID.

Patches 5-7 are power table of MRU, which driver load it from file and
write to registers accordingly.

Ping-Ke Shih (3):
  wifi: rtw89: 8922d: refactor digital power compensation to support new
    format
  wifi: rtw89: 8922d: support new digital power compensation format
  wifi: rtw89: fw: load TX compensation element by RFE type

Zong-Zhe Yang (4):
  wifi: rtw89: fw: load TX power track element according to AID
  wifi: rtw89: Wi-Fi 7 configure TX power limit for large MRU
  wifi: rtw89: debug: show large MRU in txpwr_table dbgfs
  wifi: rtw89: 8922d: configure TX shape settings

 drivers/net/wireless/realtek/rtw89/core.h     |   3 +
 drivers/net/wireless/realtek/rtw89/debug.c    |  76 ++++++++
 drivers/net/wireless/realtek/rtw89/fw.c       |  11 ++
 drivers/net/wireless/realtek/rtw89/fw.h       |   5 +
 drivers/net/wireless/realtek/rtw89/phy.h      |  10 ++
 drivers/net/wireless/realtek/rtw89/phy_be.c   | 163 ++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/reg.h      |  13 ++
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 102 ++++++++++-
 8 files changed, 374 insertions(+), 9 deletions(-)


base-commit: 7076af642955693935e60bc94546d105fb0395ca
-- 
2.25.1


^ permalink raw reply

* Re: [RFC rtw-next 1/2] wifi: rtw89: usb: add hw_info sysfs attribute
From: Greg KH @ 2026-05-20 11:36 UTC (permalink / raw)
  To: Johnson Tsai
  Cc: Johannes Berg, Ping-Ke Shih, linux-wireless@vger.kernel.org,
	driver-core@lists.linux.dev, sabae@valvesoftware.com,
	Charles Lohr
In-Reply-To: <b8640de28c5e4a94a3c2bbc3a101c1fa@realtek.com>

On Wed, May 20, 2026 at 09:41:46AM +0000, Johnson Tsai wrote:
> 
> 
> On Tuesday, May 19, 2026 20:23, Greg KH <gregkh@linuxfoundation.org> wrote:
> > On Tue, May 19, 2026 at 02:11:32PM +0200, Johannes Berg wrote:
> > > Hi,
> > >
> > > > > Example usage from user-space:
> > > > >   $ cat /sys/bus/usb/devices/2-3.1.2:1.0/hw_info
> > > > >   SN: 36 42 00 01 23
> > > > >   UUID: aa ec 2b 7c 0a 55 47 27 8d e0 b3 0f eb cc bb aa
> > >
> > > Sysfs has a "one value per file" rule (soft rule according to the
> > > docs, but harder in practice, I believe), so seems if anything that
> > > should be two files. Maybe a UUID should also be formatted as such
> > > with %pU or similar.
> > 
> > That should be 2 separate sysfs files please.
> > 
> > And yes, use %pU.
> 
> The v2 patch will use separate `sn` and `uuid` attributes, with `uuid`
> formatted via `%pU`. We also removed the spaces in `sn` to provide a clean
> string.
> 
> Example usage from user-space:
>   $ cat /sys/bus/usb/devices/2-3.1.2:1.0/sn
>   3642000123
>   $ cat /sys/bus/usb/devices/2-3.1.2:1.0/uuid
>   aaec2b7c-0a55-4727-8de0-b30febccbbaa

Wait, no, you are putting attributes in the USB interface device, which
is NOT the device your driver is creating.  Don't do that, it makes for
massive confusion.

> > And be careful about exposing serial numbers to userspace, some systems
> > don't like normal users to read them so be sure to get the permissions correct.
> > We had to add some USB code for ALLOW_SERIAL_NUMBER to make it so that
> > systems can handle this if they want to.
> > 
> > And shouldn't this just be the USB serial number to start with?  Why is there a
> > different string here?  We already have a sysfs file for this value.
> 
> Regarding the serial number and permission design, these are requirements 
> from Valve, so we have CC'd them here to provide the background.
> 
> Hi Elliot and Charles, could you please help explain the requirements and use case here?

The USB serial number is already exported in sysfs, why export it again
under a different filename?  That's ripe for total confusion :(

Also, where does this random UUID come from?  That's not part of the USB
spec, is it?  Why is it not just a USB string attribute like the spec
says to use for stuff like this?

thanks,

greg k-h

^ permalink raw reply

* Re: Question: nl80211 testmode_dump and prepare_vendor_dump  continuation missing netns recheck
From: Johannes Berg @ 2026-05-20 11:30 UTC (permalink / raw)
  To: Xie Maoyi; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <TYZPR01MB67585C3E22F1E7EE1A801741DC042@TYZPR01MB6758.apcprd01.prod.exchangelabs.com>

Hi,

On Fri, 2026-05-15 at 15:40 +0000, Xie Maoyi wrote:
> Hi Johannes,
> 
> After your acceptance of 79240f3f6d76 ("wifi: nl80211: re-check
> wiphy netns in nl80211_prepare_wdev_dump() continuation"), I
> looked at the other dumpit callbacks in net/wireless/nl80211.c.
> Two sites read state from cb->args[] across continuations without
> a comparable net_eq() recheck.
> 
> Site 1: nl80211_testmode_dump().
> 
> The continuation branch resolves rdev via
> cfg80211_rdev_by_wiphy_idx() on cb->args[0]. It does not verify
> that wiphy_net matches sock_net(cb->skb->sk).
> 
> Site 2: nl80211_prepare_vendor_dump().
> 
> The continuation branch resolves wiphy via wiphy_idx_to_wiphy()
> on cb->args[0] and proceeds. Same gap. This helper is called by
> nl80211_vendor_cmd_dump, so a fix here covers that path too.
> 
> I notice one practical limit. No in-tree mainline driver currently
> registers .testmode_dump or wiphy_vendor_command.dumpit, so the
> paths are latent today. Out-of-tree drivers may register either.
> 
> I wanted to check with you before sending anything. If you read
> these as the same class of bug as 79240f3f6d76 and a short series
> mirroring that fix would be useful, I would be glad to put one
> together when it fits your queue, or to drop the thread if you
> prefer.

I'm really not worried about this class of bug in the first place since
hardly anyone ever uses network namespaces at least as far as I'm aware,
and vendor command implementations are indeed mostly out-of-tree, but
seems we might as well fix it.

johannes

^ permalink raw reply

* [PATCH AUTOSEL 7.0-5.10] wifi: nl80211: require CAP_NET_ADMIN over the target netns in SET_WIPHY_NETNS
From: Sasha Levin @ 2026-05-20 11:18 UTC (permalink / raw)
  To: patches, stable
  Cc: Maoyi Xie, Johannes Berg, Sasha Levin, johannes, linux-wireless,
	linux-kernel
In-Reply-To: <20260520111944.3424570-1-sashal@kernel.org>

From: Maoyi Xie <maoyi.xie@ntu.edu.sg>

[ Upstream commit 15994bb0cbb8fc4879da7552ddd08c1896261c39 ]

NL80211_CMD_SET_WIPHY_NETNS dispatches with GENL_UNS_ADMIN_PERM, which
verifies that the caller has CAP_NET_ADMIN for the source netns. It
doesn't verify that the caller has CAP_NET_ADMIN over the target netns
selected by NL80211_ATTR_NETNS_FD or NL80211_ATTR_PID.

This diverges from the convention enforced in
net/core/rtnetlink.c::rtnl_get_net_ns_capable():

    /* For now, the caller is required to have CAP_NET_ADMIN in
     * the user namespace owning the target net ns.
     */
    if (!sk_ns_capable(sk, net->user_ns, CAP_NET_ADMIN))
        return ERR_PTR(-EACCES);

A user with CAP_NET_ADMIN in their own user namespace can therefore
push a wiphy into an arbitrary netns (including init_net) over which
they have no privilege.

Mirror the rtnetlink convention by requiring CAP_NET_ADMIN in the
target netns before calling cfg80211_switch_netns().

Signed-off-by: Maoyi Xie <maoyi.xie@ntu.edu.sg>
Link: https://patch.msgid.link/20260506064854.2207105-2-maoyixie.tju@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase Walkthrough

### Phase 1: Commit Message Forensics
Record: `wifi: nl80211` subsystem; action verb `require`; intent is to
require `CAP_NET_ADMIN` over the target network namespace before
`NL80211_CMD_SET_WIPHY_NETNS` moves a wiphy.

Record: Tags in the provided commit message:
`Signed-off-by: Maoyi Xie <maoyi.xie@ntu.edu.sg>`, `Link: https://patch.
msgid.link/20260506064854.2207105-2-maoyixie.tju@gmail.com`, `Signed-
off-by: Johannes Berg <johannes.berg@intel.com>`. No `Fixes:`,
`Reported-by:`, `Tested-by:`, `Reviewed-by:`, or `Cc: stable` tag was
present in the provided message.

Record: The described bug is an authorization gap. `GENL_UNS_ADMIN_PERM`
verifies `CAP_NET_ADMIN` for the netlink socket/source netns, but
`NL80211_ATTR_NETNS_FD` / `NL80211_ATTR_PID` selects a target netns that
was not separately checked. The b4-fetched cover letter includes a
concrete reproducer with `mac80211_hwsim`: a caller privileged only in
its own user namespace can move a delegated wiphy back into `init_net`.

Record: This is not a hidden cleanup fix; it is an explicit
security/permission bug fix.

### Phase 2: Diff Analysis
Record: One file changed, `net/wireless/nl80211.c`, with 13 insertions
in `nl80211_wiphy_netns()`. Scope is a single-function surgical fix.

Record: Before: after resolving the target netns and checking
`IS_ERR(net)`, the function directly called `cfg80211_switch_netns()` if
the wiphy was not already in that netns. After: it first checks
`ns_capable(net->user_ns, CAP_NET_ADMIN)`, drops the netns reference
with `put_net(net)`, and returns `-EPERM` on failure.

Record: Bug category is security authorization / logic correctness. The
missing check allowed a source-netns-capable caller to affect a
different target netns without privilege there.

Record: Fix quality is high: small, localized, follows the verified
rtnetlink convention in `rtnl_get_net_ns_capable()`, and preserves
reference cleanup. Regression risk is low and limited to denying
previously accepted unauthorized cross-netns moves.

### Phase 3: Git History Investigation
Record: `git blame` on the current stable checkout blamed the function
body to a repository snapshot-style commit, so it was not useful for
introduction history. `git log v2.6.29..v2.6.32 -S...` found the
command/function introduced by `463d018323851` (`cfg80211: make aware of
net namespaces`), first contained in `v2.6.32-rc1`.

Record: No `Fixes:` tag is present, so there was no tagged commit to
follow.

Record: Recent local `net/wireless/nl80211.c` history showed unrelated
wireless fixes/conversions and no existing equivalent target-netns
capability fix.

Record: No local prior `Maoyi Xie` commits were found under
`net/wireless`. `MAINTAINERS` verifies Johannes Berg as maintainer for
`802.11 (including CFG80211/NL80211)`, and the patch was addressed to
Johannes on linux-wireless.

Record: No code dependency was found for this patch. It is patch 1/2 in
the submitted series; patch 2 is related namespace hardening, but patch
1 is standalone for the direct permission bypass.

### Phase 4: Mailing List And External Research
Record: No commit hash was provided and the exact subject was not found
in local `master`, `wireless-next`, `net-next`, or `fixes-next`, so `b4
dig -c <commit>` was not applicable. I used the provided message-id with
`b4 am`/`b4 mbox`.

Record: `b4 am` found `[PATCH v3 0/2] wifi: nl80211: tighten netns
handling in SET_WIPHY_NETNS and dump continuation`, including this patch
as `v3 1/2`. `b4 am -c` did not report a newer revision. Attempts to
fetch v1/v2 directly with `b4 -v 1/-v 2` did not find those revisions,
but the v3 cover records that patch 1 was unchanged since v1.

Record: The full mbox contained three messages: cover, patch 1, patch 2.
It did not contain reviewer reply messages, but the cover records
Johannes review feedback about trailers/comment wording and says no code
changes since v2.

Record: Original recipients were Johannes Berg, `linux-
wireless@vger.kernel.org`, and `linux-kernel@vger.kernel.org`. No stable
nomination or NAK was found in the fetched mbox. Lore WebFetch searches
were blocked by Anubis, so stable-list discussion could not be
independently verified through WebFetch.

### Phase 5: Code Semantic Analysis
Record: Modified function: `nl80211_wiphy_netns()`.

Record: Caller surface: the only direct reference is the generic-netlink
op for `NL80211_CMD_SET_WIPHY_NETNS`; `genl_family_rcv_msg()` checks
`GENL_UNS_ADMIN_PERM` against `net->user_ns`, then
`genl_family_rcv_msg_doit()` calls `ops->doit()`, reaching
`nl80211_wiphy_netns()` from userspace netlink.

Record: Key callees: `get_net_ns_by_pid()`, `get_net_ns_by_fd()`, new
`ns_capable(net->user_ns, CAP_NET_ADMIN)`, `cfg80211_switch_netns()`,
and `put_net()`. `cfg80211_switch_netns()` moves associated wireless
netdevs with `dev_change_net_namespace()` and updates `wiphy_net_set()`.

Record: Reachability is verified by the op table and by the b4 cover’s
PoC. A userspace caller can trigger the path by sending
`NL80211_CMD_SET_WIPHY_NETNS` with target PID or netns fd.

Record: Similar convention verified in `rtnl_get_net_ns_capable()`,
which checks target `net->user_ns` before using another netns.

### Phase 6: Stable Tree Analysis
Record: The vulnerable handler/op shape exists in `v5.4`, `v5.10`,
`v5.15`, `v6.1`, `v6.6`, `v6.12`, `v6.19`, and current `7.0.y`, with no
`ns_capable(net->user_ns, CAP_NET_ADMIN)` check in the handler.

Record: `v3.18` has `NL80211_CMD_SET_WIPHY_NETNS`, but uses
`GENL_ADMIN_PERM`, so the unprivileged-user-namespace aspect is not the
same there. For active modern stable trees, the issue is present.

Record: `git apply --check` of the fetched v3 mbox succeeds on the
current `7.0.y` checkout. Older stable trees have line offsets and minor
surrounding differences, but the same local hunk context exists at least
in `v5.4`; expected backport difficulty is clean or minor-context-only.

Record: No related local fix already present was found by subject/grep
searches.

### Phase 7: Subsystem Context
Record: Subsystem is cfg80211/nl80211 wireless configuration.
Criticality is IMPORTANT: it is not core-mm/VFS, but it is a userspace-
facing network configuration and permission boundary.

Record: The wireless subsystem is active in local history, with recent
cfg80211/nl80211-adjacent fixes.

### Phase 8: Impact And Risk
Record: Affected users are systems with cfg80211/nl80211, network
namespaces/user namespaces, and a `WIPHY_FLAG_NETNS_OK` wiphy. Verified
examples include `mac80211` and drivers setting the flag such as
`brcmfmac`, `mwifiex`, and `qtnfmac`.

Record: Trigger requires the caller to hold a movable wiphy in its own
netns and pass a target netns fd or pid. The b4 cover verifies this is
reachable from an unprivileged user namespace after legitimate admin
delegation using `mac80211_hwsim`.

Record: Failure mode is a security/namespace isolation violation:
unauthorized movement of a wiphy into a netns, including `init_net`,
where the caller lacks privilege. Severity is HIGH because it bypasses
kernel namespace permission boundaries.

Record: Benefit is high for stable users because it closes a concrete
privilege boundary bug. Risk is low: 13 lines, one function, no new API,
no data structure change, and only unauthorized operations change
behavior.

### Phase 9: Final Synthesis
Record: Evidence for backporting: real security/authorization bug,
concrete PoC in the submitted cover, reachable userspace netlink
command, vulnerable code present across modern stable trees, small
contained fix, and it mirrors an existing rtnetlink convention.

Record: Evidence against backporting: no `Fixes:`/stable tag, no fetched
reviewer reply carrying an explicit stable nomination, and the exact
applied commit hash was not present in local searched branches. These do
not outweigh the verified technical issue.

Record: Unresolved: I could not verify the final applied commit object
or run `b4 dig -c` because no commit hash was provided and local branch
searches did not find the subject. WebFetch to lore/stable was blocked
by Anubis. I did not run the runtime PoC or a kernel build.

Stable rules checklist:
1. Obviously correct and tested: yes by inspection; PoC result described
   in b4 cover, though not locally rerun.
2. Fixes a real bug affecting users: yes, verified missing target-netns
   authorization.
3. Important issue: yes, security/namespace permission bypass.
4. Small and contained: yes, one function, 13 added lines.
5. No new features or APIs: yes.
6. Can apply to stable: yes for current `7.0.y`; older active stable
   trees likely clean/minor context based on matching code.

Exception category: none. This is not a device ID/quirk/build/doc fix;
it is a security permission fix.

## Verification
- [Phase 1] Parsed provided subject/tags and b4-fetched patch/cover;
  found no `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, or
  stable tag.
- [Phase 2] Compared provided diff and b4 mbox patch; confirmed 13 lines
  added to `nl80211_wiphy_netns()`.
- [Phase 3] `git blame -L` was not useful due snapshot-style history;
  `git log v2.6.29..v2.6.32 -S...` found `463d018323851`, first
  contained in `v2.6.32-rc1`.
- [Phase 3] `git log --author='Maoyi Xie' -- net/wireless` found no
  local prior commits.
- [Phase 3] `MAINTAINERS` confirms Johannes Berg maintains `802.11
  (including CFG80211/NL80211)`.
- [Phase 4] `b4 am` found v3 2-patch series and the supplied patch
  message-id.
- [Phase 4] `b4 am -c` found no newer revision.
- [Phase 4] `b4 mbox` saved the full 3-message thread; no stable
  nomination or NAK was present there.
- [Phase 5] `rg` confirmed `nl80211_wiphy_netns()` is reached via the
  `NL80211_CMD_SET_WIPHY_NETNS` generic-netlink op.
- [Phase 5] Read `genetlink.c`; confirmed `GENL_UNS_ADMIN_PERM` checks
  `net->user_ns` before calling `ops->doit()`.
- [Phase 5] Read `cfg80211_switch_netns()`; confirmed it moves wireless
  netdevs and changes the wiphy netns.
- [Phase 6] Checked `v5.4`, `v5.10`, `v5.15`, `v6.1`, `v6.6`, `v6.12`,
  `v6.19`, and current `7.0.y`; all have the handler/op without the
  target `ns_capable()` check.
- [Phase 6] `git apply --check` of the b4 mbox succeeded on current
  `7.0.y`.
- [Phase 8] `rg WIPHY_FLAG_NETNS_OK` verified affected mac80211 and
  several wireless drivers expose movable wiphys.
- UNVERIFIED: exact final commit SHA and final applied-object metadata,
  because the subject was not found in local searched branches.
- UNVERIFIED: stable-list discussion via WebFetch, because lore WebFetch
  returned Anubis anti-bot pages.
- UNVERIFIED: local runtime PoC/build; not performed.

This should be backported to stable kernel trees that contain the
`GENL_UNS_ADMIN_PERM` version of `NL80211_CMD_SET_WIPHY_NETNS`,
especially active v5.4+ stable/LTS trees.

**YES**

 net/wireless/nl80211.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ce3121b1c3319..13c2943ad3e4b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -13568,6 +13568,19 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
 	if (IS_ERR(net))
 		return PTR_ERR(net);
 
+	/*
+	 * The caller already has CAP_NET_ADMIN over the source netns
+	 * (enforced by GENL_UNS_ADMIN_PERM on the genl op). Mirror the
+	 * convention used by net/core/rtnetlink.c::rtnl_get_net_ns_capable()
+	 * and require CAP_NET_ADMIN over the target netns as well, so that
+	 * a caller that is privileged in their own user namespace cannot
+	 * push a wiphy into a netns where they have no privilege.
+	 */
+	if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) {
+		put_net(net);
+		return -EPERM;
+	}
+
 	err = 0;
 
 	/* check if anything to do */
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 7.0-5.10] wifi: libertas: fix integer underflow in process_cmdrequest()
From: Sasha Levin @ 2026-05-20 11:18 UTC (permalink / raw)
  To: patches, stable
  Cc: Amir Mohammad Jahangirzad, Johannes Berg, Sasha Levin,
	linux-wireless, libertas-dev, linux-kernel
In-Reply-To: <20260520111944.3424570-1-sashal@kernel.org>

From: Amir Mohammad Jahangirzad <a.jahangirzad@gmail.com>

[ Upstream commit 3994b4afd521d60e47e012fe2ed7b606aaec370b ]

The existing validation only checks if recvlength exceeds
LBS_CMD_BUFFER_SIZE, but doesn't check the lower bound. When a
USB device sends a response shorter than MESSAGE_HEADER_LEN, the
subtraction (recvlength - MESSAGE_HEADER_LEN) wraps to a huge
value, causing memcpy to corrupt the heap.
Add the same lower bound check that libertas_tf already has.

Signed-off-by: Amir Mohammad Jahangirzad <a.jahangirzad@gmail.com>
Link: https://patch.msgid.link/20260418004247.368944-1-a.jahangirzad@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase Walkthrough
### Phase 1: Commit Message Forensics
Step 1.1 Record: Subsystem is `wifi: libertas`; action verb is `fix`;
claimed intent is to prevent integer underflow in
`process_cmdrequest()`.

Step 1.2 Record: Tags present are `Signed-off-by: Amir Mohammad
Jahangirzad`, `Link: https://patch.msgid.link/20260418004247.368944-1-
a.jahangirzad@gmail.com`, and `Signed-off-by: Johannes Berg`. No
`Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-by`, or
`Cc: stable` tag was present in the supplied commit message or original
posted patch.

Step 1.3 Record: The commit body describes a concrete memory corruption
bug: `recvlength` is only checked against the upper bound, then
`recvlength - MESSAGE_HEADER_LEN` is stored in `priv->resp_len[i]` and
used as the `memcpy()` length. If a USB device supplies fewer than 4
bytes, the subtraction becomes negative and is converted to a huge
unsigned copy length. Symptom/failure mode: heap/driver memory
corruption from `memcpy()`. Version information: none in the message.
Root cause: missing lower-bound validation.

Step 1.4 Record: This is not hidden; it is explicitly a memory-safety
fix. It matches the same already-present guard in `libertas_tf`.

### Phase 2: Diff Analysis
Step 2.1 Record: One file changed:
`drivers/net/wireless/marvell/libertas/if_usb.c`, 3 insertions and 2
deletions. Modified function: `process_cmdrequest()`. Scope: single-file
surgical fix.

Step 2.2 Record: Before, `process_cmdrequest()` rejected only
`recvlength > LBS_CMD_BUFFER_SIZE`; lengths `1..3` passed and produced
`recvlength - MESSAGE_HEADER_LEN`. After, it rejects `recvlength <
MESSAGE_HEADER_LEN` as well as overlarge responses. This affects the USB
command-response receive path.

Step 2.3 Record: Bug category is memory safety, specifically integer
underflow leading to oversized `memcpy()`. Verified details:
`MESSAGE_HEADER_LEN` is 4, `resp_len` is `u32`, `resp_buf` is `u8
resp_buf[2][LBS_UPLD_SIZE]`, and `LBS_UPLD_SIZE` is 2312. A negative
subtraction assigned to `u32` becomes a huge length, far beyond the
destination buffer.

Step 2.4 Record: Fix quality is high: minimal bounds check, no API
change, no new behavior except rejecting malformed command responses.
Regression risk is very low; valid command responses must already
include the 4-byte command type/header.

### Phase 3: Git History Investigation
Step 3.1 Record: `git blame` shows the upper-bound check came from
`ddac452680a516` in the v2.6.25-rc1 era, and the `resp_len = recvlength
- MESSAGE_HEADER_LEN` plus `memcpy()` flow came from `7919b89c8276` in
the v2.6.26-rc1 era. This code is old and widely present.

Step 3.2 Record: No `Fixes:` tag is present in the candidate, so there
is no specific tagged introducing commit to follow. Blame nevertheless
identifies the relevant old code.

Step 3.3 Record: Recent file history includes unrelated cleanup/fix
commits such as `3968e81ba644` changing skb free placement and
`d66676e6ca96` fixing a warning in `usb_tx_block()`. I found no
prerequisite commit needed for this bounds check.

Step 3.4 Record: `git log --author='Amir Mohammad Jahangirzad'` found no
prior local commits in this Marvell wireless subtree. The final signoff
is from Johannes Berg; `MAINTAINERS` lists Johannes Berg as wireless
maintainer, while the Libertas driver itself is marked orphaned under
`linux-wireless` and `libertas-dev`.

Step 3.5 Record: Dependencies found: none. The patch uses existing local
constants and mirrors the already-existing `libertas_tf` check.

### Phase 4: Mailing List And External Research
Step 4.1 Record: No commit hash was available in local history, so `b4
dig -c` could not be used successfully; `b4 dig -c
20260418004247.368944-1-a.jahangirzad@gmail.com` failed because it
expects a commit. Fallback `b4 mbox` and the lore mirror found the
original patch at `https://yhbt.net/lore/lkml/20260418004247.368944-1-
a.jahangirzad@gmail.com/T/`. The thread has one message and no replies.
`b4 mbox -c` found no newer revision in the thread.

Step 4.2 Record: Original recipients included Johannes Berg, Kees Cook,
Ingo Molnar, Johan Hovold, `linux-wireless`, `libertas-dev`, and `linux-
kernel`. No reviewer replies, NAKs, or explicit stable nominations were
present in the fetched thread.

Step 4.3 Record: No `Reported-by` or bug-report link was present. I
found no separate public bug report for this exact issue. The message
itself provides the failure mechanism.

Step 4.4 Record: Related precedent exists: commit `3348ef6a6a126` fixed
the identical underflow in `libertas_tf: process_cmdrequest()`, with
message “If recvlength is less than MESSAGE_HEADER_LEN (4) we would end
up corrupting memory.” That analogous fix was later carried in stable
review postings for 4.19 and 3.16.

Step 4.5 Record: Web searches found the exact candidate posting and
stable history for the analogous `libertas_tf` fix, but no exact stable
discussion for this new `libertas` patch.

### Phase 5: Code Semantic Analysis
Step 5.1 Record: Modified function: `process_cmdrequest()`.

Step 5.2 Record: Caller is `if_usb_receive()`, reached as the receive
URB completion callback installed by `usb_fill_bulk_urb()` through
`if_usb_submit_rx_urb()`.

Step 5.3 Record: Key callees are `memcpy()`, `dev_kfree_skb_irq()`, and
`lbs_notify_command_response()`. The command response is later consumed
by the main thread through `lbs_process_command_response()`.

Step 5.4 Record: Reachability is verified through USB receive
completion: a Libertas USB device response with type `CMD_TYPE_REQUEST`
reaches `process_cmdrequest()`. The triggering input is device-
controlled USB receive data, so this is reachable with affected hardware
or a malicious/faulty USB device.

Step 5.5 Record: Similar pattern found in `libertas_tf`; that sibling
driver already has the exact lower-bound check. `if_sdio` and `if_spi`
use different response formats and do not subtract `MESSAGE_HEADER_LEN`
in the same way.

### Phase 6: Cross-Referencing And Stable Tree Analysis
Step 6.1 Record: Representative tags `v3.16`, `v4.14`, `v4.19`, `v5.4`,
`v5.10`, `v5.15`, `v6.1`, `v6.6`, `v6.12`, and newer `v6.13` through
`v6.17` all contain the buggy `process_cmdrequest()` pattern without the
lower-bound check. The bug dates back to at least the v2.6.26-rc1 era.

Step 6.2 Record: Expected backport difficulty is low for modern stable
trees: the same context is present in representative stable tags, and
`git apply --check` succeeds against the current tree. Very old trees
before the Marvell directory move may need path/context adjustment, as
verified by older tags using `drivers/net/wireless/libertas/if_usb.c`.

Step 6.3 Record: No exact related fix for `libertas` was found in local
history. The sibling `libertas_tf` fix exists and was stable-backported.

### Phase 7: Subsystem And Maintainer Context
Step 7.1 Record: Subsystem is wireless driver code under
`drivers/net/wireless/marvell/libertas`. Criticality: driver-specific,
but memory corruption in a kernel USB receive path is high severity for
affected systems.

Step 7.2 Record: Subsystem activity is low-to-moderate; recent history
shows occasional fixes and cleanups. `MAINTAINERS` marks Marvell
Libertas as orphaned, with `linux-wireless` and `libertas-dev` lists.

### Phase 8: Impact And Risk Assessment
Step 8.1 Record: Affected population is config- and hardware-specific:
systems with `CONFIG_LIBERTAS_USB` and Marvell Libertas 8388 USB
devices, or systems exposed to a malicious USB device matching the
driver IDs.

Step 8.2 Record: Trigger condition is a USB command response shorter
than `MESSAGE_HEADER_LEN` but with `CMD_TYPE_REQUEST` dispatch. This is
device-controlled. I did not verify an unprivileged software-only
trigger; physical or device-level control is the verified trigger model.

Step 8.3 Record: Failure mode is heap/driver memory corruption from
oversized `memcpy()`. Severity: HIGH to CRITICAL, because kernel memory
corruption can crash the system and can have security implications.

Step 8.4 Record: Benefit is high for affected systems: prevents kernel
memory corruption from malformed USB responses. Risk is very low: 3-line
effective validation change in one driver function, with precedent in
sibling driver.

### Phase 9: Final Synthesis
Step 9.1 Record: Evidence for backporting: real memory corruption bug;
old code present across many stable release tags; tiny surgical fix; no
new API or feature; exact validation already used by `libertas_tf`;
analogous `libertas_tf` fix was stable-backported. Evidence against:
driver-specific and no external bug report or tested-by tag. Unresolved:
exact final upstream commit hash was not present in local history, so
`b4 dig -c <commit_hash>` could not be completed.

Step 9.2 Record:
1. Obviously correct and tested? Obviously correct by code inspection;
   no explicit `Tested-by`.
2. Fixes a real bug? Yes, verified underflow into oversized `memcpy()`.
3. Important issue? Yes, kernel memory corruption.
4. Small and contained? Yes, one function in one file.
5. No new features/APIs? Yes.
6. Can apply to stable trees? Yes for modern representative tags with
   likely clean/minor context; old pre-directory-move trees may need
   path adjustment.

Step 9.3 Record: No exception category such as device ID, quirk, DT,
build, or docs applies. This is a direct memory-safety bug fix.

Step 9.4 Record: Stable backport decision is YES. The fix prevents
kernel memory corruption in an old, stable-present USB driver path with
extremely low regression risk.

## Verification
- Phase 1: Parsed supplied tags and fetched original patch thread with
  `b4 mbox`; confirmed no `Fixes`, `Reported-by`, `Tested-by`,
  `Reviewed-by`, `Acked-by`, or stable tag.
- Phase 2: Read `drivers/net/wireless/marvell/libertas/if_usb.c`,
  `dev.h`, and `defs.h`; confirmed `MESSAGE_HEADER_LEN`, `resp_len`,
  `resp_buf`, and `memcpy()` behavior.
- Phase 3: Ran `git blame` on `process_cmdrequest()`; identified old
  introducing history around `ddac452680a516` and `7919b89c8276`.
- Phase 3: Ran `git describe --contains`; confirmed relevant code dates
  to v2.6.25/v2.6.26-era history.
- Phase 4: `b4 dig` with the message-id failed because no local commit
  hash was available; recorded as unresolved.
- Phase 4: `b4 mbox` fetched the patch thread; `b4 mbox -c` found one
  message and no newer revision.
- Phase 4: Fetched lore mirror and stable archive pages; confirmed
  analogous `libertas_tf` fix and stable review postings.
- Phase 5: Traced callers from `if_usb_receive()` through
  `usb_fill_bulk_urb()` and `if_usb_submit_rx_urb()`.
- Phase 6: Checked release tags from `v3.16` through representative
  active v6 tags; confirmed the buggy code exists broadly.
- Phase 6: Ran `git apply --check` against the current tree; patch
  applies cleanly there.
- Phase 7: Checked `MAINTAINERS`; confirmed Libertas is orphaned under
  wireless lists and Johannes Berg is listed for wireless maintenance.
- Phase 8: Verified trigger is USB device-controlled receive data; no
  unprivileged software-only trigger was verified.

**YES**

 drivers/net/wireless/marvell/libertas/if_usb.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c
index 8a6bf1365cfab..42d3fd32ece28 100644
--- a/drivers/net/wireless/marvell/libertas/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas/if_usb.c
@@ -625,9 +625,10 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
 	unsigned long flags;
 	u8 i;
 
-	if (recvlength > LBS_CMD_BUFFER_SIZE) {
+	if (recvlength < MESSAGE_HEADER_LEN ||
+	    recvlength > LBS_CMD_BUFFER_SIZE) {
 		lbs_deb_usbd(&cardp->udev->dev,
-			     "The receive buffer is too large\n");
+			     "The receive buffer is invalid: %d\n", recvlength);
 		kfree_skb(skb);
 		return;
 	}
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 7.0-5.15] wifi: nl80211: re-check wiphy netns in nl80211_prepare_wdev_dump() continuation
From: Sasha Levin @ 2026-05-20 11:18 UTC (permalink / raw)
  To: patches, stable
  Cc: Maoyi Xie, Johannes Berg, Sasha Levin, johannes, linux-wireless,
	linux-kernel
In-Reply-To: <20260520111944.3424570-1-sashal@kernel.org>

From: Maoyi Xie <maoyi.xie@ntu.edu.sg>

[ Upstream commit 79240f3f6d766b342b57c32397d643e1cfa26b81 ]

NL80211_CMD_GET_SCAN is implemented as a multi-call dumpit. The first
invocation of nl80211_prepare_wdev_dump() validates the requested wdev
against the caller's netns via __cfg80211_wdev_from_attrs(). Subsequent
invocations look up the same wiphy by its global index and do not check
that the wiphy is still in the caller's netns.

Add the same filter to the continuation path. If the wiphy's netns no
longer matches the caller's, return -ENODEV and the netlink dump
machinery terminates the walk cleanly.

Signed-off-by: Maoyi Xie <maoyi.xie@ntu.edu.sg>
Link: https://patch.msgid.link/20260506064854.2207105-3-maoyixie.tju@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Phase Walkthrough

**Phase 1: Commit Message Forensics**
- Step 1.1 Record: Subsystem `wifi: nl80211`; action verb `re-check`;
  intent is to revalidate the wiphy net namespace during
  `nl80211_prepare_wdev_dump()` continuation.
- Step 1.2 Record: Tags are `Signed-off-by: Maoyi Xie`, `Link: https://p
  atch.msgid.link/20260506064854.2207105-3-maoyixie.tju@gmail.com`,
  `Signed-off-by: Johannes Berg`. No `Fixes`, `Reported-by`, `Tested-
  by`, `Reviewed-by`, `Acked-by`, or `Cc: stable`.
- Step 1.3 Record: The committed message says first dump invocation
  validates via `__cfg80211_wdev_from_attrs()`, but later invocations
  recover the wiphy by global index and lacked a netns check. The v3
  mailing-list patch further states the failure mode: BSS scan data can
  continue being copied from a wiphy after it moved to another netns.
- Step 1.4 Record: This is a hidden security/correctness fix, not a
  cleanup. It fixes a namespace isolation race in a multi-call netlink
  dump.

**Phase 2: Diff Analysis**
- Step 2.1 Record: One file changed, `net/wireless/nl80211.c`; commit
  stat is 12 insertions. One function changed:
  `nl80211_prepare_wdev_dump()`. Scope is single-file surgical.
- Step 2.2 Record: Before, continuation path did
  `wiphy_idx_to_wiphy(cb->args[0] - 1)`, accepted the wiphy, then
  searched `wdev_list`. After, it returns `-ENODEV` if
  `!net_eq(wiphy_net(wiphy), sock_net(cb->skb->sk))`.
- Step 2.3 Record: Bug category is race / namespace isolation /
  information disclosure. A wiphy can move netns between dumpit calls
  via `NL80211_CMD_SET_WIPHY_NETNS`.
- Step 2.4 Record: Fix quality is high: one predicate and clean error
  return before taking `wiphy.mtx`. Regression risk is low; it only
  rejects a continuation whose object no longer belongs to the caller’s
  netns.

**Phase 3: Git History**
- Step 3.1 Record: Current checkout is shallow; `git blame` attributed
  the region to a shallow boundary, so that blame is not reliable.
  Pickaxe history found the continuation-by-global-wiphy-index pattern
  in old history, including `c319d50bfcf67` (`nl80211: fix another
  nl80211_fam.attrbuf race`), contained by `v3.11-rc6`. Netns support
  for cfg80211/nl80211 was introduced by `463d018323851`, contained by
  `v2.6.32-rc1`.
- Step 3.2 Record: No `Fixes:` tag, so no tagged introducer to follow.
- Step 3.3 Record: Fetched wireless history shows the candidate
  immediately follows companion commit `15994bb0cbb8f` (`wifi: nl80211:
  require CAP_NET_ADMIN over the target netns in SET_WIPHY_NETNS`). No
  intermediate commit between them.
- Step 3.4 Record: Author has only these two fetched wireless commits.
  Committer is Johannes Berg, the nl80211/cfg80211 maintainer.
- Step 3.5 Record: No compile dependency on the companion commit, but
  logical/security context is stronger if `15994bb0cbb8f` is backported
  too.

**Phase 4: Mailing List / External Research**
- Step 4.1 Record: `b4 dig -c 79240f3f6d766...` found the v3 patch at
  the provided `patch.msgid.link` URL. `b4 dig -a` found v1 and v3; `b4
  am` showed v1, v2, v3. v3 cover says no code changes since v2 and that
  Johannes review caused comment/trailer cleanup.
- Step 4.2 Record: `b4 dig -w` shows Johannes Berg, `linux-wireless`,
  and `linux-kernel` were included.
- Step 4.3 Record: No syzbot/bugzilla report. The series cover and patch
  body provide the bug explanation and patch 1 includes a mac80211_hwsim
  reproducer for the related `SET_WIPHY_NETNS` privilege path.
- Step 4.4 Record: This is patch 2/2 in a series. Patch 1 hardens
  target-netns capability checks; patch 2 fixes dump continuation
  filtering.
- Step 4.5 Record: Lore WebFetch was blocked by Anubis; WebSearch did
  not find stable-specific discussion.

**Phase 5: Code Semantic Analysis**
- Step 5.1 Record: Modified function is `nl80211_prepare_wdev_dump()`.
- Step 5.2 Record: Exact callers are `nl80211_dump_station()`,
  `nl80211_dump_mpath()`, `nl80211_dump_mpp()`, `nl80211_dump_scan()`,
  and `nl80211_dump_survey()`.
- Step 5.3 Record: Key callees are `__cfg80211_wdev_from_attrs()`,
  `wiphy_idx_to_wiphy()`, `wiphy_net()`, `sock_net()`, `net_eq()`,
  `wiphy_to_rdev()`, and list walk over `wiphy.wdev_list`.
- Step 5.4 Record: `NL80211_CMD_GET_SCAN` maps to `nl80211_dump_scan()`
  and has no admin flag in the ops entry; `NL80211_CMD_SET_WIPHY_NETNS`
  maps to `nl80211_wiphy_netns()` with `GENL_UNS_ADMIN_PERM`.
- Step 5.5 Record: Similar dump paths `nl80211_dump_wiphy()` and
  `nl80211_dump_interface()` already filter by `net_eq(wiphy_net(...),
  sock_net(skb->sk))` each iteration.

**Phase 6: Stable Tree Analysis**
- Step 6.1 Record: The affected continuation code exists in checked tags
  `v6.19`, `v6.18`, `v6.12`, `v6.6`, `v6.1`, `v5.15`, `v5.10`, `v5.4`,
  `v4.19`, and `v4.14`.
- Step 6.2 Record: Modern stable trees have the same helper shape. Older
  trees such as `v5.4` and `v4.14` have different function
  signatures/locking, so they may need small backport adjustment.
- Step 6.3 Record: Searches in checked stable tags did not find this
  candidate or the companion commit already present.

**Phase 7: Subsystem Context**
- Step 7.1 Record: Subsystem is wireless cfg80211/nl80211, an important
  networking control-plane subsystem.
- Step 7.2 Record: `net/wireless/nl80211.c` is actively maintained;
  fetched wireless history shows this series was taken through Johannes
  Berg’s wireless tree.

**Phase 8: Impact / Risk**
- Step 8.1 Record: Affected users are systems using wireless devices
  with nl80211 netns movement support, including delegated/container
  wireless setups and mac80211_hwsim.
- Step 8.2 Record: Trigger requires a multi-call dump and a wiphy netns
  move between invocations. The related series verifies an unprivileged
  userns path when the caller has a delegated `WIPHY_FLAG_NETNS_OK`
  wiphy.
- Step 8.3 Record: Failure mode is namespace isolation breach / cross-
  netns scan-result exposure, not a crash. Severity: HIGH due
  security/isolation impact.
- Step 8.4 Record: Benefit is high for isolation correctness; risk is
  very low because the patch adds one local validation and returns an
  existing error code.

**Phase 9: Final Synthesis**
- Step 9.1 Record: Evidence for backporting: real namespace isolation
  bug, old code present across stable trees, small surgical fix,
  maintainer-applied, aligns with existing dump filtering. Evidence
  against: companion patch should also be considered, and older trees
  may require minor backport edits. Unresolved: no independent `Tested-
  by`; stable-specific lore discussion could not be fetched.
- Step 9.2 Record: Stable rules: obviously correct yes; fixes real bug
  yes; important issue yes due namespace isolation/security; small and
  contained yes; no new API/feature yes; applies cleanly or with minor
  adjustment depending on tree.
- Step 9.3 Record: No exception category applies.
- Step 9.4 Record: Backport is warranted, preferably together with
  `15994bb0cbb8f` for the complete netns hardening series.

## Verification
- Phase 1: Parsed `git show 79240f3f6d766...` and b4 v3 patch text;
  verified tags and commit body.
- Phase 2: Verified diff is one hunk in `nl80211_prepare_wdev_dump()`
  with 12 insertions.
- Phase 3: Ran `git blame`, pickaxe history, `git show` for
  `c319d50bfcf67`, `463d018323851`, companion `15994bb0cbb8f`, and
  fetched wireless history.
- Phase 4: Ran `b4 dig`, `b4 dig -a`, `b4 dig -w`, `b4 am` for v1/v2/v3,
  saved/read mbox; WebFetch to lore was blocked by Anubis.
- Phase 5: Verified callers and relevant ops entries in
  `net/wireless/nl80211.c`.
- Phase 6: Used `git grep` across stable tags to confirm affected code
  exists and checked stable logs for absence of the candidate.
- Phase 8: Severity is based on verified patch text plus code paths; no
  build or runtime test was run.

**YES**

 net/wireless/nl80211.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b94231c8441c4..ce3121b1c3319 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1146,6 +1146,18 @@ static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
 			rtnl_unlock();
 			return -ENODEV;
 		}
+
+		/*
+		 * The first invocation validated the wdev's netns against
+		 * the caller via __cfg80211_wdev_from_attrs(). The wiphy
+		 * may have moved netns between dumpit invocations (via
+		 * NL80211_CMD_SET_WIPHY_NETNS), so re-check here.
+		 */
+		if (!net_eq(wiphy_net(wiphy), sock_net(cb->skb->sk))) {
+			rtnl_unlock();
+			return -ENODEV;
+		}
+
 		*rdev = wiphy_to_rdev(wiphy);
 		*wdev = NULL;
 
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v6 5/6] wifi: mac80211: Fix overread in PREP frame processing
From: Johannes Berg @ 2026-05-20 11:16 UTC (permalink / raw)
  To: Masashi Honma, linux-wireless
In-Reply-To: <20260515233839.86829-5-masashi.honma@gmail.com>

On Sat, 2026-05-16 at 08:38 +0900, Masashi Honma wrote:
> 
> +/* IEEE Std 802.11-2016 9.4.2.114 PREP element */
> +static inline bool ieee80211_mesh_prep_size_ok(const u8 *pos, u8 elen)
> +{
...

> +	if (elen != needed)
> +		return false;
> +
> +	return true;

nit: maybe just "return elen == needed;"

johannes

^ permalink raw reply

* Re: [PATCH v6 4/6] wifi: mac80211: Fix overread in PREQ frame processing
From: Johannes Berg @ 2026-05-20 11:15 UTC (permalink / raw)
  To: Masashi Honma, linux-wireless
In-Reply-To: <20260515233839.86829-4-masashi.honma@gmail.com>

On Sat, 2026-05-16 at 08:38 +0900, Masashi Honma wrote:
> 
> +		/* Right now we only supports 1 target */

nit: "support"

johannes

^ permalink raw reply

* Re: [PATCH v6 1/6] wifi: mac80211: Use struct instead of macro for PREQ frame
From: Johannes Berg @ 2026-05-20 11:14 UTC (permalink / raw)
  To: Masashi Honma, linux-wireless
In-Reply-To: <20260515233839.86829-1-masashi.honma@gmail.com>

Hi,

So I was tempted to just take this, but I did have a couple of nit
comments and questions, so maybe let's iterate once more.

On Sat, 2026-05-16 at 08:38 +0900, Masashi Honma wrote:
> Signed-off-by: Masashi Honma <masashi.honma@gmail.com>

It would be nice to have a bit more commit message, but yeah, it doesn't
do that much ...

I'd definitely reformat this:

> +static inline struct ieee80211_mesh_hwmp_preq_bottom *
> +	ieee80211_mesh_hwmp_preq_get_bottom(const u8 *ie)

to not have that tab there, and

> +{
> +	struct ieee80211_mesh_hwmp_preq_top *top =
> +		(struct ieee80211_mesh_hwmp_preq_top *)ie;
> +	return (struct ieee80211_mesh_hwmp_preq_bottom *)

to have a blank line between the var declaration and the code.

In this case I'd also be tempted to just use (void *) casts to make it
much shorter, since the other types are implied by the variable/return
types.

> +		struct ieee80211_mesh_hwmp_preq_top *preq_elem_top =
> +			(struct ieee80211_mesh_hwmp_preq_top *)hwmp_ie;
> +		struct ieee80211_mesh_hwmp_preq_bottom *preq_elem_bottom =
> +			ieee80211_mesh_hwmp_preq_get_bottom(hwmp_ie);

same here, perhaps.

> +		orig_addr = preq_elem_top->orig_addr;
> +		orig_sn = get_unaligned_le32(&preq_elem_top->orig_sn);
> +		orig_lifetime = get_unaligned_le32(&preq_elem_bottom->lifetime);
> +		orig_metric = get_unaligned_le32(&preq_elem_bottom->metric);

Ok, oops, I just realized my other thought on this was wrong - the
previous PREQ_IE_LIFETIME() was u32_field_get() which loaded an entirely
u32 from there using get_unaligned_le32().

However, another comment: You don't need get_unaligned_le32() here since
the struct is __packed, so you can simplify all of these to just

	orig_sn = le32_to_cpu(preq_elem_top->orig_sn);

etc.

> +	target_sn = get_unaligned_le32(&target[0].sn);
> +	orig_sn = get_unaligned_le32(&preq_elem_top->orig_sn);

same throughout wherever you access through a __packed struct. This also
applies to the other patches.

johannes

^ permalink raw reply

* Re: [PATCH 0/6] b43: complete N-PHY rev 8 + radio 2057 rev 8 support
From: Johannes Berg @ 2026-05-20 11:06 UTC (permalink / raw)
  To: Alessio Ferri, Michael Büsch
  Cc: linux-wireless, b43-dev, kvalo, linux-kernel
In-Reply-To: <20260519230241.49489a8f@DELL-MOBILE03.ad.smart.it>

On Tue, 2026-05-19 at 23:02 +0200, Alessio Ferri wrote:
> 
> The patchset is tested on my own DLink DSL 3580L router and generated by
> claude from our shared notes, i then reviewed it for sanity and
> verified it by navigating from the router with modified b43 driver with
> my phone.

I would ask you to disclose this in the commits per

https://docs.kernel.org/process/coding-assistants.html

johannes

^ permalink raw reply

* Re: [PATCH v4] wifi: mac80211: fix monitor mode frame capture for real chanctx drivers
From: Óscar Alfonso Díaz @ 2026-05-20  9:55 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Devin Wittmayer, linux-wireless, Felix Fietkau, Lorenzo Bianconi,
	linux-kernel, stable, fjhhz1997, Brite
In-Reply-To: <e73634b3b52d9ebe6c4e339ea5f6c35cb6d433a7.camel@sipsolutions.net>

Ok, I'll do the testing using this one you suggested:
https://patchwork.kernel.org/project/linux-wireless/patch/20260519235713.49109-2-lucid_duck@justthetip.ca/

Thanks.
--
Oscar

OpenPGP Key: DA9C60E9 ||
https://pgp.mit.edu/pks/lookup?op=get&search=0x79B17260DA9C60E9
4F74 B302 354D 817D DE38 0A43 79B1 7260 DA9C 60E9
--

El mié, 20 may 2026 a las 11:53, Johannes Berg
(<johannes@sipsolutions.net>) escribió:
>
> On Wed, 2026-05-20 at 11:51 +0200, Óscar Alfonso Díaz wrote:
> > Ok, let me do one final test using Johannes’ v2 patch. The expected
> > behavior is as follows:
> >
> > 6.18 or lower: no need to test, it will not work. It’s clear now that
> > this does not matter, since the goal is only to fix newer kernel
> > versions.
> >
> > 6.19: some versions of the 6.19 will crash and others will not. The
> > crash was fixed at some point between 6.18.12 and 6.19.12. No need to
> > test.
> >
> > 7.0, or 7.1: the expected result is that there will be no crash, and
> > VIF + deauth will work only on 2.4 GHz. It will not work on 5 GHz
> > (I'll test both, normal DoS and VIF+DoS). There should be no crash,
> > but it will not work.
> >
> > So I'll focus my testing on 7.0 and 7.1 and I'll get back to you with
> > the results. I'll be testing this patch (v2):
> > https://patchwork.kernel.org/project/linux-wireless/patch/20251216111909.25076-2-johannes@sipsolutions.net/
> >
>
> Thanks. For testing that one you'd have to revert the other first, I
> think, you could also just test this one:
>
> https://patchwork.kernel.org/project/linux-wireless/patch/20260519235713.49109-2-lucid_duck@justthetip.ca/
>
> But I think they're basically all equivalent.
>
> Since we eventually need a patch to apply w/o reverting, Devin's is
> probably better than my old one.
>
> johannes

^ permalink raw reply

* Re: [PATCH v4] wifi: mac80211: fix monitor mode frame capture for real chanctx drivers
From: Johannes Berg @ 2026-05-20  9:53 UTC (permalink / raw)
  To: Óscar Alfonso Díaz
  Cc: Devin Wittmayer, linux-wireless, Felix Fietkau, Lorenzo Bianconi,
	linux-kernel, stable, fjhhz1997, Brite
In-Reply-To: <CA+bbHrUqh+nu_eKBMVaPH6Q8YxuKS=S0kON2Zsb+gRZHU=SBPA@mail.gmail.com>

On Wed, 2026-05-20 at 11:51 +0200, Óscar Alfonso Díaz wrote:
> Ok, let me do one final test using Johannes’ v2 patch. The expected
> behavior is as follows:
> 
> 6.18 or lower: no need to test, it will not work. It’s clear now that
> this does not matter, since the goal is only to fix newer kernel
> versions.
> 
> 6.19: some versions of the 6.19 will crash and others will not. The
> crash was fixed at some point between 6.18.12 and 6.19.12. No need to
> test.
> 
> 7.0, or 7.1: the expected result is that there will be no crash, and
> VIF + deauth will work only on 2.4 GHz. It will not work on 5 GHz
> (I'll test both, normal DoS and VIF+DoS). There should be no crash,
> but it will not work.
> 
> So I'll focus my testing on 7.0 and 7.1 and I'll get back to you with
> the results. I'll be testing this patch (v2):
> https://patchwork.kernel.org/project/linux-wireless/patch/20251216111909.25076-2-johannes@sipsolutions.net/
> 

Thanks. For testing that one you'd have to revert the other first, I
think, you could also just test this one:

https://patchwork.kernel.org/project/linux-wireless/patch/20260519235713.49109-2-lucid_duck@justthetip.ca/

But I think they're basically all equivalent.

Since we eventually need a patch to apply w/o reverting, Devin's is
probably better than my old one.

johannes

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox