Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] wifi: mt76: mt792x: fix mt7925u USB WFSYS reset handling
From: Satadru Pramanik @ 2026-03-11 18:15 UTC (permalink / raw)
  To: Nick
  Cc: Sean Wang, nbd, lorenzo.bianconi, linux-wireless, linux-mediatek,
	Sean Wang, stable
In-Reply-To: <CAFrh3J-PsVQ1u_hGFxTVKK0uOs6KxT=euK+jbGvWCueqvynAgw@mail.gmail.com>

After rebuilding the kernel with 7.0-rc3 and the two patches at
https://patchwork.kernel.org/project/linux-wireless/list/?series=1064695,
I can confirm that after a warm reboot booted from that kernel, the
mt7925u-based adapter is once again visible.

Thanks!

Regards,

Satadru Pramanik



On Wed, Mar 11, 2026 at 12:42 PM Satadru Pramanik <satadru@gmail.com> wrote:
>
> Hello all, I'm rebuilding this kernel one more time in case I mispatched, and will let you know shortly if a new kernel build works.
>
> Regards,
>
> Satadru
>
> On Wed, Mar 11, 2026 at 12:15 PM Nick <morrownr@gmail.com> wrote:
>>
>> > From: Sean Wang <sean.wang@mediatek.com>
>> >
>> > mt7925u uses different reset/status registers from mt7921u. Reusing the
>> > mt7921u register set causes the WFSYS reset to fail.
>> >
>> > Add a chip-specific descriptor in mt792xu_wfsys_reset() to select the
>> > correct registers and fix mt7925u failing to initialize after a warm
>> > reboot.
>> >
>> > Fixes: d28e1a48952e ("wifi: mt76: mt792x: introduce mt792x-usb module")
>> > Cc: stable@vger.kernel.org
>> > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
>> > ---
>> >  drivers/net/wireless/mediatek/mt76/mt792x_regs.h |  4 ++++
>> >  drivers/net/wireless/mediatek/mt76/mt792x_usb.c  | 13 ++++++++++++-
>> >  2 files changed, 16 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
>> > index 7ddde9286861..d2a8b2b0df32 100644
>> > --- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
>> > +++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
>> > @@ -392,6 +392,10 @@
>> >  #define MT_CBTOP_RGU_WF_SUBSYS_RST     MT_CBTOP_RGU(0x600)
>> >  #define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0)
>> >
>> > +#define MT7925_CBTOP_RGU_WF_SUBSYS_RST 0x70028600
>> > +#define MT7925_WFSYS_INIT_DONE_ADDR    0x184c1604
>> > +#define MT7925_WFSYS_INIT_DONE         0x00001d1e
>> > +
>> >  #define MT_HW_BOUND                    0x70010020
>> >  #define MT_HW_CHIPID                   0x70010200
>> >  #define MT_HW_REV                      0x70010204
>> > diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
>> > index a92e872226cf..47827d1c5ccb 100644
>> > --- a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
>> > +++ b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
>> > @@ -224,6 +224,15 @@ static const struct mt792xu_wfsys_desc mt7921_wfsys_desc = {
>> >         .need_status_sel = true,
>> >  };
>> >
>> > +static const struct mt792xu_wfsys_desc mt7925_wfsys_desc = {
>> > +       .rst_reg = MT7925_CBTOP_RGU_WF_SUBSYS_RST,
>> > +       .done_reg = MT7925_WFSYS_INIT_DONE_ADDR,
>> > +       .done_mask = U32_MAX,
>> > +       .done_val = MT7925_WFSYS_INIT_DONE,
>> > +       .delay_ms = 20,
>> > +       .need_status_sel = false,
>> > +};
>> > +
>> >  int mt792xu_dma_init(struct mt792x_dev *dev, bool resume)
>> >  {
>> >         int err;
>> > @@ -254,7 +263,9 @@ EXPORT_SYMBOL_GPL(mt792xu_dma_init);
>> >
>> >  int mt792xu_wfsys_reset(struct mt792x_dev *dev)
>> >  {
>> > -       const struct mt792xu_wfsys_desc *desc = &mt7921_wfsys_desc;
>> > +       const struct mt792xu_wfsys_desc *desc = is_mt7925(&dev->mt76) ?
>> > +                                               &mt7925_wfsys_desc :
>> > +                                               &mt7921_wfsys_desc;
>> >         u32 val;
>> >         int i;
>> >
>> > --
>> > 2.43.0
>> >
>>
>> Sean, testing results from: Satadru Pramanik <satadru@gmail.com>
>>
>> "The updated patches from
>> https://patchwork.kernel.org/project/linux-wireless/list/?series=1064695
>> do NOT work. I get the -110 error with them on a warm reboot.
>> Reverting to the kernel with the older patch restores my adapter
>> connection on a warm reboot."
>>
>> You are welcome to stop by the Github issue where this issue is being discussed:
>>
>> https://github.com/morrownr/USB-WiFi/issues/688#
>>
>> Nick

^ permalink raw reply

* Re: [PATCH 00/18] wifi: mt76: mt7925: add MT7927 (Filogic 380) support
From: Shengyu Qu @ 2026-03-11 18:50 UTC (permalink / raw)
  To: Sean Wang, Javier Tia
  Cc: wiagn233, linux-wireless, Felix Fietkau, Lorenzo Bianconi,
	Ryder Lee, Shayne Chen, Sean Wang, Matthias Brugger,
	AngeloGioacchino Del Regno, Deren Wu, Ming Yen Hsieh,
	linux-kernel, linux-arm-kernel, linux-mediatek, Marcin FM,
	Cristian-Florin Radoi, George Salukvadze, Evgeny Kapusta,
	Samu Toljamo, Ariel Rosenfeld, Chapuis Dario,
	Thibaut François, 张旭涵
In-Reply-To: <CAGp9Lzq1motdBxa9uk59Nhx0rxt4XJAp5OynpWVsB_sAm6Lx8Q@mail.gmail.com>


[-- Attachment #1.1.1: Type: text/plain, Size: 10307 bytes --]

Hello Sean,

Could you upload the firmware of this chip to linux-firmware repo? Also
could you(or someone who is more familiar with this chip) do a deep
review of these code? This series is heavily AI-assisted when
developing, so there might be some hidden bugs or something else that
haven't been discovered.

Best regards,
Shengyu

在 2026/3/7 15:08, Sean Wang 写道:
> Hi Javier,
> 
> On Fri, Mar 6, 2026 at 6:33 PM Javier Tia <floss@jetm.me> wrote:
>>
>> This series adds support for the MediaTek MT7927 (Filogic 380) combo
>> WiFi 7 + BT 5.4 module to the mt7925 driver. The MT7927 uses PCI ID
>> 14c3:7927 (some hardware reports 14c3:6639) and shares the mt7925
>> firmware interface but requires different DMA ring layout, IRQ mapping,
>> chip initialization, and power management handling.
>>
>> Tested hardware:
>> - ASUS ROG Crosshair X870E Hero (BT 0489:e13a, WiFi 14c3:6639)
>> - ASUS ProArt X870E-Creator WiFi (BT 0489:e13a / 13d3:3588, WiFi 14c3:6639)
>> - ASUS ROG Strix X870E-E (BT 0489:e13a, WiFi 14c3:7927)
>> - Gigabyte X870E Aorus Master X3D (BT 0489:e10f, WiFi 14c3:7927)
>> - Gigabyte Z790 AORUS MASTER X (BT 0489:e10f, WiFi 14c3:7927)
>> - Lenovo Legion Pro 7 16ARX9 (BT 0489:e0fa, WiFi 14c3:7927)
>> - TP-Link Archer TBE550E PCIe (BT 0489:e116, WiFi 14c3:7927)
>> - EDUP EP-MT7927BE M.2 card (WiFi 14c3:7927)
>> - Foxconn/Azurewave M.2 modules (WiFi 14c3:6639)
>> - AMD RZ738 reference design (WiFi 14c3:0738)
>>
> 
> Thanks for coordinating the work and delivering the driver.
> 
>> Tested on Arch Linux, CachyOS, EndeavourOS, Fedora (Bazzite), NixOS,
>> openSUSE Tumbleweed, and Ubuntu across kernels 6.13-6.19.
>>
>> What works:
>> - WiFi 7 with EHT 320MHz on 2.4/5/6 GHz bands
>> - 320MHz data path verified at 841 Mbps (iperf3 -t30 -P8)
>> - PCIe initialization with CBTOP remap and MT7927-specific DMA layout
>> - Runtime power management and suspend/resume (S3)
>> - DBDC (dual-band concurrent) mode
>> - Explicit band_idx assignment for stable 5GHz/6GHz operation
>> - ASPM disabled for MT7927 to prevent throughput collapse
>>
>> Known limitations (planned as follow-up series):
>> - MLO (Multi-Link Operation): tested working on 5GHz+2.4GHz STR
>>    (776 Mbps) but requires additional patches for link lifetime
>>    and error handling. Sean Wang's series [1] addresses these;
>>    MLO support will be submitted as a follow-up on top of that.
>>
>> [1] https://lore.kernel.org/linux-wireless/20260306232238.2039675-1-sean.wang@kernel.org/
>> - TX retransmissions: elevated retry rate on all bands, firmware-side
>>    rate adaptation issue not addressable in the driver.
>>
>> Patches 1-11 bring up the basic driver (chip ID, firmware, DMA, init,
>> power management, 320MHz MCS, mac_reset guard, IRQ map, probe fix).
>> Patch 12 advertises EHT 320MHz capabilities, guarded by is_mt7927().
>> Patches 13-14 fix DMASHDL PM wake and disable ASPM.
>> Patch 15 adds 320MHz bandwidth handling in RXV/TXS status reporting.
>> Patch 16 fixes stale pointer comparisons in change_vif_links.
>> Patch 17 assigns explicit band_idx for stable 5GHz/6GHz operation.
>> Patch 18 adds the missing 320MHz case in bss_rlm_tlv() so firmware
>> receives the correct bandwidth when associated to a 320MHz BSS.
>>
>> The WiFi firmware ships as part of the linux-firmware package
>> (mediatek/mt6639/ directory - the firmware uses the mobile SoC codename).
>>
>> To: linux-wireless@vger.kernel.org
>> To: Felix Fietkau <nbd@nbd.name>
>> To: Lorenzo Bianconi <lorenzo@kernel.org>
>> To: Ryder Lee <ryder.lee@mediatek.com>
>> To: Shayne Chen <shayne.chen@mediatek.com>
>> To: Sean Wang <sean.wang@mediatek.com>
>> To: Matthias Brugger <matthias.bgg@gmail.com>
>> To: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> To: Deren Wu <deren.wu@mediatek.com>
>> To: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
>> Cc: linux-kernel@vger.kernel.org
>> Cc: linux-arm-kernel@lists.infradead.org
>> Cc: linux-mediatek@lists.infradead.org
>> Tested-by: Marcin FM <marcin@lgic.pl>
>> Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
>> Tested-by: George Salukvadze <giosal90@gmail.com>
>> Tested-by: Evgeny Kapusta <3193631@gmail.com>
>> Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
>> Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
>> Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
>> Tested-by: Thibaut François <tibo@humeurlibre.fr>
>> Tested-by: 张旭涵 <Loong.0x00@gmail.com>
>>
>> Signed-off-by: Javier Tia <floss@jetm.me>
>> ---
>> Javier Tia (18):
>>        wifi: mt76: mt7925: add MT7927 chip ID helpers
>>        wifi: mt76: mt7925: add MT7927 firmware paths and PCI device IDs
>>        wifi: mt76: mt7925: add MT7927 CBTOP remap and chip initialization
>>        wifi: mt76: mt7925: add MT7927 DMA ring layout, IRQ map, and prefetch
>>        wifi: mt76: mt7925: skip CLR_OWN in mt7925e_mcu_init for MT7927
>>        wifi: mt76: mt7925: add MT7927 power management, DBDC, and CNM fixes
>>        wifi: mt76: mt7925: use irq_map fields instead of MT_INT_RX_DONE_ALL
>>        wifi: mt76: mt7925: guard mac_reset against MT7927 DMA destruction
>>        wifi: mt76: mt7925: populate EHT 320MHz MCS map in sta_rec
>>        wifi: mt76: mt7925: enable MT7927 runtime power management
>>        wifi: mt76: mt7925: fix uninitialized is_mt7927_hw in probe
>>        wifi: mt76: mt7925: advertise EHT 320MHz capabilities for 6GHz band
>>        wifi: mt76: mt7925: restore FW_DWLD_BYPASS_DMASHDL in MT7927 PM wake path
>>        wifi: mt76: mt7925: disable ASPM for MT7927 to fix throughput collapse
>>        wifi: mt76: mt7925: handle 320MHz bandwidth in RXV and TXS
>>        wifi: mt76: mt7925: fix stale pointer comparisons in change_vif_links
>>        wifi: mt76: mt7925: fix MT7927 band_idx for stable 5GHz/6GHz operation
>>        wifi: mt76: mt7925: add 320MHz bandwidth to bss_rlm_tlv
>>
> 
> The patchset should be ordered so that common changes (e.g., enabling
> 320 MHz support) are added first,
> while chip-specific changes are introduced later (e.g.,
> MT7927-specific IRQ, DMA, and hardware initialization sequences).
> Before introducing chip-specific logic, try to make the functions
> generic enough so that other chips can reuse them in the same way.
> Checks such as is_mt7927 and duplicated function should only be added
> if they cannot be avoided
> 
> The more code we can reuse across chips, the fewer maintenance
> concerns there will be, and we can focus more effort on the
> chip-specific parts.
> 
> Please reorganize the patchset order as follows:
> 
> 1. Common patches that can be reused by other chipsets (now or in the
> future) should come first we don't need to mention mt7927
> 
> "wifi: mt76: mt7925: fix stale pointer comparisons in change_vif_links"
> "wifi: mt76: mt7925: add 320MHz bandwidth to bss_rlm_tlv"
> "wifi: mt76: mt7925: handle 320MHz bandwidth in RXV and TXS"
> "wifi: mt76: mt7925: populate EHT 320MHz MCS map in sta_rec"
> "wifi: mt76: mt7925: advertise EHT 320MHz capabilities for 6GHz band"
> 
> Here we can add a helper like is_320MHz_supported() and then advertise
> EHT 320MHz capabilities, but do not need to mention is_mt7927() yet.
> 
> 2. Then introduce MT7927-related changes
> 
> wifi: mt76: mt7925: add MT7927 chip ID helpers
> Keep the MCU part of "wifi: mt76: mt7925: add MT7927 firmware paths
> and PCI device IDs" but leave enabling the PCI device table for the
> last patch.
> 
> 3. IRQ handling
> 
> Combine
> 
> wifi: mt76: mt7925: use irq_map fields instead of MT_INT_RX_DONE_ALL
> the IRQ part of wifi: mt76: mt7925: add MT7927 DMA ring layout, IRQ
> map, and prefetch
> into one patch about irq_map handling, trying to reuse mt7925_irq as
> much as possible.
> 
> 4. DMA handling
> 
> Combine
> 
> the DMA part of "wifi: mt76: mt7925: add MT7927 DMA ring layout, IRQ
> map, and prefetch"
> "wifi: mt76: mt7925: restore FW_DWLD_BYPASS_DMASHDL in MT7927 PM wake path"
> into one patch about DMA handling, trying to reuse mt7925_dma_init as
> much as possible.
> 
> 5. Hardware initialization
> 
> Combine
> 
> "wifi: mt76: mt7925: add MT7927 CBTOP remap and chip initialization"
> "wifi: mt76: mt7925: fix uninitialized is_mt7927_hw in probe"
> "wifi: mt76: mt7925: skip CLR_OWN in mt7925e_mcu_init for MT7927"
> "wifi: mt76: mt7925: add MT7927 power management, DBDC, and CNM fixes"
> 
> into one or more patches focused on pure hardware initialization in
> logical order. If the register definition is used by MT7927, add
> MT7927_ as the prefix.
> 
> 6. Band index fix
> 
> "wifi: mt76: mt7925: fix MT7927 band_idx for stable 5GHz/6GHz operation"
> This is worth introducing helper functions and using them instead of
> implementing the logic inline.
> 
> 7. Low power support
> 
> Combine
> 
> "wifi: mt76: mt7925: enable MT7927 runtime power management"
> "wifi: mt76: mt7925: disable ASPM for MT7927 to fix throughput collapse"
> 
> into one or more patches related to enabling or disabling low power support.
> 
> 8. Final patch
> The last patch should enable the MT7927 PCI device table.
> 
>>   drivers/net/wireless/mediatek/mt76/mt76_connac.h   |   8 +-
>>   drivers/net/wireless/mediatek/mt76/mt7925/init.c   |  12 +
>>   drivers/net/wireless/mediatek/mt76/mt7925/mac.c    |   9 +
>>   drivers/net/wireless/mediatek/mt76/mt7925/main.c   |  72 +++++-
>>   drivers/net/wireless/mediatek/mt76/mt7925/mcu.c    |  59 ++++-
>>   drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h |  12 +
>>   drivers/net/wireless/mediatek/mt76/mt7925/pci.c    | 248 ++++++++++++++++++++-
>>   .../net/wireless/mediatek/mt76/mt7925/pci_mac.c    |  13 +-
>>   .../net/wireless/mediatek/mt76/mt7925/pci_mcu.c    |  19 +-
>>   drivers/net/wireless/mediatek/mt76/mt792x.h        |   6 +
>>   drivers/net/wireless/mediatek/mt76/mt792x_dma.c    |  26 ++-
>>   drivers/net/wireless/mediatek/mt76/mt792x_regs.h   |  30 +++
>>   12 files changed, 479 insertions(+), 35 deletions(-)
>> ---
>> base-commit: 97492c019da4b62df83255e968b23b81c0315530
>> change-id: 20260305-mt7927-wifi-support-02f9738a3962
>>
>> Best regards,
>> --
>> Javier Tia <floss@jetm.me>
>>
>>


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply

* [PATCH] dt-bindings: net: wireless: marvell,sd8787: Relax length constraints
From: Fabio Estevam @ 2026-03-11 19:45 UTC (permalink / raw)
  To: johannes
  Cc: robh, krzk+dt, conor+dt, briannorris, Frank.Li, kvalo,
	linux-wireless, devicetree, linux-kernel, Fabio Estevam

Commit 31ed9d9d71ec ("ARM: dts: rockchip: Limit WiFi TX power on
rk3288-veyron-jerry") added calibration data for the rk3288-veyron-jerry
platform. The commit message explicitly notes that "the length can vary
between hw versions", as documented in the original text binding.

The current YAML schema enforces fixed maximum lengths for calibration
data arrays, which causes dtbs_check warnings for rk3288-veyron-jerry.dts.

Relax the constraints for the two properties that have
variable-length data in this platform by adding minItems based on the
actual data used in the downstream kernel:

- marvell,caldata-txpwrlimit-2g: 508 bytes (from rk3288-veyron-jerry.dts)
- marvell,caldata-txpwrlimit-5g-sub2: 744 bytes (from 
rk3288-veyron-jerry.dts)

The original maxItems values are preserved as upper bounds to maintain
validation for other platforms while accommodating this specific
hardware variant.

Fixes: 25f855413885 ("dt-bindings: net: wireless: convert marvel-8xxx.txt to yaml format")
Signed-off-by: Fabio Estevam <festevam@gmail.com>
---
 .../devicetree/bindings/net/wireless/marvell,sd8787.yaml        | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/wireless/marvell,sd8787.yaml b/Documentation/devicetree/bindings/net/wireless/marvell,sd8787.yaml
index 930b700b73d0..0d5b4274f151 100644
--- a/Documentation/devicetree/bindings/net/wireless/marvell,sd8787.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/marvell,sd8787.yaml
@@ -37,6 +37,7 @@ properties:
   marvell,caldata-txpwrlimit-2g:
     $ref: /schemas/types.yaml#/definitions/uint8-array
     description: Calibration data for the 2GHz band.
+    minItems: 508
     maxItems: 566
 
   marvell,caldata-txpwrlimit-5g-sub0:
@@ -52,6 +53,7 @@ properties:
   marvell,caldata-txpwrlimit-5g-sub2:
     $ref: /schemas/types.yaml#/definitions/uint8-array
     description: Calibration data for sub-band 2 in the 5GHz band.
+    minItems: 316
     maxItems: 750
 
   marvell,caldata-txpwrlimit-5g-sub3:
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH 1/2] mt76: connac: fix txpower_cur not updated in mt76_connac_mcu_set_rate_txpower()
From: bryam vargas @ 2026-03-11 20:55 UTC (permalink / raw)
  To: Sean Wang
  Cc: linux-wireless, nbd, lorenzo,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <CANAPQzjiBf8Rqphn2SypYN2O6bddj6vB=63Mp=T5YVEt2oGvyw@mail.gmail.com>

Changes in v2:
- patch 1: implement mt7921-specific .get_txpower callback instead of
  updating txpower_cur in the write path, as suggested by Sean Wang
- patch 2: trigger USB reset only when mt792xu_wfsys_reset() returns
  -ETIMEDOUT, avoiding the race condition with async
  usb_queue_reset_device(), as suggested by Sean Wang

Both patches compile clean against v6.18 and tested for two days on
MT7921U USB at 2400m altitude (Bogotá, Colombia).

Bryam Vargas (2):
  mt76: mt7921: add mt7921-specific get_txpower callback
  mt76: mt7921u: trigger USB reset only on wfsys timeout

^ permalink raw reply

* Re: [PATCH 1/2] mt76: connac: fix txpower_cur not updated in mt76_connac_mcu_set_rate_txpower()
From: bryam vargas @ 2026-03-11 20:57 UTC (permalink / raw)
  To: Sean Wang
  Cc: linux-wireless, nbd, lorenzo,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <CANAPQzgiE1rMP3F=5NJg3hp2uBXtq44+vTRBdkHwdfHyXJ8MQQ@mail.gmail.com>

From 6c75ad481f0c3667d6ae2a2c8f7c2df08b1d52b5 Mon Sep 17 00:00:00 2001
From: bryam <bryamestebanvargas@gmail.com>
Date: Mon, 9 Mar 2026 11:52:53 -0500
Subject: [PATCH v2 1/2] mt76: mt7921: add mt7921-specific get_txpower callback

Instead of updating txpower_cur in the write path
(mt76_connac_mcu_set_rate_txpower), implement a mt7921-specific
.get_txpower callback that derives the reported TX power directly
from the SKU limits at query time.

This avoids mixing write-side configuration with reporting logic.
The callback uses mt76_get_power_bound() for SAR constraints and
chain delta, then mt76_get_rate_power_limits() for per-rate EEPROM
limits, yielding the actual TX power value.

Fixes: 3b4a3bdba808 ("mt76: mt7921: add support for reporting tx power")
Signed-off-by: Bryam Vargas <bryamestebanvargas@gmail.com>
---
 .../net/wireless/mediatek/mt76/mt7921/main.c  | 27 ++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 67383c4..35454e5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -1517,6 +1517,31 @@ static void mt7921_rfkill_poll(struct ieee80211_hw *hw)
     wiphy_rfkill_set_hw_state(hw->wiphy, ret ? false : true);
 }

+
+static int mt7921_get_txpower(struct ieee80211_hw *hw,
+                  struct ieee80211_vif *vif,
+                  unsigned int link_id, int *dbm)
+{
+    struct mt76_phy *phy = mt76_vif_phy(hw, vif);
+    struct mt76_power_limits limits;
+    int n_chains, delta;
+    s8 tx_power;
+
+    if (!phy)
+        return -EINVAL;
+
+    if (!phy->chandef.chan)
+        return mt76_get_txpower(hw, vif, link_id, dbm);
+
+    n_chains = hweight16(phy->chainmask);
+    delta = mt76_tx_power_path_delta(n_chains);
+    tx_power = mt76_get_power_bound(phy, phy->chandef.chan->max_power);
+    tx_power = mt76_get_rate_power_limits(phy, phy->chandef.chan,
+                          &limits, tx_power);
+    *dbm = DIV_ROUND_UP(tx_power + delta, 2);
+    return 0;
+}
+
 const struct ieee80211_ops mt7921_ops = {
     .tx = mt792x_tx,
     .start = mt7921_start,
@@ -1541,7 +1566,7 @@ const struct ieee80211_ops mt7921_ops = {
     .wake_tx_queue = mt76_wake_tx_queue,
     .release_buffered_frames = mt76_release_buffered_frames,
     .channel_switch_beacon = mt7921_channel_switch_beacon,
-    .get_txpower = mt76_get_txpower,
+    .get_txpower = mt7921_get_txpower,
     .get_stats = mt792x_get_stats,
     .get_et_sset_count = mt792x_get_et_sset_count,
     .get_et_strings = mt792x_get_et_strings,
--
2.43.0

^ permalink raw reply related

* Re: [PATCH 1/2] mt76: connac: fix txpower_cur not updated in mt76_connac_mcu_set_rate_txpower()
From: bryam vargas @ 2026-03-11 20:58 UTC (permalink / raw)
  To: Sean Wang
  Cc: linux-wireless, nbd, lorenzo,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <CANAPQzgD312EPSbvaQTE6U+wn85L65+xZHms7DP509ApxWvSZA@mail.gmail.com>

From 9fabc33e722f321b4048ada6d4667ddacbb1495a Mon Sep 17 00:00:00 2001
From: bryam <bryamestebanvargas@gmail.com>
Date: Mon, 9 Mar 2026 12:25:37 -0500
Subject: [PATCH v2 2/2] mt76: mt7921u: trigger USB reset only on wfsys timeout

Instead of unconditionally scheduling a USB device reset at the start
of the reset sequence, trigger it only when mt792xu_wfsys_reset()
returns -ETIMEDOUT, which indicates the chip is in a latched state
(SEFI - Single Event Functional Interrupt) where register writes over
USB become silent no-ops.

This avoids the race condition where usb_queue_reset_device() was
scheduled asynchronously while the driver continued normal reset
operations on the same device.

Tested-on: Minisforum NAB9 (MT7921U USB adapter) at 2400m altitude,
           Bogota, Colombia. Cosmic radiation causes periodic SEFI
           events; USB reset restores connectivity without intervention.

Signed-off-by: Bryam Vargas <bryamestebanvargas@gmail.com>
---
 .../net/wireless/mediatek/mt76/mt7921/usb.c   | 32 +++++++++----------
 .../net/wireless/mediatek/mt76/mt792x_usb.c   | 16 ++++------
 2 files changed, 23 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
index 8c8c78f..44c7437 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
@@ -86,33 +86,33 @@ static int mt7921u_mcu_init(struct mt792x_dev *dev)

 static int mt7921u_mac_reset(struct mt792x_dev *dev)
 {
-    struct usb_interface *intf = to_usb_interface(dev->mt76.dev);
     int err;

     mt76_txq_schedule_all(&dev->mphy);
     mt76_worker_disable(&dev->mt76.tx_worker);
-
     set_bit(MT76_RESET, &dev->mphy.state);
     set_bit(MT76_MCU_RESET, &dev->mphy.state);
-
     wake_up(&dev->mt76.mcu.wait);
     skb_queue_purge(&dev->mt76.mcu.res_q);
-
     mt76u_stop_rx(&dev->mt76);
     mt76u_stop_tx(&dev->mt76);

-    /* When the chip enters a latched state (SEFI - Single Event
-     * Functional Interrupt, e.g. from cosmic radiation at altitude),
-     * all register writes over USB become silent no-ops.
-     * usb_queue_reset_device() electrically resets the chip via the
-     * USB hub regardless of internal state -- identical to probe().
-     * Async variant required to avoid deadlock in workqueue context.
-     */
-    dev_warn(dev->mt76.dev,
-         "mt7921u: scheduling USB reset for chip recovery\n");
-    usb_queue_reset_device(intf);
-
-    mt792xu_wfsys_reset(dev);
+    err = mt792xu_wfsys_reset(dev);
+    if (err == -ETIMEDOUT) {
+        /* Chip is in a latched state (SEFI - Single Event Functional
+         * Interrupt, e.g. from cosmic radiation at altitude).
+         * Register writes over USB become silent no-ops; schedule an
+         * electrical USB reset via the hub as last resort.
+         * usb_queue_reset_device() is async to avoid deadlock in
+         * workqueue context.
+         */
+        struct usb_interface *intf = to_usb_interface(dev->mt76.dev);
+
+        dev_warn(dev->mt76.dev,
+             "mt7921u: wfsys reset timed out, scheduling USB reset\n");
+        usb_queue_reset_device(intf);
+        goto out;
+    }

     clear_bit(MT76_MCU_RESET, &dev->mphy.state);
     err = mt76u_resume_rx(&dev->mt76);
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
index cfd385e..4737384 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
@@ -269,7 +269,6 @@ EXPORT_SYMBOL_GPL(mt792xu_wfsys_reset);

 int mt792xu_init_reset(struct mt792x_dev *dev)
 {
-    struct usb_interface *intf = to_usb_interface(dev->mt76.dev);

     set_bit(MT76_RESET, &dev->mphy.state);

@@ -279,15 +278,14 @@ int mt792xu_init_reset(struct mt792x_dev *dev)
     mt76u_stop_rx(&dev->mt76);
     mt76u_stop_tx(&dev->mt76);

-    /* Same rationale as mt7921u_mac_reset(): if the chip is in a
-     * latched state (SEFI), register writes over USB are no-ops.
-     * Schedule a USB port reset before software reset sequence.
-     */
-    dev_warn(dev->mt76.dev,
-         "mt7921u: scheduling USB device reset (init_reset path)\n");
-    usb_queue_reset_device(intf);
+    if (mt792xu_wfsys_reset(dev) == -ETIMEDOUT) {
+        struct usb_interface *intf = to_usb_interface(dev->mt76.dev);
+
+        dev_warn(dev->mt76.dev,
+             "mt792xu: wfsys reset timed out, scheduling USB reset\n");
+        usb_queue_reset_device(intf);
+    }

-    mt792xu_wfsys_reset(dev);

     clear_bit(MT76_RESET, &dev->mphy.state);

--
2.43.0

^ permalink raw reply related

* Re: [PATCH v3 19/21] wifi: rtl8xxxu: add hw crypto support for AP mode
From: Bitterblue Smith @ 2026-03-11 22:16 UTC (permalink / raw)
  To: Ping-Ke Shih, Martin Kaistra, linux-wireless@vger.kernel.org
  Cc: Jes Sorensen, Sebastian Andrzej Siewior
In-Reply-To: <deb687c2fd62467ebcf139acd8aae9c0@realtek.com>

On 11/03/2026 04:38, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> On 25/02/2026 04:28, Ping-Ke Shih wrote:
>>> Martin Kaistra <martin.kaistra@linutronix.de> wrote:
>>>> Am 21.02.26 um 23:09 schrieb Bitterblue Smith:
>>>>> On 22/12/2023 12:14, Martin Kaistra wrote:
>>>>>> Add a custom function for allocating entries in the sec cam. This allows
>>>>>> us to store multiple keys with the same keyidx.
>>>>>>
>>>>>> The maximum number of sec cam entries for 8188f is 16 according to the
>>>>>> vendor driver. Add the number to rtl8xxxu_fileops, so that other chips
>>>>>> which might support more entries, can set a different number there.
>>>>>>
>>>>>> Set the bssid as mac address for group keys instead of just using the
>>>>>> ethernet broadcast address and use BIT(6) in the sec cam ctrl entry
>>>>>> for differentiating them from pairwise keys like in the vendor driver.
>>>>>>
>>>>>> Add the TXDESC_EN_DESC_ID bit and the hw_key_idx to tx
>>>>>> broadcast/multicast packets in AP mode.
>>>>>>
>>>>>> Finally, allow the usage of rtl8xxxu_set_key() for AP mode.
>>>>>>
>>>>>> Signed-off-by: Martin Kaistra <martin.kaistra@linutronix.de>
>>>>>> Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
>>>>>> ---
>>>>>>   .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h  |  5 ++
>>>>>>   .../realtek/rtl8xxxu/rtl8xxxu_8188f.c         |  1 +
>>>>>>   .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 48 +++++++++++++++----
>>>>>>   3 files changed, 44 insertions(+), 10 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
>>>> b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
>>>>>> index c5e6d8f7d26bd..62e6318bc0924 100644
>>>>>> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
>>>>>> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
>>>>>> @@ -498,6 +498,7 @@ struct rtl8xxxu_txdesc40 {
>>>>>>   #define DESC_RATE_ID_SHIFT         16
>>>>>>   #define DESC_RATE_ID_MASK          0xf
>>>>>>   #define TXDESC_NAVUSEHDR           BIT(20)
>>>>>> +#define TXDESC_EN_DESC_ID           BIT(21)
>>>>>>   #define TXDESC_SEC_RC4                     0x00400000
>>>>>>   #define TXDESC_SEC_AES                     0x00c00000
>>>>>>   #define TXDESC_PKT_OFFSET_SHIFT            26
>>>>>> @@ -1775,6 +1776,7 @@ struct rtl8xxxu_cfo_tracking {
>>>>>>   #define RTL8XXXU_MAX_MAC_ID_NUM    128
>>>>>>   #define RTL8XXXU_BC_MC_MACID       0
>>>>>>   #define RTL8XXXU_BC_MC_MACID1      1
>>>>>> +#define RTL8XXXU_MAX_SEC_CAM_NUM    64
>>>>>>
>>>>>>   struct rtl8xxxu_priv {
>>>>>>      struct ieee80211_hw *hw;
>>>>>> @@ -1908,6 +1910,7 @@ struct rtl8xxxu_priv {
>>>>>>      char led_name[32];
>>>>>>      struct led_classdev led_cdev;
>>>>>>      DECLARE_BITMAP(mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
>>>>>> +    DECLARE_BITMAP(cam_map, RTL8XXXU_MAX_SEC_CAM_NUM);
>>>>>>   };
>>>>>>
>>>>>>   struct rtl8xxxu_sta_info {
>>>>>> @@ -1919,6 +1922,7 @@ struct rtl8xxxu_sta_info {
>>>>>>
>>>>>>   struct rtl8xxxu_vif {
>>>>>>      int port_num;
>>>>>> +    u8 hw_key_idx;
>>>>>>   };
>>>>>>
>>>>>>   struct rtl8xxxu_rx_urb {
>>>>>> @@ -1993,6 +1997,7 @@ struct rtl8xxxu_fileops {
>>>>>>      u16 max_aggr_num;
>>>>>>      u8 supports_ap:1;
>>>>>>      u16 max_macid_num;
>>>>>> +    u16 max_sec_cam_num;
>>>>>>      u32 adda_1t_init;
>>>>>>      u32 adda_1t_path_on;
>>>>>>      u32 adda_2t_path_on_a;
>>>>>> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
>>>> b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
>>>>>> index 1e1c8fa194cb8..574a5fe951543 100644
>>>>>> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
>>>>>> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
>>>>>> @@ -1751,6 +1751,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
>>>>>>      .max_aggr_num = 0x0c14,
>>>>>>      .supports_ap = 1,
>>>>>>      .max_macid_num = 16,
>>>>>> +    .max_sec_cam_num = 16,
>>>>>>      .adda_1t_init = 0x03c00014,
>>>>>>      .adda_1t_path_on = 0x03c00014,
>>>>>>      .trxff_boundary = 0x3f7f,
>>>>>> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
>>>> b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
>>>>>> index ecf54eb8dba61..7aafae9fe76b8 100644
>>>>>> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
>>>>>> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
>>>>>> @@ -4559,8 +4559,10 @@ static void rtl8xxxu_cam_write(struct rtl8xxxu_priv
>> *priv,
>>>>>>       * This is a bit of a hack - the lower bits of the cipher
>>>>>>       * suite selector happens to match the cipher index in the CAM
>>>>>>       */
>>>>>> -    addr = key->keyidx << CAM_CMD_KEY_SHIFT;
>>>>>> +    addr = key->hw_key_idx << CAM_CMD_KEY_SHIFT;
>>>>>>      ctrl = (key->cipher & 0x0f) << 2 | key->keyidx | CAM_WRITE_VALID;
>>>>>> +    if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
>>>>>> +            ctrl |= BIT(6);
>>>>>>
>>>>>>      for (j = 5; j >= 0; j--) {
>>>>>>              switch (j) {
>>>>>> @@ -5546,13 +5548,14 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
>>>>>>      struct rtl8xxxu_tx_urb *tx_urb;
>>>>>>      struct ieee80211_sta *sta = NULL;
>>>>>>      struct ieee80211_vif *vif = tx_info->control.vif;
>>>>>> +    struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
>>>>>>      struct device *dev = &priv->udev->dev;
>>>>>>      u32 queue, rts_rate;
>>>>>>      u16 pktlen = skb->len;
>>>>>>      int tx_desc_size = priv->fops->tx_desc_size;
>>>>>>      u8 macid;
>>>>>>      int ret;
>>>>>> -    bool ampdu_enable, sgi = false, short_preamble = false;
>>>>>> +    bool ampdu_enable, sgi = false, short_preamble = false, bmc = false;
>>>>>>
>>>>>>      if (skb_headroom(skb) < tx_desc_size) {
>>>>>>              dev_warn(dev,
>>>>>> @@ -5594,10 +5597,14 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
>>>>>>              tx_desc->txdw0 =
>>>>>>                      TXDESC_OWN | TXDESC_FIRST_SEGMENT |
>> TXDESC_LAST_SEGMENT;
>>>>>>      if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
>>>>>> -        is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
>>>>>> +        is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
>>>>>>              tx_desc->txdw0 |= TXDESC_BROADMULTICAST;
>>>>>> +            bmc = true;
>>>>>> +    }
>>>>>> +
>>>>>>
>>>>>>      tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT);
>>>>>> +    macid = rtl8xxxu_get_macid(priv, sta);
>>>>>>
>>>>>>      if (tx_info->control.hw_key) {
>>>>>>              switch (tx_info->control.hw_key->cipher) {
>>>>>> @@ -5612,6 +5619,10 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
>>>>>>              default:
>>>>>>                      break;
>>>>>>              }
>>>>>> +            if (bmc && rtlvif->hw_key_idx != 0xff) {
>>>>>> +                    tx_desc->txdw1 |= TXDESC_EN_DESC_ID;
>>>>>> +                    macid = rtlvif->hw_key_idx;
>>>>>> +            }
>>>>>>      }
>>>>>>
>>>>>>      /* (tx_info->flags & IEEE80211_TX_CTL_AMPDU) && */
>>>>>> @@ -5655,7 +5666,6 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
>>>>>>      else
>>>>>>              rts_rate = 0;
>>>>>>
>>>>>> -    macid = rtl8xxxu_get_macid(priv, sta);
>>>>>>      priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi,
>> short_preamble,
>>>>>>                              ampdu_enable, rts_rate, macid);
>>>>>>
>>>>>> @@ -6667,6 +6677,7 @@ static int rtl8xxxu_add_interface(struct ieee80211_hw
>> *hw,
>>>>>>
>>>>>>      priv->vifs[port_num] = vif;
>>>>>>      rtlvif->port_num = port_num;
>>>>>> +    rtlvif->hw_key_idx = 0xff;
>>>>>>
>>>>>>      rtl8xxxu_set_linktype(priv, vif->type, port_num);
>>>>>>      ether_addr_copy(priv->mac_addr, vif->addr);
>>>>>> @@ -6843,11 +6854,19 @@ static int rtl8xxxu_set_rts_threshold(struct
>> ieee80211_hw *hw, u32 rts)
>>>>>>      return 0;
>>>>>>   }
>>>>>>
>>>>>> +static int rtl8xxxu_get_free_sec_cam(struct ieee80211_hw *hw)
>>>>>> +{
>>>>>> +    struct rtl8xxxu_priv *priv = hw->priv;
>>>>>> +
>>>>>> +    return find_first_zero_bit(priv->cam_map,
>> priv->fops->max_sec_cam_num);
>>>>>> +}
>>>>>> +
>>>>>>   static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd
>> cmd,
>>>>>>                          struct ieee80211_vif *vif,
>>>>>>                          struct ieee80211_sta *sta,
>>>>>>                          struct ieee80211_key_conf *key)
>>>>>>   {
>>>>>> +    struct rtl8xxxu_vif *rtlvif = (struct rtl8xxxu_vif *)vif->drv_priv;
>>>>>>      struct rtl8xxxu_priv *priv = hw->priv;
>>>>>>      struct device *dev = &priv->udev->dev;
>>>>>>      u8 mac_addr[ETH_ALEN];
>>>>>> @@ -6859,9 +6878,6 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw,
>> enum set_key_cmd cmd,
>>>>>>      dev_dbg(dev, "%s: cmd %02x, cipher %08x, index %i\n",
>>>>>>              __func__, cmd, key->cipher, key->keyidx);
>>>>>>
>>>>>> -    if (vif->type != NL80211_IFTYPE_STATION)
>>>>>> -            return -EOPNOTSUPP;
>>>>>> -
>>>>>>      if (key->keyidx > 3)
>>>>>>              return -EOPNOTSUPP;
>>>>>>
>>>>>> @@ -6885,7 +6901,7 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw,
>> enum set_key_cmd cmd,
>>>>>>              ether_addr_copy(mac_addr, sta->addr);
>>>>>>      } else {
>>>>>>              dev_dbg(dev, "%s: group key\n", __func__);
>>>>>> -            eth_broadcast_addr(mac_addr);
>>>>>> +            ether_addr_copy(mac_addr, vif->bss_conf.bssid);
>>>>>>      }
>>>>>>
>>>>>>      val16 = rtl8xxxu_read16(priv, REG_CR);
>>>>>> @@ -6899,16 +6915,28 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw,
>> enum set_key_cmd cmd,
>>>>>>
>>>>>>      switch (cmd) {
>>>>>>      case SET_KEY:
>>>>>> -            key->hw_key_idx = key->keyidx;
>>>>>> +
>>>>>> +            retval = rtl8xxxu_get_free_sec_cam(hw);
>>>>>> +            if (retval < 0)
>>>>>> +                    return -EOPNOTSUPP;
>>>>>> +
>>>>>> +            key->hw_key_idx = retval;
>>>>>> +
>>>>>> +            if (vif->type == NL80211_IFTYPE_AP && !(key->flags &
>> IEEE80211_KEY_FLAG_PAIRWISE))
>>>>>> +                    rtlvif->hw_key_idx = key->hw_key_idx;
>>>>>> +
>>>>>>              key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
>>>>>>              rtl8xxxu_cam_write(priv, key, mac_addr);
>>>>>> +            set_bit(key->hw_key_idx, priv->cam_map);
>>>>>
>>>>> Hi Martin,
>>>>
>>>> Hi Bitterblue,
>>>>
>>>>>
>>>>> It turns out RTL8188CUS and RTL8192CU don't like this patch, specifically
>>>>> when we use iwd. After the WPA2 handshake no more data is transmitted.
>>>>>
>>>>> Before this patch, key->hw_key_idx was the same as key->keyidx. After
>>>>> this patch, when we use iwd, the group key is installed first. It has
>>>>> key->keyidx = 1, but it gets key->hw_key_idx = 0. The pairwise key is
>>>>> installed second. It has key->keyidx = 0, but it gets key->hw_key_idx = 1.
>>>>> Both keyidx and hw_key_idx are passed to the chip in rtl8xxxu_cam_write().
>>>>>
>>>>> It's fine with wpa_supplicant. wpa_supplicant installs the pairwise key
>>>>> first, with key->keyidx = 0, then the group key, with key->keyidx = 1.
>>>>>
>>>>> This patch imitating rtw88 makes the old chips work again with iwd.
>>>>> What do you think?
>>>>
>>>> So you reserve the first 4 entries for group keys and use key->keyidx as
>>>> key->hw_key_idx directly for those, right? Does that work if 2 virtual
>>>> interfaces are used at the same time?
>>>> I will do some tests in the next days, but I suspect this be an issue.
>>>
>>> Ah. I'm not aware that rtl8xxxu can support 2 virtual interfaces, and
>>> only RTL8188FU declares .supports_concurrent = 1, so maybe we can have
>>> special handling for this chip?
>>
>> I would like to enable supports_concurrent for more chips, if I can test
>> this feature.
>>
>>>
>>> I'd share some information about security CAM for reference. Since data is
>>> quite old (10+ years), I can't guarantee all are correct.
>>>
>>> 1. default key switch in rtl8xxxu_set_key()
>>>    SEC_CFG_TXBC_USE_DEFKEY and SEC_CFG_RXBC_USE_DEFKEY mean that
>>>    broadcast/multicast packets use default key (CAM entries 0~3 for
>>>    keyidx 0~3).
>>>    For two interfaces case, that'd a problem, so maybe we should use
>>>    software encryption/decryption for non-pairwise key.
>>>
>>>       val8 = SEC_CFG_TX_SEC_ENABLE | SEC_CFG_TXBC_USE_DEFKEY |
>>>               SEC_CFG_RX_SEC_ENABLE | SEC_CFG_RXBC_USE_DEFKEY;
>>>       val8 |= SEC_CFG_TX_USE_DEFKEY | SEC_CFG_RX_USE_DEFKEY;
>>>       rtl8xxxu_write8(priv, REG_SECURITY_CFG, val8);
>>>
>>> 2. group key (GK) field of security CAM in rtl8xxxu_cam_write()
>>>    The group key field of security CAM is BIT(6) which isn't supported
>>>    by earlier chips (sorry I have no data about the exact chips).
>>>
>>
>> BIT 6 is used in the rtl8188eu driver, and not used in the rtl8192cu driver,
>> so I assume it's just the older RTL8188CU/RTL8192CU and RTL8723AU that don't
>> support it.
>>
>>>    If a chip can support group key field, the CAM layout with default key
>>>    enabled for two interfaces (STA-1+AP-1) can be
>>>
>>>    STA-1 <-> AP-10
>>>    AP-1  <-> STA-20
>>>
>>>    CAM  GK   MAC    KEY
>>>     0
>>>     1   1    00:    AP-1 (GTK)  // should be on entry 0~3 depends on key_idx
>>>     2
>>>     3
>>>     4
>>>     5   1    AP-10  AP-10 (GTK)  // can be on any entry after 4
>>>     6
>>>
>>
>> What are the numbers 1, 10, and 20 in "AP-1", "AP-10", "STA-20" ?
> 
> Just represent different roles. 
> 
> For rtl8xxxu, two interfaces are STA-1 and AP-1, and STA-1 connect to AP-10,
> and AP-1 is connected from STA-20.
> 
> I don't add pairwise key to above example, because it is simple, just one
> entry to a PTK. Instead, I only list group key in the example.
> 
> For AP role (AP-1), it can send broadcast packets to many stations, so
> use default key.
> (but it should not receive a broadcast packet from stations)
> 
> For station role (STA-1), it should receive broadcast packets from
> specific AP-10, so add an entry with AP-10's MAC address.
> 

Oh, now I understand, thank you.

>>
>>>     (pairwise key can be on any entry after 4)
>>>
>>>       if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
>>>               ctrl |= BIT(6);
>>>
>>> My perspective are
>>> 1. currently default key is enabled, so we should treat CAM entry 0~3 as
>>>    special cases. That means rtl8xxxu_get_free_sec_cam() should be modified
>>>    as Bitterblue's version.
>>>
>>> 2. For two interfaces, I guess RTL8188FU can support GK bit, so it'd be worth
>>>    to try the method of example 2 above.
>>>
>>>    If we want earlier chips can support two interfaces, I think we should
>>>    disable default key.
>>
>> Indeed, the rtl8192cu driver (out of kernel) doesn't set SEC_CFG_TXBC_USE_DEFKEY
>> and SEC_CFG_RXBC_USE_DEFKEY when concurrent mode is enabled.
>>
>>> Seemingly, it is not possible that using hardware
>>>    crypto when operating one interface and then switching to use software>
>> crypto when operating two interfaces. That means broadcast/multicast
>>>    packets should be by software crypto entirely if we want to support two
>>>    interfaces.
>>>
>>> 3. I think rtw88 has similar problem for two interfaces.
>>>
>>>>
>>>>>
>>>>> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c
>>>> b/drivers/net/wireless/realtek/rtl8xxxu/core.c
>>>>> index ee278f0548e4..f7b35655bec5 100644
>>>>> --- a/drivers/net/wireless/realtek/rtl8xxxu/core.c
>>>>> +++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c
>>>>> @@ -6942,7 +6942,8 @@ static int rtl8xxxu_get_free_sec_cam(struct
>> ieee80211_hw *hw)
>>>>>   {
>>>>>       struct rtl8xxxu_priv *priv = hw->priv;
>>>>>
>>>>> -     return find_first_zero_bit(priv->cam_map,
>> priv->fops->max_sec_cam_num);
>>>>> +     return find_next_zero_bit(priv->cam_map,
>> priv->fops->max_sec_cam_num,
>>>>> +                               RTL8XXXU_SEC_DEFAULT_KEY_NUM);
>>>>>   }
>>>>>
>>>>>   static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd
>> cmd,
>>>>> @@ -6999,12 +7000,15 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw,
>> enum set_key_cmd cmd,
>>>>>
>>>>>       switch (cmd) {
>>>>>       case SET_KEY:
>>>>> +             if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
>>>>> +                     retval = rtl8xxxu_get_free_sec_cam(hw);
>>>>> +                     if (retval < 0)
>>>>> +                             return -EOPNOTSUPP;
>>>>>
>>>>> -             retval = rtl8xxxu_get_free_sec_cam(hw);
>>>>> -             if (retval < 0)
>>>>> -                     return -EOPNOTSUPP;
>>>>> -
>>>>> -             key->hw_key_idx = retval;
>>>>> +                     key->hw_key_idx = retval;
>>>>> +             } else {
>>>>> +                     key->hw_key_idx = key->keyidx;
>>>>> +             }
>>>>>
>>>>>               if (vif->type == NL80211_IFTYPE_AP && !(key->flags &
>> IEEE80211_KEY_FLAG_PAIRWISE))
>>>>>                       rtlvif->hw_key_idx = key->hw_key_idx;
>>>>> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
>>>> b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
>>>>> index 4b05dba22e67..188f4bbe99cd 100644
>>>>> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
>>>>> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
>>>>> @@ -1788,6 +1788,7 @@ struct rtl8xxxu_cfo_tracking {
>>>>>   #define RTL8XXXU_BC_MC_MACID        0
>>>>>   #define RTL8XXXU_BC_MC_MACID1       1
>>>>>   #define RTL8XXXU_MAX_SEC_CAM_NUM    64
>>>>> +#define RTL8XXXU_SEC_DEFAULT_KEY_NUM 4
>>>>>
>>>>>   struct rtl8xxxu_priv {
>>>>>       struct ieee80211_hw *hw;
>>>
> 


^ permalink raw reply

* Re: [PATCH 49/61] media: Prefer IS_ERR_OR_NULL over manual NULL check
From: Kieran Bingham @ 2026-03-11 23:03 UTC (permalink / raw)
  To: Philipp Hahn, amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel,
	dri-devel, gfs2, intel-gfx, intel-wired-lan, iommu, kvm,
	linux-arm-kernel, linux-block, linux-bluetooth, linux-btrfs,
	linux-cifs, linux-clk, linux-erofs, linux-ext4, linux-fsdevel,
	linux-gpio, linux-hyperv, linux-input, linux-kernel, linux-leds,
	linux-media, linux-mips, linux-mm, linux-modules, linux-mtd,
	linux-nfs, linux-omap, linux-phy, lin 
  Cc: Shuah Khan, Mauro Carvalho Chehab
In-Reply-To: <20260310-b4-is_err_or_null-v1-49-bd63b656022d@avm.de>

Quoting Philipp Hahn (2026-03-10 11:49:15)
> Prefer using IS_ERR_OR_NULL() over using IS_ERR() and a manual NULL
> check.
> 
> Change generated with coccinelle.
> 
> To: Shuah Khan <skhan@linuxfoundation.org>
> To: Kieran Bingham <kieran.bingham@ideasonboard.com>
> To: Mauro Carvalho Chehab <mchehab@kernel.org>
> Cc: linux-media@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Philipp Hahn <phahn-oss@avm.de>
> ---
>  drivers/media/test-drivers/vimc/vimc-streamer.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/test-drivers/vimc/vimc-streamer.c b/drivers/media/test-drivers/vimc/vimc-streamer.c
> index 15d863f97cbf96b7ca7fbf3d7b6b6ec39fcc8ae3..da5aca50bcb4990c06f28e5a883eb398606991e9 100644
> --- a/drivers/media/test-drivers/vimc/vimc-streamer.c
> +++ b/drivers/media/test-drivers/vimc/vimc-streamer.c
> @@ -167,7 +167,7 @@ static int vimc_streamer_thread(void *data)
>                 for (i = stream->pipe_size - 1; i >= 0; i--) {
>                         frame = stream->ved_pipeline[i]->process_frame(
>                                         stream->ved_pipeline[i], frame);
> -                       if (!frame || IS_ERR(frame))
> +                       if (IS_ERR_OR_NULL(frame))

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

>                                 break;
>                 }
>                 //wait for 60hz
> 
> -- 
> 2.43.0
>

^ permalink raw reply

* [PATCH wireless-next 03/28] wifi: iwlwifi: mld: Add check for null vif in stats callback.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

A crash was seen in this area, protect against null.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/stats.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/stats.c b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
index 7b8709716324..8d6bd7219b94 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/stats.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
@@ -415,7 +415,7 @@ iwl_mld_process_per_link_stats(struct iwl_mld *mld,
 
 		bss_conf = wiphy_dereference(mld->wiphy,
 					     mld->fw_id_to_bss_conf[fw_id]);
-		if (!bss_conf || bss_conf->vif->type != NL80211_IFTYPE_STATION)
+		if (!bss_conf || !bss_conf->vif || bss_conf->vif->type != NL80211_IFTYPE_STATION)
 			continue;
 
 		link_stats = &per_link[fw_id];
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 01/28] wifi: iwlwifi: mld:  Check for NULL before lookup.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Do not call iwl_mld_sta_from_mac80211(sta) unless we have
verified sta is non NULL.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/agg.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
index 3bf36f8f6874..a757077b0a7a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
@@ -194,7 +194,7 @@ iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
 	struct iwl_mld_baid_data *baid_data;
 	struct iwl_mld_reorder_buffer *buffer;
 	struct iwl_mld_reorder_buf_entry *entries;
-	struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
+	struct iwl_mld_sta *mld_sta;
 	struct iwl_mld_link_sta *mld_link_sta;
 	u32 reorder = le32_to_cpu(desc->reorder_data);
 	bool amsdu, last_subframe, is_old_sn, is_dup;
@@ -221,6 +221,8 @@ iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
 		      "Got valid BAID without a valid station assigned\n"))
 		return IWL_MLD_PASS_SKB;
 
+	mld_sta = iwl_mld_sta_from_mac80211(sta);
+
 	/* not a data packet */
 	if (!ieee80211_is_data_qos(hdr->frame_control) ||
 	    is_multicast_ether_addr(hdr->addr1))
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 00/28] iwlwifi + mac80211 stability
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

mac80211 and iwlwifi stability patches from our internal
tree.

General test case is 40 be200 radios attempting to connect and
run max traffic against an AP that doesn't really like that many
eMLSR stations.  Firmware crashes, AP rejections, assoc timeouts,
and other problems are seen often, and that seems to hit a lot
of edge cases.  Kernel has kasan, lockdep and other debugging
enabled.

This was primarily tested against 6.18.14 stable kernel, but has been
revised to work against wireless-next and it is passing at least the
first hour of tests so far.  Likely some problems still remain in
this area.

checkpatch seems mostly satisfied.

Ben Greear (28):
  wifi: iwlwifi: mld:  Check for NULL before lookup.
  wifi: iwlwifi: mld: Fix un-set return value in error case.
  wifi: iwlwifi: mld: Add check for null vif in stats callback.
  wifi: mac80211:  Check debugfs creation return values.
  wifi: mac80211: do not fail taking sta to lower state.
  wifi: mac80211: Mark sta as uploaded if single transition succeeds.
  wifi: mac80211:  Fix use-after-free of debugfs inodes.
  wifi: mac80211: Debugfs safety checks.
  wifi: mac80211: Use warn-on-once in drv_remove_chanctxt
  wifi: mac80211: Ensure sta debugfs is not double-freed.
  wifi: iwlwifi: mld: Fix stale reference in fw_id_to_link_sta
  wifi: iwlwifi: mld:  Improve logging in error cases.
  wifi: iwlwifi: mld: Remove warning about BAID.
  wifi: mac80211: Add dmesg log regarding warn-on in drv-stop.
  wifi: iwlwifi: mld: Fix use-after-free of bss_conf
  wifi: iwlwifi: mld: Check for null in iwl_mld_wait_sta_txqs_empty
  wifi: iwlwifi: mld: use warn-on-once in error path.
  wifi: iwlwifi: mld: Use warn-on-once in emlsr exit logic.
  wifi: iwlwifi: mld: Improve error message in rx path.
  wifi: iwlwifi: mld: Improve logging message.
  wifi: iwlwifi: mld: Protect from null mld_sta
  wifi: mac80211: Add force-cleanup call to driver.
  wifi: iwlwifi: mld: Support force-cleanup op
  wifi: iwlwifi: mld: Fix NPE in flush logic.
  wifi: iwlwifi: mld: Fix bad return address in tx code.
  wifi: mac80211: Ensure link work-items are only initialized once.
  wifi: iwlwifi: mld: Convert to WARN_ONCE in link removal path.
  wifi: mac80211: Decrease WARN spam.

 drivers/net/wireless/intel/iwlwifi/mld/agg.c  |  20 +++-
 drivers/net/wireless/intel/iwlwifi/mld/link.c |  42 +++++--
 .../net/wireless/intel/iwlwifi/mld/mac80211.c |  21 +++-
 drivers/net/wireless/intel/iwlwifi/mld/mlo.c  |   5 +-
 drivers/net/wireless/intel/iwlwifi/mld/rx.c   |   4 +-
 drivers/net/wireless/intel/iwlwifi/mld/sta.c  |  20 +++-
 drivers/net/wireless/intel/iwlwifi/mld/sta.h  |   2 +-
 .../net/wireless/intel/iwlwifi/mld/stats.c    |   2 +-
 drivers/net/wireless/intel/iwlwifi/mld/tx.h   |   2 +
 include/net/mac80211.h                        |   7 ++
 net/mac80211/debugfs.c                        |  11 ++
 net/mac80211/debugfs_key.c                    |   6 +
 net/mac80211/debugfs_netdev.c                 | 106 +++++++++++++++++-
 net/mac80211/debugfs_sta.c                    |  15 +++
 net/mac80211/driver-ops.c                     |  10 +-
 net/mac80211/driver-ops.h                     |  12 +-
 net/mac80211/ieee80211_i.h                    |   1 +
 net/mac80211/link.c                           |  29 +++--
 net/mac80211/sta_info.c                       |   8 +-
 net/mac80211/util.c                           |   8 +-
 20 files changed, 286 insertions(+), 45 deletions(-)

-- 
2.42.0


^ permalink raw reply

* [PATCH wireless-next 02/28] wifi: iwlwifi: mld: Fix un-set return value in error case.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Ensure 'err' is set in error return path.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index 0c53d6bd9651..d44ec81d2ce4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -2519,7 +2519,7 @@ iwl_mld_change_vif_links(struct ieee80211_hw *hw,
 	struct ieee80211_bss_conf *link_conf;
 	u16 removed = old_links & ~new_links;
 	u16 added = new_links & ~old_links;
-	int err;
+	int err = -EINVAL;
 
 	lockdep_assert_wiphy(mld->wiphy);
 
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 11/28] wifi: iwlwifi: mld: Fix stale reference in fw_id_to_link_sta
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

If memory cannot be allocated, clear the fw_id_to_link_sta so there
is not a dangling pointer that may later be accessed and cause
use-after-free.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/sta.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
index 6b7a89e050e6..c478cee570a2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
@@ -540,8 +540,10 @@ iwl_mld_add_link_sta(struct iwl_mld *mld, struct ieee80211_link_sta *link_sta)
 		mld_link_sta = &mld_sta->deflink;
 	} else {
 		mld_link_sta = kzalloc_obj(*mld_link_sta);
-		if (!mld_link_sta)
+		if (!mld_link_sta) {
+			RCU_INIT_POINTER(mld->fw_id_to_link_sta[fw_id], NULL);
 			return -ENOMEM;
+		}
 	}
 
 	mld_link_sta->fw_id = fw_id;
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 08/28] wifi: mac80211: Debugfs safety checks.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Safety checks in case links are not be properly cleaned up at
the time we are removing netdev debugfs.  Since link debugfs
is child of netdev debugfs, and we are about to recursively clean
up the netdev tree, be sure to null out any debugfs inode pointers
in the child links.

Root cause of the inode use-after-free is something
different, but this patch may also make system more resiliant.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/debugfs_netdev.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index bc2da35db4ae..000859b8c005 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -1037,9 +1037,33 @@ static void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata,
 		add_link_files(&sdata->deflink, sdata->vif.debugfs_dir);
 }
 
+static void
+ieee80211_debugfs_clear_link_ptr(struct ieee80211_sub_if_data *sdata,
+				 struct dentry *dir)
+{
+	struct ieee80211_link_data *link;
+	int i;
+
+	rcu_read_lock();
+
+	if (sdata->vif.debugfs_dir == dir)
+		sdata->vif.debugfs_dir = NULL;
+
+	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+		link = rcu_access_pointer(sdata->link[i]);
+		if (!link)
+			continue;
+
+		if (dir == link->debugfs_dir)
+			link->debugfs_dir = NULL;
+	}
+	rcu_read_unlock();
+}
+
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_link_data *link;
+	struct dentry *dir;
 	int i;
 
 	if (!sdata->vif.debugfs_dir)
@@ -1061,8 +1085,10 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 	}
 	rcu_read_unlock();
 
-	debugfs_remove_recursive(sdata->vif.debugfs_dir);
+	dir = sdata->vif.debugfs_dir;
+	debugfs_remove_recursive(dir);
 	sdata->vif.debugfs_dir = NULL;
+	ieee80211_debugfs_clear_link_ptr(sdata, dir);
 	sdata->debugfs.subdir_stations = NULL;
 }
 
@@ -1151,7 +1177,7 @@ void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link)
 
 	/* Recreate the directory excluding the driver data */
 	debugfs_remove_recursive(link->debugfs_dir);
-	link->debugfs_dir = NULL;
+	ieee80211_debugfs_clear_link_ptr(link->sdata, link->debugfs_dir);
 
 	ieee80211_link_debugfs_add(link);
 }
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 06/28] wifi: mac80211: Mark sta as uploaded if single transition succeeds.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

The hope is that this would allow cleanup code to run properly in
case this fails halfway through.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/sta_info.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 4259e9c13ed7..ad211c714dbb 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -836,18 +836,18 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local,
 		err = drv_sta_state(local, sdata, sta, state, state + 1);
 		if (err)
 			break;
-	}
-
-	if (!err) {
 		/*
 		 * Drivers using legacy sta_add/sta_remove callbacks only
 		 * get uploaded set to true after sta_add is called.
+		 * We are at least somewhat added now.
 		 */
 		if (!local->ops->sta_add)
 			sta->uploaded = true;
-		return 0;
 	}
 
+	if (!err)
+		return 0;
+
 	if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		sdata_info(sdata,
 			   "failed to move IBSS STA %pM to state %d (%d) - keeping it anyway\n",
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 04/28] wifi: mac80211:  Check debugfs creation return values.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Add return error checking for the debugfs directory create
calls.  Assign error pointers to NULL instead of potential error
codes that the create logic may return.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/debugfs.c        | 11 +++++++++++
 net/mac80211/debugfs_key.c    |  6 ++++++
 net/mac80211/debugfs_netdev.c | 33 +++++++++++++++++++++++++++++++++
 net/mac80211/debugfs_sta.c    | 15 +++++++++++++++
 4 files changed, 65 insertions(+)

diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index e8d0a8b71d59..1f428f8a7633 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -680,6 +680,12 @@ void debugfs_hw_add(struct ieee80211_local *local)
 		return;
 
 	local->debugfs.keys = debugfs_create_dir("keys", phyd);
+	if (IS_ERR(local->debugfs.keys)) {
+		pr_err("Failed to create local keys debugfs dir, rv: %ld phyd: 0x%px\n",
+		       (long)(local->debugfs.keys), phyd);
+		local->debugfs.keys = NULL;
+		return;
+	}
 
 	DEBUGFS_ADD(total_ps_buffered);
 	DEBUGFS_ADD(wep_iv);
@@ -705,6 +711,11 @@ void debugfs_hw_add(struct ieee80211_local *local)
 			   phyd, &local->aql_threshold);
 
 	statsd = debugfs_create_dir("statistics", phyd);
+	if (IS_ERR(statsd)) {
+		pr_err("Failed to create local stats debugfs dir, rv: %ld phyd: 0x%px\n",
+		       (long)(statsd), phyd);
+		return;
+	}
 
 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
 	DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount);
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 117f58af5ff9..670bcfa8c4ed 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -335,6 +335,12 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
 	keycount++;
 	key->debugfs.dir = debugfs_create_dir(buf,
 					key->local->debugfs.keys);
+	if (IS_ERR(key->debugfs.dir)) {
+		pr_err("Failed to create key debugfs dir, rv: %ld phyd: 0x%px\n",
+		       (long)(key->debugfs.dir), key->local->debugfs.keys);
+		key->debugfs.dir = NULL;
+		return;
+	}
 
 	sta = key->sta;
 	if (sta) {
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index f3c6a41e4911..51d2ae232a85 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -882,6 +882,11 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
 {
 	struct dentry *dir = debugfs_create_dir("mesh_stats",
 						sdata->vif.debugfs_dir);
+	if (IS_ERR(dir)) {
+		sdata_err(sdata, "Failed to create mesh stats dir, rv: %ld vif dir: 0x%px\n",
+			  (long)(dir), sdata->vif.debugfs_dir);
+		return;
+	}
 #define MESHSTATS_ADD(name)\
 	debugfs_create_file(#name, 0400, dir, sdata, &name##_ops)
 
@@ -897,6 +902,11 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
 {
 	struct dentry *dir = debugfs_create_dir("mesh_config",
 						sdata->vif.debugfs_dir);
+	if (IS_ERR(dir)) {
+		sdata_err(sdata, "Failed to create mesh config dir, rv: %ld vif dir: 0x%px\n",
+			  (long)(dir), sdata->vif.debugfs_dir);
+		return;
+	}
 
 #define MESHPARAMS_ADD(name) \
 	debugfs_create_file(#name, 0600, dir, sdata, &name##_ops)
@@ -1003,10 +1013,25 @@ static void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata,
 	sprintf(buf, "netdev:%s", sdata->name);
 	sdata->vif.debugfs_dir = debugfs_create_dir(buf,
 		sdata->local->hw.wiphy->debugfsdir);
+
+	if (IS_ERR(sdata->vif.debugfs_dir)) {
+		sdata_err(sdata, "Failed to create netdev dir, rv: %ld name: %s wiphy dir: 0x%px\n",
+			  (long)(sdata->vif.debugfs_dir), buf, sdata->local->hw.wiphy->debugfsdir);
+		sdata->vif.debugfs_dir = NULL;
+		return;
+	}
+
 	/* deflink also has this */
 	sdata->deflink.debugfs_dir = sdata->vif.debugfs_dir;
+
 	sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
 							sdata->vif.debugfs_dir);
+	if (IS_ERR(sdata->debugfs.subdir_stations)) {
+		sdata_err(sdata, "Failed to create netdev subdir-stations dir, rv: %ld wiphy dir: 0x%px\n",
+			  (long)(sdata->debugfs.subdir_stations), sdata->vif.debugfs_dir);
+		sdata->debugfs.subdir_stations = NULL;
+		return;
+	}
 	add_files(sdata);
 	if (!mld_vif)
 		add_link_files(&sdata->deflink, sdata->vif.debugfs_dir);
@@ -1058,6 +1083,14 @@ void ieee80211_link_debugfs_add(struct ieee80211_link_data *link)
 		debugfs_create_dir(link_dir_name,
 				   link->sdata->vif.debugfs_dir);
 
+	if (IS_ERR(link->debugfs_dir)) {
+		sdata_err(link->sdata, "Failed to create debugfs dir, rv: %ld  link-dir-name: %s vif dir: 0x%px\n",
+			  (long)(link->debugfs_dir), link_dir_name,
+			  link->sdata->vif.debugfs_dir);
+		link->debugfs_dir = NULL;
+		return;
+	}
+
 	DEBUGFS_ADD(link->debugfs_dir, addr);
 	add_link_files(link, link->debugfs_dir);
 }
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index ef75255d47d5..23cb2099e3b3 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -1250,6 +1250,12 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
 	 * dir might still be around.
 	 */
 	sta->debugfs_dir = debugfs_create_dir(mac, stations_dir);
+	if (IS_ERR(sta->debugfs_dir)) {
+		sdata_err(sdata, "Failed to create sta debugfs dir, rv: %ld name: %s stations dir: 0x%px\n",
+			  (long)(sta->debugfs_dir), mac, stations_dir);
+		sta->debugfs_dir = NULL;
+		return;
+	}
 
 	DEBUGFS_ADD(flags);
 	DEBUGFS_ADD(aid);
@@ -1303,6 +1309,15 @@ void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta)
 			debugfs_create_dir(link_dir_name,
 					   link_sta->sta->debugfs_dir);
 
+		if (IS_ERR(link_sta->debugfs_dir)) {
+			sdata_err(link_sta->sta->sdata,
+				  "Failed to create link-sta debugfs dir, rv: %ld name: %s stations dir: 0x%px\n",
+				  (long)(link_sta->debugfs_dir), link_dir_name,
+				  link_sta->sta->debugfs_dir);
+			link_sta->debugfs_dir = NULL;
+			return;
+		}
+
 		DEBUGFS_ADD(addr);
 	} else {
 		if (WARN_ON(link_sta != &link_sta->sta->deflink))
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 05/28] wifi: mac80211: do not fail taking sta to lower state.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

If sdata-in-driver-check fails, then we assume STA is definitely
not in the driver, and so going to less connected states should not
fail.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/driver-ops.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index 49753b73aba2..59998d0af3ff 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -143,8 +143,12 @@ int drv_sta_state(struct ieee80211_local *local,
 	lockdep_assert_wiphy(local->hw.wiphy);
 
 	sdata = get_bss_sdata(sdata);
-	if (!check_sdata_in_driver(sdata))
+	if (!check_sdata_in_driver(sdata)) {
+		/* Going down should not fail in this case. */
+		if (new_state < old_state)
+			return 0;
 		return -EIO;
+	}
 
 	trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
 	if (local->ops->sta_state) {
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 09/28] wifi: mac80211: Use warn-on-once in drv_remove_chanctxt
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

But still log it to dmesg.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/driver-ops.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 51bf3c7822a7..e2283d7dcd1e 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1035,8 +1035,10 @@ static inline void drv_remove_chanctx(struct ieee80211_local *local,
 	might_sleep();
 	lockdep_assert_wiphy(local->hw.wiphy);
 
-	if (WARN_ON(!ctx->driver_present))
+	if (WARN_ON_ONCE(!ctx->driver_present)) {
+		pr_err("drv-remove-chanctx, NOT driver_present, not sending request to driver.");
 		return;
+	}
 
 	trace_drv_remove_chanctx(local, ctx);
 	if (local->ops->remove_chanctx)
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 14/28] wifi: mac80211: Add dmesg log regarding warn-on in drv-stop.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

And make it WARN_ON_ONCE.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/driver-ops.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index 59998d0af3ff..397a0281412a 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -38,8 +38,10 @@ void drv_stop(struct ieee80211_local *local, bool suspend)
 	might_sleep();
 	lockdep_assert_wiphy(local->hw.wiphy);
 
-	if (WARN_ON(!local->started))
+	if (WARN_ON_ONCE(!local->started)) {
+		pr_err("mac80211: drv-stop called but local is not started.\n");
 		return;
+	}
 
 	trace_drv_stop(local, suspend);
 	local->ops->stop(&local->hw, suspend);
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 23/28] wifi: iwlwifi: mld: Support force-cleanup op
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

This lets mac80211 force the driver to clean up any lingering
configuration, fixing use-after-free in case of unrecoverable
hardware failure.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index badaceb120b3..03810291ed33 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -560,6 +560,18 @@ iwl_mld_restart_cleanup(struct iwl_mld *mld)
 	iwl_mld_ftm_restart_cleanup(mld);
 }
 
+/* mac80211 thinks our driver/firmware/hardware has crashed
+ * and cannot be recovered.  Force clean any existing configuration
+ * (stas, etc), as mac80211 will not attempt further cleanup.
+ */
+static void iwl_mld_mac80211_force_cleanup(struct ieee80211_hw *hw)
+{
+	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
+
+	IWL_ERR(mld, "mac80211-force-cleanup called, calling mld_restart_cleanup.\n");
+	iwl_mld_restart_cleanup(mld);
+}
+
 static
 int iwl_mld_mac80211_start(struct ieee80211_hw *hw)
 {
@@ -2717,6 +2729,7 @@ const struct ieee80211_ops iwl_mld_hw_ops = {
 	.config = iwl_mld_mac80211_config,
 	.get_antenna = iwl_mld_get_antenna,
 	.set_antenna = iwl_mld_set_antenna,
+	.force_cleanup = iwl_mld_mac80211_force_cleanup,
 	.add_interface = iwl_mld_mac80211_add_interface,
 	.remove_interface = iwl_mld_mac80211_remove_interface,
 	.conf_tx = iwl_mld_mac80211_conf_tx,
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 19/28] wifi: iwlwifi: mld: Improve error message in rx path.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Print return code that is causing the failure path.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/rx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
index 214dcfde2fb4..f5c20a3aa869 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c
@@ -2204,8 +2204,8 @@ void iwl_mld_sync_rx_queues(struct iwl_mld *mld,
 	ret = wait_event_timeout(mld->rxq_sync.waitq,
 				 READ_ONCE(mld->rxq_sync.state) == 0,
 				 SYNC_RX_QUEUE_TIMEOUT);
-	WARN_ONCE(!ret, "RXQ sync failed: state=0x%lx, cookie=%d\n",
-		  mld->rxq_sync.state, mld->rxq_sync.cookie);
+	WARN_ONCE(!ret, "RXQ sync failed: state=0x%lx, cookie=%d, ret: %d\n",
+		  mld->rxq_sync.state, mld->rxq_sync.cookie, ret);
 
 out:
 	mld->rxq_sync.state = 0;
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 07/28] wifi: mac80211:  Fix use-after-free of debugfs inodes.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

When recursively removing debugfs files, clean up child link
debugfs pointers since the recursive removal will have deleted
their memory.  This fixes use-after-free problem when those child
links are eventually cleaned up.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/debugfs_netdev.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 51d2ae232a85..bc2da35db4ae 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -1039,9 +1039,28 @@ static void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata,
 
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 {
+	struct ieee80211_link_data *link;
+	int i;
+
 	if (!sdata->vif.debugfs_dir)
 		return;
 
+	/* In case where there were errors on station creation and maybe
+	 * teardown, we may get here with some links still active.  We are
+	 * about to recursively delete debugfs, so remove any pointers the
+	 * links may have.
+	 */
+	rcu_read_lock();
+
+	for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+		link = rcu_access_pointer(sdata->link[i]);
+		if (!link)
+			continue;
+
+		link->debugfs_dir = NULL;
+	}
+	rcu_read_unlock();
+
 	debugfs_remove_recursive(sdata->vif.debugfs_dir);
 	sdata->vif.debugfs_dir = NULL;
 	sdata->debugfs.subdir_stations = NULL;
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 17/28] wifi: iwlwifi: mld: use warn-on-once in error path.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

Just splat a WARNING once, and add debug output to indicate
a bit about why it is hitting the warn path.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/agg.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
index 23d55374ef8a..413a8688e4eb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c
@@ -496,7 +496,9 @@ static void iwl_mld_free_reorder_buffer(struct iwl_mld *mld,
 		 * sync internal DELBA notification should trigger a release
 		 * of all frames in the reorder buffer.
 		 */
-		WARN_ON(1);
+		WARN_ON_ONCE(1);
+		IWL_ERR(mld, "free-reorder-buffer problem, rxq: %d  num-stored: %d, will purge frames\n",
+			i, reorder_buf->num_stored);
 
 		for (int j = 0; j < data->buf_size; j++)
 			__skb_queue_purge(&entries[j].frames);
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 12/28] wifi: iwlwifi: mld:  Improve logging in error cases.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

To give better understanding of how and when failures
happen.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 drivers/net/wireless/intel/iwlwifi/mld/sta.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
index c478cee570a2..6338ca46f68e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c
@@ -574,7 +574,8 @@ static int iwl_mld_rm_sta_from_fw(struct iwl_mld *mld, u8 fw_sta_id)
 				   WIDE_ID(MAC_CONF_GROUP, STA_REMOVE_CMD),
 				   &cmd);
 	if (ret)
-		IWL_ERR(mld, "Failed to remove station. Id=%d\n", fw_sta_id);
+		IWL_ERR(mld, "Failed to remove station. Id=%d ret: %d\n",
+			fw_sta_id, ret);
 
 	return ret;
 }
@@ -735,8 +736,10 @@ int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
 	int ret;
 
 	ret = iwl_mld_init_sta(mld, sta, vif, type);
-	if (ret)
+	if (ret) {
+		IWL_ERR(mld, "iwl-mld-add-sta, mld-init-sta failed. ret=%d\n", ret);
 		return ret;
+	}
 
 	/* We could have add only the deflink link_sta, but it will not work
 	 * in the restart case if the single link that is active during
@@ -744,8 +747,10 @@ int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
 	 */
 	for_each_sta_active_link(mld_sta->vif, sta, link_sta, link_id) {
 		ret = iwl_mld_add_link_sta(mld, link_sta);
-		if (ret)
+		if (ret) {
+			IWL_ERR(mld, "iwl-mld-add-sta, mld-add-link-sta failed. ret=%d\n", ret);
 			goto destroy_sta;
+		}
 	}
 
 	return 0;
-- 
2.42.0


^ permalink raw reply related

* [PATCH wireless-next 10/28] wifi: mac80211: Ensure sta debugfs is not double-freed.
From: greearb @ 2026-03-11 23:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <20260311230730.163348-1-greearb@candelatech.com>

From: Ben Greear <greearb@candelatech.com>

I saw an instance where use-after-free was found when attempting to
delete sta's debugfs.  Add check to netdev debugfs free logic to ensure
any sta's that still exist have nulled out debugfs entries since
netdev is going to do a recursive debugfs delete.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
 net/mac80211/debugfs_netdev.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 000859b8c005..2e4bc34e6c5c 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -1063,6 +1063,8 @@ ieee80211_debugfs_clear_link_ptr(struct ieee80211_sub_if_data *sdata,
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_link_data *link;
+	struct rhashtable_iter hti;
+	struct sta_info *sta;
 	struct dentry *dir;
 	int i;
 
@@ -1083,6 +1085,28 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 
 		link->debugfs_dir = NULL;
 	}
+
+	/* And, same for all stations.  See ieee80211_sta_debugfs_add where
+	 * they are added to the sdata->debugfs.subdir_stations directory
+	 */
+	rhashtable_walk_enter(&sdata->local->sta_hash.ht, &hti);
+	rhashtable_walk_start(&hti);
+
+	while ((sta = rhashtable_walk_next(&hti))) {
+		if (IS_ERR(sta)) {
+			if (PTR_ERR(sta) != -EAGAIN)
+				break;
+			continue;
+		}
+		if (sta->sdata != sdata)
+			continue;
+
+		sta->debugfs_dir = NULL;
+	}
+
+	rhashtable_walk_stop(&hti);
+	rhashtable_walk_exit(&hti);
+
 	rcu_read_unlock();
 
 	dir = sdata->vif.debugfs_dir;
-- 
2.42.0


^ permalink raw reply related


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