Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH v2][next] iwlegacy: Avoid multiple -Wflex-array-member-not-at-end warnings
From: Stanislaw Gruszka @ 2026-02-16 18:38 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A. R. Silva, Johannes Berg, linux-wireless, linux-kernel,
	linux-hardening
In-Reply-To: <202602091212.743C6B9B7C@keescook>

On Mon, Feb 09, 2026 at 12:46:23PM -0800, Kees Cook wrote:
> @@ -2664,7 +2668,8 @@ struct il3945_beacon_notif {
>  } __packed;
>  
>  struct il4965_beacon_notif {
> -	struct il4965_tx_resp beacon_notify_hdr;
> +	struct il4965_tx_resp_hdr beacon_notify_hdr;
> +	__le32 status;
>  	__le32 low_tsf;
>  	__le32 high_tsf;
>  	__le32 ibss_mgr_status;
> 
> 
> What do folks think?

Both options, with __struct_group(), and this one, are ok for me.

Regards
Stanislaw


^ permalink raw reply

* Re: [PATCH v2][next] iwlegacy: Avoid multiple -Wflex-array-member-not-at-end warnings
From: Gustavo A. R. Silva @ 2026-02-16  3:42 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: Kees Cook, Gustavo A. R. Silva, Johannes Berg, linux-wireless,
	linux-kernel, linux-hardening
In-Reply-To: <20260216184033.GB10063@wp.pl>


> When you will repost, please use 'wifi: iwlegacy:' prefix in the title.

Sure thing.

Thanks for the feedback
-Gustavo

^ permalink raw reply

* Re: [PATCH v2][next] iwlegacy: Avoid multiple -Wflex-array-member-not-at-end warnings
From: Stanislaw Gruszka @ 2026-02-16 18:40 UTC (permalink / raw)
  To: Gustavo A. R. Silva
  Cc: Kees Cook, Gustavo A. R. Silva, Johannes Berg, linux-wireless,
	linux-kernel, linux-hardening
In-Reply-To: <4bf43164-b130-4643-9f4f-761f49bd0dc9@embeddedor.com>

Hi

On Mon, Feb 09, 2026 at 03:23:59PM +0900, Gustavo A. R. Silva wrote:

When you will repost, please use 'wifi: iwlegacy:' prefix in the title.

Regards
Stanislaw

> On 2/10/26 05:46, Kees Cook wrote:
> > On Mon, Feb 09, 2026 at 01:38:15PM +0900, Gustavo A. R. Silva wrote:
> > > -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
> > > getting ready to enable it, globally.
> > > 
> > > Move the conflicting declarations (which in a couple of cases happen
> > > to be in a union, so the entire unions are moved) to the end of the
> > > corresponding structures. Notice that `struct il_tx_beacon_cmd`,
> > > `struct il4965_tx_resp`, and `struct il3945_tx_beacon_cmd` are flexible
> > > structures, this is structures that contain a flexible-array member.
> > 
> > I think explicit mention of il3945_frame and il_frame should be included
> > in the commit log (probably after the above), as they are the ones that
> > contain the mentioned il*_tx_beacon_cmd structs that have a trailing
> > flex array.
> 
> Okay.
> 
> > 
> > > The case for struct il4965_beacon_notif is different. Since this
> > > structure is defined by hardware, we use the struct_group() helper
> > > to create the new `struct il4965_tx_resp_hdr` type. We then use this newly
> > > created type to replace the obhect type of  causing trouble in
> > > struct il4965_beacon_notif, namely `stryct il4965_tx_resp`.
> > 
> > Above two lines have typos and maybe a missing name (between "of" and
> > "causing")?
> 
> Aggh.. yes, I had fixed this before, but somehow I ended up using the
> wrong changelog text. Thanks for the catch!
> 
> > 
> > > In order to preserve the memory layout in struct il4965_beacon_notif,
> > > add member `__le32 beacon_tx_status`, which was previously included
> > > by `struct il4965_tx_resp` (as `__le32 status`), but it's not present
> > > in the newly created type `struct il4965_tx_resp_hdr`.
> > 
> > It may help to explicitly mention how the union exists to provide the
> > "status" member to anything using struct il4965_tx_resp, but there's no
> > sane way to do the overlap across structs, so anything using
> > il4965_beacon_notif needs have its own view of "status".
> 
> Okay.
> 
> > 
> > It does feel like accessing il4965_tx_resp's agg_status should be using
> > a different struct (like happens for other things that want bytes beyond
> > "status"), but okay.
> > 
> > Anyway, it's another situation of a header with a trailing flex array
> > that needs to overlap with differing deserializations of the trailing
> > bytes. The complication here is the kind of "layering violation" of
> > agg_status and status.
> > 
> > > Notice that after this changes, the size of struct il4965_beacon_notif
> > > along with its member's offsets remain the same, hence the memory
> > > layout doesn't change:
> > > 
> > > Before changes:
> > > struct il4965_beacon_notif {
> > > 	struct il4965_tx_resp      beacon_notify_hdr;    /*     0    24 */
> > > 	__le32                     low_tsf;              /*    24     4 */
> > > 	__le32                     high_tsf;             /*    28     4 */
> > > 	__le32                     ibss_mgr_status;      /*    32     4 */
> > > 
> > > 	/* size: 36, cachelines: 1, members: 4 */
> > > 	/* last cacheline: 36 bytes */
> > > };
> > > 
> > > After changes:
> > > struct il4965_beacon_notif {
> > > 	struct il4965_tx_resp_hdr  beacon_notify_hdr;    /*     0    20 */
> > > 	__le32                     beacon_tx_status;     /*    20     4 */
> > > 	__le32                     low_tsf;              /*    24     4 */
> > > 	__le32                     high_tsf;             /*    28     4 */
> > > 	__le32                     ibss_mgr_status;      /*    32     4 */
> > > 
> > > 	/* size: 36, cachelines: 1, members: 5 */
> > > 	/* last cacheline: 36 bytes */
> > > };
> > > 
> > > We also want to ensure that when new members are added to the flexible
> > > structure `struct il4965_tx_resp` (if any), they are always included
> > > within the newly created struct type. To enforce this, we use
> > > `static_assert()` (which is intentionally placed right after the struct,
> > > this is, no blank line in between). This ensures that the memory layout
> > > of both the flexible structure and the new `struct il4965_tx_resp_hdr`
> > > type remains consistent after any changes.
> > > 
> > > Lastly, refactor the rest of the code, accordingly.
> > 
> > I think the changes look consistent with other similar logical changes
> > that have been made for -Wfamnae.
> > 
> > Since enabling -fms-extensions I'm on the look-out for cases where
> > we can use transparent struct members (i.e. define the header struct
> > separately and then use it transparently) instead of using the struct
> > group when we don't need to make the interior explicitly addressable
> > (as we have in this case), as it makes the diff way smaller:
> 
> Ah yes, I can do this. The only thing is that I'd have to change every
> place where members in struct il4965_tx_resp are used, e.g.
> 
> s/frame_count/hdr.frame_count
> 
> and so on...
> 
> Another thing to take into account (fortunately, not in this case) is
> when the FAM needs to be annotated with __counted_by(). If we use a
> separate struct for the header portion of the flexible structure, GCC
> currently cannot _see_ the _counter_ if it's included in a non-anonymous
> structure. However, this will be possible in the near future, correct?
> 
> > 
> > diff --git a/drivers/net/wireless/intel/iwlegacy/commands.h b/drivers/net/wireless/intel/iwlegacy/commands.h
> > index b61b8f377702..440dff2a4ad9 100644
> > --- a/drivers/net/wireless/intel/iwlegacy/commands.h
> > +++ b/drivers/net/wireless/intel/iwlegacy/commands.h
> > @@ -1690,7 +1690,7 @@ struct agg_tx_status {
> >   	__le16 sequence;
> >   } __packed;
> > -struct il4965_tx_resp {
> > +struct il4965_tx_resp_hdr {
> >   	u8 frame_count;		/* 1 no aggregation, >1 aggregation */
> >   	u8 bt_kill_count;	/* # blocked by bluetooth (unused for agg) */
> >   	u8 failure_rts;		/* # failures due to unsuccessful RTS */
> > @@ -1707,6 +1707,10 @@ struct il4965_tx_resp {
> >   	__le16 reserved;
> >   	__le32 pa_power1;	/* RF power amplifier measurement (not used) */
> >   	__le32 pa_power2;
> > +} __packed;
> > +
> > +struct il4965_tx_resp {
> > +	struct il4965_tx_resp_hdr;
> >   	/*
> >   	 * For non-agg:  frame status TX_STATUS_*
> > @@ -2664,7 +2668,8 @@ struct il3945_beacon_notif {
> >   } __packed;
> >   struct il4965_beacon_notif {
> > -	struct il4965_tx_resp beacon_notify_hdr;
> > +	struct il4965_tx_resp_hdr beacon_notify_hdr;
> > +	__le32 status;
> >   	__le32 low_tsf;
> >   	__le32 high_tsf;
> >   	__le32 ibss_mgr_status;
> > 
> > 
> > What do folks think?
> 
> I'll wait for maintainers to chime in.
> 
> > 
> > > With these changes fix the following warnings:
> > > 
> > > 11 drivers/net/wireless/intel/iwlegacy/common.h:526:11: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> > > 11 drivers/net/wireless/intel/iwlegacy/commands.h:2667:31: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> > > 4 drivers/net/wireless/intel/iwlegacy/3945.h:131:11: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> > 
> > Yay for getting these gone! :)
> > 
> 
> We're getting there! \o/
> 
> Thanks
> -Gustavo
> 

^ permalink raw reply

* Re: [PATCH] wifi: iwlwifi: prevent NAPI processing after firmware error
From: Ben Greear @ 2026-02-16 18:12 UTC (permalink / raw)
  To: Cole Leavitt; +Cc: johannes.berg, miriam.rachel.korenblit, linux-wireless
In-Reply-To: <20260214183306.10188-1-cole@unwrap.rs>

On 2/14/26 10:33 AM, Cole Leavitt wrote:
> Ben,
> 
> Good catch on both fronts.
> 
> On the build_tfd dangling pointer -- you're right. The failure path at
> line 775 leaves entries[idx].skb/cmd pointing at caller-owned objects
> (set at lines 763-764). The caller gets -1 and presumably frees the
> skb, so entries[idx].skb becomes a dangling pointer. While write_ptr
> not advancing means current unmap paths won't iterate to that index,
> it's a latent UAF waiting for a flush path change or future code to
> touch it. Two NULL stores inside a held spinlock cost nothing. I think
> this should go upstream as its own patch.
> 
> On the TOCTOU question -- this is the part I spent the most time on.
> The window you're asking about is: firmware starts producing corrupt
> completion data *before* STATUS_FW_ERROR gets set. Our NAPI/TX handler
> checks can't help there because the flag isn't set yet.
> 
> The primary guard in that window is iwl_txq_used() in
> iwl_pcie_reclaim(). It validates that the firmware's SSN falls within
> [read_ptr, write_ptr). This catches wild values -- out-of-range SSNs,
> wraparound corruption, etc.
> 
> What it can't catch is an in-range corrupt SSN -- e.g., firmware says
> reclaim up to index 15 when legitimate is 8, but write_ptr is 20.
> That passes bounds checking and the reclaim loop frees skbs for
> entries still in-flight (active DMA). The NULL skb WARN_ONCE in the
> loop catches double-reclaim but not first-time over-reclaim.
> 
> The complete fix for this would be a per-entry generation counter --
> tag each entry on submit, validate on reclaim. But that adds per-entry
> overhead on the TX hot path to protect against a condition (firmware
> producing corrupt completions) that is already terminal. I think the
> right trade-off is:
> 
>    1. Your build_tfd NULL fix (eliminates one dangling pointer class)
>    2. STATUS_FW_ERROR checks in NAPI poll + TX handlers (this series --
>       shrinks the detection window to near-zero)
>    3. The existing iwl_txq_used() bounds check (catches most corrupt
>       SSNs)
> 
> Together these make the damage window small enough that a per-entry
> generation scheme isn't justified -- by the time firmware is sending
> corrupt SSNs, we're in dump-and-reset territory anyway.
> 
> That said, if you're seeing corruption patterns in your customer
> testing where a valid-looking-but-wrong SSN gets through before
> FW_ERROR fires, I'd be very interested in the traces. That would
> change the cost/benefit on the generation counter approach.

Hello Cole,

Looks like even with your patches we are still seeing use-after-free.  I tried
adding a lot of checks to detect already freed skbs in iwlwifi, and those are not hitting,
so possibly the bug is very close to the end of the call chain, or I am doing it
wrong, or it is some sort of race or bug that my code will not catch.

We do not see any related crashes when using mt76 radios, so pretty sure this
is related to iwlwifi.  A particular AP reproduces this problem within
a day, and we can run tcp tests for 30+ days against other APs with no problem.
I don't know what the AP could be doing to trigger this though.

No FW crash was seen in my logs in this case.

My tree is here if you care to investigate any of my UAF debugging or see
what code is printing some of these logs.  Suggestions for improvement would
be welcome!

https://github.com/greearb/linux-ct-6.18

One problem I see (for several years) is an infinite busy-spin in iwl-mvm-tx-tso-segment.  I added code to break
out after 32k loops, and warn.  That hits here.  The system crashes 28 minutes later, so not
sure if that is directly related.  I guess I can try to do more debugging around that bad tso
segment path.

Feb 16 00:16:01 LF1-MobileStation1 kernel: skbuff: ERROR: Found more than 32000 packets in skbuff::skb_segment, bailing out.
Feb 16 00:16:01 LF1-MobileStation1 kernel: ERROR: iwl-mvm-tx-tso-segment, list gso-segment list is huge: 32001, bailing out.
Feb 16 00:16:06 LF1-MobileStation1 kernel: skbuff: ERROR: Found more than 32000 packets in skbuff::skb_segment, bailing out.
Feb 16 00:16:06 LF1-MobileStation1 kernel: ERROR: iwl-mvm-tx-tso-segment, list gso-segment list is huge: 32001, bailing out.

Feb 16 00:44:06 LF1-MobileStation1 kernel: ------------[ cut here ]------------
Feb 16 00:44:06 LF1-MobileStation1 kernel: refcount_t: underflow; use-after-free.
Feb 16 00:44:06 LF1-MobileStation1 kernel: WARNING: CPU: 18 PID: 1203 at lib/refcount.c:28 refcount_warn_saturate+0xd8/0xe0
Feb 16 00:44:06 LF1-MobileStation1 kernel: Modules linked in: nf_conntrack_netlink nf_conntrack nfnetlink tls vrf nf_defrag_ipv6 nf_defrag_ipv4 8021q garp mrp 
stp llc macvlan wanlink(O) pktgen rpcrdma rdma_cm iw_cm ib_cm ib_core qrtr nct7802 vfat fat intel_rapl_msr coretemp intel_rapl_common intel_uncore_frequency 
intel_uncore_frequency_common snd_hda_codec_intelhdmi snd_hda_codec_hdmi snd_hda_codec_alc882 x86_pkg_temp_thermal intel_powerclamp snd_hda_codec_realtek_lib 
ofpart snd_hda_codec_generic i2c_designware_platform spi_nor kvm_intel spi_pxa2xx_platform iwlmld i2c_designware_core spd5118 dw_dmac iTCO_wdt intel_pmc_bxt ccp 
mtd regmap_i2c spi_pxa2xx_core uvcvideo kvm snd_hda_intel 8250_dw iTCO_vendor_support mac80211 uvc snd_intel_dspcfg irqbypass videobuf2_vmalloc snd_hda_codec 
videobuf2_memops btusb videobuf2_v4l2 btbcm snd_hda_core videobuf2_common snd_hwdep videodev btmtk snd_seq btrtl mc btintel iwlwifi cdc_acm onboard_usb_dev 
snd_seq_device bluetooth snd_pcm cfg80211 snd_timer intel_pmc_core snd intel_lpss_pci i2c_i801 pmt_telemetry
Feb 16 00:44:06 LF1-MobileStation1 kernel:  i2c_smbus soundcore intel_lpss pmt_discovery spi_intel_pci mei_hdcp idma64 i2c_mux pmt_class wmi_bmof spi_intel 
pcspkr mei_pxp intel_pmc_ssram_telemetry bfq acpi_tad acpi_pad nfsd auth_rpcgss nfs_acl lockd grace nfs_localio sch_fq_codel sunrpc fuse zram raid1 dm_raid 
raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq xe drm_ttm_helper gpu_sched drm_suballoc_helper drm_gpuvm drm_exec 
drm_gpusvm_helper i915 i2c_algo_bit drm_buddy intel_gtt drm_client_lib drm_display_helper drm_kms_helper cec rc_core intel_oc_wdt ttm ixgbe agpgart mdio 
libie_fwlog e1000e igc dca hwmon drm mei_wdt intel_vsec i2c_core video wmi pinctrl_alderlake efivarfs [last unloaded: nfnetlink]
Feb 16 00:44:06 LF1-MobileStation1 kernel: CPU: 18 UID: 0 PID: 1203 Comm: irq/343-iwlwifi Tainted: G S         O        6.18.9+ #53 PREEMPT(full)
Feb 16 00:44:06 LF1-MobileStation1 kernel: Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE
Feb 16 00:44:06 LF1-MobileStation1 kernel: Hardware name: Default string /Default string, BIOS 5.27 11/12/2024
Feb 16 00:44:06 LF1-MobileStation1 kernel: RIP: 0010:refcount_warn_saturate+0xd8/0xe0
Feb 16 00:44:07 LF1-MobileStation1 kernel: Code: ff 48 c7 c7 d8 a4 6d 82 c6 05 d0 4a 3e 01 01 e8 3e 83 a7 ff 0f 0b c3 48 c7 c7 80 a4 6d 82 c6 05 bc 4a 3e 01 01 
e8 28 83 a7 ff <0f> 0b c3 0f 1f 44 00 00 8b 07 3d 00 00 00 c0 74 12 83 f8 01 74 13
Feb 16 00:44:07 LF1-MobileStation1 kernel: RSP: 0018:ffffc9000045c6d0 EFLAGS: 00010282
Feb 16 00:44:07 LF1-MobileStation1 kernel: RAX: 0000000000000000 RBX: ffff8882772db000 RCX: 0000000000000000
Feb 16 00:44:07 LF1-MobileStation1 kernel: RDX: ffff88885faa5f00 RSI: 0000000000000001 RDI: ffff88885fa98d00
Feb 16 00:44:07 LF1-MobileStation1 kernel: RBP: ffff8882447d9e00 R08: 0000000000000000 R09: 0000000000000003
Feb 16 00:44:07 LF1-MobileStation1 kernel: R10: ffffc9000045c570 R11: ffffffff82b58da8 R12: ffff88820165f200
Feb 16 00:44:07 LF1-MobileStation1 kernel: R13: 0000000000000001 R14: 00000000000005a8 R15: ffffc9000045c890
Feb 16 00:44:07 LF1-MobileStation1 kernel: FS:  0000000000000000(0000) GS:ffff8888dc5ae000(0000) knlGS:0000000000000000
Feb 16 00:44:07 LF1-MobileStation1 kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Feb 16 00:44:07 LF1-MobileStation1 kernel: CR2: 00007fd1022fdcb4 CR3: 0000000005a36004 CR4: 0000000000772ef0
Feb 16 00:44:07 LF1-MobileStation1 kernel: PKRU: 55555554
Feb 16 00:44:07 LF1-MobileStation1 kernel: Call Trace:
Feb 16 00:44:07 LF1-MobileStation1 kernel:  <IRQ>
Feb 16 00:44:07 LF1-MobileStation1 kernel:  tcp_shifted_skb+0x1d2/0x300
Feb 16 00:44:07 LF1-MobileStation1 kernel:  tcp_sacktag_walk+0x2da/0x4d0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  tcp_sacktag_write_queue+0x4a1/0x9a0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  tcp_ack+0xd66/0x16e0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? ip_finish_output2+0x189/0x570
Feb 16 00:44:07 LF1-MobileStation1 kernel:  tcp_rcv_established+0x211/0xc10
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? sk_filter_trim_cap+0x1a7/0x350
Feb 16 00:44:07 LF1-MobileStation1 kernel:  tcp_v4_do_rcv+0x1bf/0x350
Feb 16 00:44:07 LF1-MobileStation1 kernel:  tcp_v4_rcv+0xddf/0x1550
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? raw_local_deliver+0xcc/0x280
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ip_protocol_deliver_rcu+0x20/0x130
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ip_local_deliver_finish+0x85/0xf0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ip_sublist_rcv_finish+0x35/0x50
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ip_sublist_rcv+0x16f/0x200
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ip_list_rcv+0xfe/0x130
Feb 16 00:44:07 LF1-MobileStation1 kernel:  __netif_receive_skb_list_core+0x183/0x1f0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  netif_receive_skb_list_internal+0x1c8/0x2a0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  gro_receive_skb+0x12e/0x210
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ieee80211_rx_napi+0x82/0xc0 [mac80211]
Feb 16 00:44:07 LF1-MobileStation1 kernel:  iwl_mld_rx_mpdu+0xd0f/0xf00 [iwlmld]
Feb 16 00:44:07 LF1-MobileStation1 kernel:  iwl_pcie_rx_handle+0x394/0xa00 [iwlwifi]
Feb 16 00:44:07 LF1-MobileStation1 kernel:  iwl_pcie_napi_poll_msix+0x3f/0x110 [iwlwifi]
Feb 16 00:44:07 LF1-MobileStation1 kernel:  __napi_poll+0x25/0x1e0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  net_rx_action+0x2d3/0x340
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? try_to_wake_up+0x2e6/0x610
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? __handle_irq_event_percpu+0xa3/0x230
Feb 16 00:44:07 LF1-MobileStation1 kernel:  handle_softirqs+0xca/0x2b0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? irq_thread_dtor+0xa0/0xa0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  do_softirq.part.0+0x3b/0x60
Feb 16 00:44:07 LF1-MobileStation1 kernel:  </IRQ>
Feb 16 00:44:07 LF1-MobileStation1 kernel:  <TASK>
Feb 16 00:44:07 LF1-MobileStation1 kernel:  __local_bh_enable_ip+0x58/0x60
Feb 16 00:44:07 LF1-MobileStation1 kernel:  iwl_pcie_irq_rx_msix_handler+0xbb/0x100 [iwlwifi]
Feb 16 00:44:07 LF1-MobileStation1 kernel:  irq_thread_fn+0x19/0x50
Feb 16 00:44:07 LF1-MobileStation1 kernel:  irq_thread+0x126/0x230
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? irq_finalize_oneshot.part.0+0xc0/0xc0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? irq_forced_thread_fn+0x40/0x40
Feb 16 00:44:07 LF1-MobileStation1 kernel:  kthread+0xf7/0x1f0
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? kthreads_online_cpu+0x100/0x100
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? kthreads_online_cpu+0x100/0x100
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ret_from_fork+0x114/0x140
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ? kthreads_online_cpu+0x100/0x100
Feb 16 00:44:07 LF1-MobileStation1 kernel:  ret_from_fork_asm+0x11/0x20
Feb 16 00:44:07 LF1-MobileStation1 kernel:  </TASK>
Feb 16 00:44:07 LF1-MobileStation1 kernel: ---[ end trace 0000000000000000 ]---
Feb 16 00:44:07 LF1-MobileStation1 kernel: BUG: kernel NULL pointer dereference, address: 0000000000000000

[NPE shortly after in tcp code, bug real problem is the use-after-free I assume]
# serial console output of the crash following the UAF.

#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 0 P4D 0
Oops: Oops: 0000 [#1] SMP
CPU: 18 UID: 0 PID: 1203 Comm: irq/343-iwlwifi Tainted: G S      W  O        6.18.9+ #53 PREEMPT(full)
Tainted: [S]=CPU_OUT_OF_SPEC, [W]=WARN, [O]=OOT_MODULE
Hardware name: Default string /Default string, BIOS 5.27 11/12/2024
RIP: 0010:tcp_rack_detect_loss+0x11c/0x170
Code: 07 00 00 48 8b 87 b0 06 00 00 44 01 ee 48 29 d0 ba 00 00 00 00 48 0f 48 c2 29 c6 85 f6 7e 27 41 8b 06 39 f0 0f 42 c6 41 89 06 <48> 8b 45 58 4c 8d 65 58 48 
89 eb 48 83 e8 58 4d 39 fc 74 ab 48 89
RSP: 0018:ffffc9000045c758 EFLAGS: 00010293
RAX: 000000000000408d RBX: ffff88824fff7a00 RCX: 20c49ba5e353f7cf
RDX: 0000000000000000 RSI: 000000000000408d RDI: ffff88820165f200
RBP: ffffffffffffffa8 R08: 0000000083eed3f9 R09: 000000000000012c
R10: 00000000000005ba R11: 000000000000001d R12: ffff88824fff7a58
R13: 000000000000408d R14: ffffc9000045c79c R15: ffff88820165f888
FS:  0000000000000000(0000) GS:ffff8888dc5ae000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 0000000005a36004 CR4: 0000000000772ef0
PKRU: 55555554
Call Trace:
  <IRQ>
  tcp_rack_mark_lost+0x59/0xe0
  tcp_identify_packet_loss+0x30/0x70
  tcp_fastretrans_alert+0x366/0x810
  tcp_ack+0xc66/0x16e0
  ? ip_finish_output2+0x189/0x570
  tcp_rcv_established+0x211/0xc10
  ? sk_filter_trim_cap+0x1a7/0x350
  tcp_v4_do_rcv+0x1bf/0x350
  tcp_v4_rcv+0xddf/0x1550
  ? raw_local_deliver+0xcc/0x280
  ip_protocol_deliver_rcu+0x20/0x130
  ip_local_deliver_finish+0x85/0xf0
  ip_sublist_rcv_finish+0x35/0x50
  ip_sublist_rcv+0x16f/0x200
  ip_list_rcv+0xfe/0x130
  __netif_receive_skb_list_core+0x183/0x1f0
  netif_receive_skb_list_internal+0x1c8/0x2a0
  gro_receive_skb+0x12e/0x210
  ieee80211_rx_napi+0x82/0xc0 [mac80211]
  iwl_mld_rx_mpdu+0xd0f/0xf00 [iwlmld]
  iwl_pcie_rx_handle+0x394/0xa00 [iwlwifi]
  iwl_pcie_napi_poll_msix+0x3f/0x110 [iwlwifi]
  __napi_poll+0x25/0x1e0
  net_rx_action+0x2d3/0x340
  ? try_to_wake_up+0x2e6/0x610
  ? __handle_irq_event_percpu+0xa3/0x230
  handle_softirqs+0xca/0x2b0
  ? irq_thread_dtor+0xa0/0xa0
  do_softirq.part.0+0x3b/0x60
  </IRQ>
  <TASK>
  __local_bh_enable_ip+0x58/0x60
  iwl_pcie_irq_rx_msix_handler+0xbb/0x100 [iwlwifi]
  irq_thread_fn+0x19/0x50
  irq_thread+0x126/0x230
  ? irq_finalize_oneshot.part.0+0xc0/0xc0
  ? irq_forced_thread_fn+0x40/0x40
  kthread+0xf7/0x1f0
  ? kthreads_online_cpu+0x100/0x100
  ? kthreads_online_cpu+0x100/0x100
  ret_from_fork+0x114/0x140
  ? kthreads_online_cpu+0x100/0x100
  ret_from_fork_asm+0x11/0x20
  </TASK>
Modules linked in: nf_conntrack_netlink nf_conntrack nfnetlink tls vrf nf_defrag_ipv6 nf_defrag_ipv4 8021q garp mrp stp llc macvlan wanlink(O) pktgen rpcrdma 
rdma_cm iw_cm ib_cm ib_core qrtr nct7802 vfat fat intel_rapl_msr coretemp intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common 
snd_hda_codec_intelhdmi snd_hda_codec_hdmi snd_hda_codec_alc882 x86_pkg_temp_thermal intel_powerclamp snd_hda_codec_realtek_lib ofpart snd_hda_codec_generic 
i2c_designware_platform spi_nor kvm_intel spi_pxa2xx_platform iwlmld i2c_designware_core spd5118 dw_dmac iTCO_wdt intel_pmc_bxt ccp mtd regmap_i2c 
spi_pxa2xx_core uvcvideo kvm snd_hda_intel 8250_dw iTCO_vendor_support mac80211 uvc snd_intel_dspcfg irqbypass videobuf2_vmalloc snd_hda_codec videobuf2_memops 
btusb videobuf2_v4l2 btbcm snd_hda_core videobuf2_common snd_hwdep videodev btmtk snd_seq btrtl mc btintel iwlwifi cdc_acm onboard_usb_dev snd_seq_device 
bluetooth snd_pcm cfg80211 snd_timer intel_pmc_core snd intel_lpss_pci i2c_i801 pmt_telemetry
  i2c_smbus soundcore intel_lpss pmt_discovery spi_intel_pci mei_hdcp idma64 i2c_mux pmt_class wmi_bmof spi_intel pcspkr mei_pxp intel_pmc_ssram_telemetry bfq 
acpi_tad acpi_pad nfsd auth_rpcgss nfs_acl lockd grace nfs_localio sch_fq_codel sunrpc fuse zram raid1 dm_raid raid456 async_raid6_recov async_memcpy async_pq 
async_xor xor async_tx raid6_pq xe drm_ttm_helper gpu_sched drm_suballoc_helper drm_gpuvm drm_exec drm_gpusvm_helper i915 i2c_algo_bit drm_buddy intel_gtt 
drm_client_lib drm_display_helper drm_kms_helper cec rc_core intel_oc_wdt ttm ixgbe agpgart mdio libie_fwlog e1000e igc dca hwmon drm mei_wdt intel_vsec 
i2c_core video wmi pinctrl_alderlake efivarfs [last unloaded: nfnetlink]
CR2: 0000000000000000
---[ end trace 0000000000000000 ]---
RIP: 0010:tcp_rack_detect_loss+0x11c/0x170
Code: 07 00 00 48 8b 87 b0 06 00 00 44 01 ee 48 29 d0 ba 00 00 00 00 48 0f 48 c2 29 c6 85 f6 7e 27 41 8b 06 39 f0 0f 42 c6 41 89 06 <48> 8b 45 58 4c 8d 65 58 48 
89 eb 48 83 e8 58 4d 39 fc 74 ab 48 89
RSP: 0018:ffffc9000045c758 EFLAGS: 00010293
RAX: 000000000000408d RBX: ffff88824fff7a00 RCX: 20c49ba5e353f7cf
RDX: 0000000000000000 RSI: 000000000000408d RDI: ffff88820165f200
RBP: ffffffffffffffa8 R08: 0000000083eed3f9 R09: 000000000000012c
R10: 00000000000005ba R11: 000000000000001d R12: ffff88824fff7a58
R13: 000000000000408d R14: ffffc9000045c79c R15: ffff88820165f888
FS:  0000000000000000(0000) GS:ffff8888dc5ae000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 0000000005a36004 CR4: 0000000000772ef0
PKRU: 55555554
Kernel panic - not syncing: Fatal exception in interrupt
Kernel Offset: disabled
Rebooting in 10 seconds..

Thanks,
Ben

> 
> Thanks,
> Cole
> 


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com

^ permalink raw reply

* Re: [PATCH wireless-next v8 2/3] wifi: cfg80211: add initial UHR support
From: Harshitha Prem @ 2026-02-16 17:39 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless
  Cc: Karthikeyan Kathirvel, vasanthakumar.thiagarajan,
	Lorenzo Bianconi, ath12k, Jeff Johnson, Ping-Ke Shih
In-Reply-To: <9576fdbc0b9b62caba88e05716d7c7028512130d.camel@sipsolutions.net>



On 2/13/2026 3:56 PM, Johannes Berg wrote:
> On Fri, 2026-02-13 at 11:11 +0100, Johannes Berg wrote:
>> Hi Harshita,
>>
>>>> Should we add a separate netlink attribute for the UHR operation, which
>>>> hostapd would fill with the _full_ data like it appears in association
>>>> response etc.?
>>>>
>>>> That way, hostapd doesn't need to build a separate data/attribute
>>>> structure but can just use hostapd_eid_uhr_operation(..., false) for it.
>>>>
>>>> An alternative would be to add more attributes for everything, but it's
>>>> probably more complicated on both sides?
>>
>>> Thank you for the suggestions.
>>>
>>> We feel that using separate nested attributes for each feature is the better approach, as this allows us to reuse the attributes for the Enhanced BSS Parameter Critical Update procedure, where similar information is carried in the UHR parameters update element.
>>
>> Heh, I'll admit I'm surprised - I'm usually the one advocating for
>> finer-grained attributes, and here I didn't ;-)
> 
> Wait, so I wrote a lot and forgot to circle back to this question ...
> 
> Basically I think that it's not going to be useful to split it up. I
> have no objections to it, but it complicates the code (especially in
> hostapd) quite a bit, because it's going to be either
> 
>  1) include each thing (NPCA, DBE, ...) in its own attribute, so that
>     e.g. NPCA would be 4 or 6 bytes per spec format, but then we need
>     separate validation for each in nl80211
> 
>  2) we really break it all down to each individual value, so e.g. NPCA
>     would have separate attributes for minimum duration threshold,
>     switch and switch back delay, initial QSRC and a MOPLEN flag; this
>     is a bit easier to capture in a policy, but a LOT of parameters
>     overall.
> 
> The thing - and why I wrote so much - is that we basically only need a
> single current, and in the case of updates additionally a single post-
> update, UHR operation.
> 
> So unless we're going to completely design away from beacon templates
> and create an API where including the UHR Parameters Update element is
> fully the firmware's (or driver's) responsibility across all the
> different frame types, then the split isn't really needed. And even if
> we _do_ design it completely that way, giving the post-update UHR
> operation and comparing to the pre-update one isn't a huge stretch for a
> design that just required fully rebuilding all the frames (parsing all
> the way into fragmented elements and putting them back together in a
> completely new way, including re-fragmenting elements and subelements
> etc. which all sounds very messy to me.)
> 

For beacon‑offloaded drivers, we initially thought a separate NL command
for the UHR critical update, with dedicated nested attributes, would
make it easier to trigger the firmware/driver. At the same time, we’ve
been having ongoing discussions around CSA and the UHR critical update,
especially around the overlap with post‑beacon template handling in CSA.

Thank you. The proposal to introduce CMD_START_MLD_BSS_UPDATE gave us a
different perspective and helped us rethink how best to handle this.


> johannes


^ permalink raw reply

* Re: [PATCH wireless-next v8 2/3] wifi: cfg80211: add initial UHR support
From: Harshitha Prem @ 2026-02-16 17:17 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless
  Cc: Karthikeyan Kathirvel, vasanthakumar.thiagarajan,
	Lorenzo Bianconi, ath12k, Jeff Johnson, Ping-Ke Shih
In-Reply-To: <be9ab3c7f05b0f56f19aee0ffc7c2f96138b9a05.camel@sipsolutions.net>



On 2/13/2026 3:41 PM, Johannes Berg wrote:
> Hi Harshita,
> 
>>> Should we add a separate netlink attribute for the UHR operation, which
>>> hostapd would fill with the _full_ data like it appears in association
>>> response etc.?
>>>
>>> That way, hostapd doesn't need to build a separate data/attribute
>>> structure but can just use hostapd_eid_uhr_operation(..., false) for it.
>>>
>>> An alternative would be to add more attributes for everything, but it's
>>> probably more complicated on both sides?
> 
>> Thank you for the suggestions.
>>
>> We feel that using separate nested attributes for each feature is the better approach, as this allows us to reuse the attributes for the Enhanced BSS Parameter Critical Update procedure, where similar information is carried in the UHR parameters update element.
> 
> Heh, I'll admit I'm surprised - I'm usually the one advocating for
> finer-grained attributes, and here I didn't ;-)
> 
>> While this approach is slightly more verbose, we believe it offers better extensibility for the future.
> 
> Does it actually, though?
> 
> I had sort of expected hostapd to add the UHR Parameters Update element
> to the beacons, and configure some way of having firmware set the
> countdown ("Countdown Timer"). Turns out this is not only in beacons but
> also in probe response, (re)association response and (UHR? [1]) link
> reconfiguration response frames.
> 
> [1] the spec says "Link Reconfiguration Response" but I think it should
> say "UHR Link Reconfiguration Response"
> 
> But I guess this is going to end up a continuation of the previous wifi7
> discussion from last year [2] which hadn't really completed. And Lorenzo
> just posted another thing on this [3].
> 
> [2] https://lore.kernel.org/linux-wireless/20250717045540.27208-1-aditya.kumar.singh@oss.qualcomm.com/
> [3] https://lore.kernel.org/linux-wireless/20260212-mt7996-link-reconf-v1-0-2b110340d6c4@kernel.org/
> 
> 
> So I think maybe we need to figure out how we will do all of this first?
> 
> Naively, I would've said ... something stupid. I'm reading the spec as
> I'm writing this ;-) The UHR Parameters Update element is actually
> included in all the beacons across the entire AP MLD.
> 
> Maybe we need to take a step back from our previous discussion as well,
> and introduce a broader concept here?
> 
> 
> I could imagine, for example, something where you say in the nl80211 API
> some variation of
> 
>  1) Let's start a new update operation ("NL80211_CMD_START_MLD_BSS_UPDATE"),
>     I guess already with some parameters saying:
>      - the updated affiliated AP (link)
>      - the number of beacon intervals you want to do it for
>      - the post-update UHR operation (?)
>        (or the new channel if it's CSA? etc.?)
> 
>      - maybe - more critical if we use it for CSA - already the beacon
>        templates for all the links? with all the things I say in (2)
>        below, but that's more complex maybe?
> 
>        the reason I say this is that there's a difference here in how
>        the counter is done - for CSA etc. the things have to disappear
>        from the beacon immediately, for UHR updates they stick around
>        and the counter indicates "in the past"
> 
>     returning a cookie for the operation.
> 
>  2) hostapd updates each link's beacon now including the UHR Parameters
>     Update element(s), for each currently ongoing update it includes -
>     indexed by the cookie - a list of offsets where the counters are
>     updated.
> 
>     Thing is that this depends on the operation - CSA will already need
>     the post-switch beacon template so the flow can continue without
>     involving hostapd, hostapd may however need to update the beacon in
>     the interim (both pre- and post-switch ones!) and need to refer
>     again to where the counters are filled in ...
> 
> 


Hi Johannes,

This approach looks well suited to handling overlapping update scenarios.

To make sure I understand it correctly, I’d like to walk through a
concise example where a UHR critical update and a CSA overlap on link 0
of a 3‑link AP MLD.


t1: A UHR critical update is triggered. hostapd sends
NL80211_CMD_START_MLD_BSS_UPDATE with an advanced notification (5
TBTTs), post‑interval (5 TBTTs), and the beacon template with UHR
parameters update element for link 0. Timers start in mac80211, and
hostapd receives cookie X.


t2: hostapd sends NL80211_CMD_UPDATE_AP with cookie X and offset where
the counter is updated for link 1 (and then link 2).

the countdown values would be handled in mac80211 with the offset
mentioned similar to ieee80211_set_beacon_cntdwn().

t3: Before the UHR advanced interval completes, a CSA is triggered (due
to radar or user‑initiated). Another NL80211_CMD_START_MLD_BSS_UPDATE is
issued with CSA countdown 5, including CSA and after beacon templates.
The after template carries cookie X and the offset. Since UHR CU is
already in progress, hostapd could also include an updated parameters
update element. Also, an updated UHR operation element which can be
modified in after beacon template if CSA finishes after the UHR CU
advance interval. (why to provide the UHR operation element separately
is because the advance notification can be before or after the CSA
finalize).
hostapd then receives cookie Y for the CSA.


t4: hostapd issues NL80211_CMD_UPDATE_AP for link 1 with cookie X (UHR
offset) and cookie Y (CSA offset), followed by link 2.


t5: When the UHR advanced notification interval expires, the CSA after
beacon template is updated to reflect the new operation element by
mac80211 or getting it from hostapd.


t6: Once the CSA completes, the driver updates the after beacon template
along with updated counter for UHR parameter update element. (since it
will be in the post notification interval)


t7: When the UHR post‑interval completes, the UHR parameter update
element is removed. Since offsets are known, the driver can remove it
from the latest beacon template.

Please let me know if this sequence aligns with the intended behavior,
or if I’m missing any edge cases.

Also, CSA during NPCA parameter update seems very tricky as the channel
information advertised in NPCA may not be relevant when there is a CSA,
perhaps stop the NPCA CU (still spec has not mentioned any details on
the abort scenario though)

Even, in case of link removal during UHR CU update, we need to stop the
UHR CU.

Furthermore, the UHR capabilities carries the advance notification
interval, post notification  (i guess yet to be added in element as I
see it in "37-8—Enhanced Critical Updates Mechanism") and update
indication in TIM interval, these intervals can be sent in the START_AP.
I assume, these intervals cannot be modified dynamically as these are
exchanged in assoc response (Will reconfirm again).

For beacon offloaded drivers, NL80211_CMD_START_MLD_BSS_UPDATE can be as
a trigger. May be we can add the updated UHR operation element in case
of UHR. So, that firmware/driver handle the timers as well as
constructing the elements since "the encoding of fields in Mode specific
parameters for any feature say DPS/NPCA/DBE etc.. is same as the
corresponding field in operation parameters field for that feature" (but
i see bit variations for NPCA between both)

I guess, this means the proposal of having a separate netlink attribute
for the UHR operation with _full_ data like is much useful.

Still, we are thinking through on all the other cases of wifi-7/CCA etc..

> Either way, it feels like we've reached the end of where the current
> design with CSA and BSS color updates will take us. Lorenzo already gave
> up and put the parsing into the driver to find the offsets, but I
> personally think that's very inflexible.
> 
> Some operations such as link removal may not need to have perfect
> timing, but some others like CSA really do want the updates to happen at
> the precise moment.
> 
> In some way, it's almost good that we haven't completed the WiFi7 part
> since the UHR part throws another curveball with the counters
> decrementing below zero - for past updates - in a sense.
> 
> 
> johannes

Thanks in advance for your time and clarification.

Regards,
Harshitha


^ permalink raw reply

* Wi-Fi quirk found in Dell Inspiron 5567
From: Bandhan Pramanik @ 2026-02-16 17:05 UTC (permalink / raw)
  To: linux-wireless, ath10k

Hello,

I messaged regarding Dell Inspiron 5567 earlier. This is regarding the 
QCA9377 chips placed on these devices.

I fixed the issue using "pcie_aspm=off", and I can say that the ASPM 
configs of the Wi-Fi chip might be problematic on this device.

The reason is that *these laptops run Wi-Fi erratically if we don't turn 
off the ASPM*. The result is the overwriting of the dmesg ring buffer 
within seconds of boot and IRQ #16 being turned off for the influx of 
multiple correctable errors, which hampers the touchpads too.

What are your thoughts on turning off this device's ASPM by default? I 
will be happy to provide any details as needed.

Bandhan



^ permalink raw reply

* [PATCH v7 2/3] dt-bindings: net: wireless: mt76: add more PCI devices
From: Ryder Lee @ 2026-02-16 16:01 UTC (permalink / raw)
  To: Felix Fietkau, Rob Herring
  Cc: devicetree, linux-mediatek, linux-wireless, Ryder Lee
In-Reply-To: <8fa8ec500b3d4de7b1966c6887f1dfbe5c46a54c.1771205424.git.ryder.lee@mediatek.com>

This adds support for mt7915/mt7916/mt7990/mt7992/mt7996 PCI devices.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
v7: add missing dts mailing list and maintainers
---
 .../devicetree/bindings/net/wireless/mediatek,mt76.yaml      | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
index ae6b97cdc..72cc30251 100644
--- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
@@ -27,6 +27,11 @@ properties:
       - mediatek,mt7622-wmac
       - mediatek,mt7981-wmac
       - mediatek,mt7986-wmac
+      - pci14c3,7915  # mt7915
+      - pci14c3,7906  # mt7916
+      - pci14c3,7990  # mt7996
+      - pci14c3,7992  # mt7992
+      - pci14c3,7993  # mt7990
 
   reg:
     minItems: 1
-- 
2.45.2


^ permalink raw reply related

* [PATCH v7 3/3] dt-bindings: net: wireless: mt76: clarify backoff limit usage
From: Ryder Lee @ 2026-02-16 16:01 UTC (permalink / raw)
  To: Felix Fietkau, Rob Herring
  Cc: devicetree, linux-mediatek, linux-wireless, Ryder Lee, Allen Ye
In-Reply-To: <8fa8ec500b3d4de7b1966c6887f1dfbe5c46a54c.1771205424.git.ryder.lee@mediatek.com>

Clarify the usage of path backoff limit properties in mt76 binding.
Add explicit documentation for old generation (mt7915, mt7916, mt7981,
mt7986) and new generation (mt7990, mt7992, mt7996) devices, including
the difference in beamforming and non-beamforming entries.

Rephrase the paths-ru/paths-ru-bf description to make them more precise.

Co-developed-by: Allen Ye <allen.ye@mediatek.com>
Signed-off-by: Allen Ye <allen.ye@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
v4:
- revise commit message
- use PCI id as the compatible string to replace "connac2/3"

v5: fix missing starting space in comment(comments)
v6: separate commits with their own separate rationale
v7: add missing dts mailing list and maintainers
---
 .../bindings/net/wireless/mediatek,mt76.yaml     | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
index 72cc30251..20b868f7d 100644
--- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
@@ -257,6 +257,14 @@ properties:
                       followed by 10 power limit values. The order of the
                       channel resource unit settings is RU26, RU52, RU106,
                       RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160.
+                      - For mt7981/mt7986/mt7915/mt7916
+                        - Beamforming entries for BW20~BW160 and OFDM do not
+                          include 1T1ss.
+                        - When 1T1ss is not used, it should be filled with 0.
+                      - For mt7996/mt7992/mt7990
+                        - Beamforming entries for BW20~BW160 and RU include
+                          1T1ss, but OFDM does not include 1T1ss.
+                        - 1T1ss is taken into account, so no need to fill with 0.
                     minItems: 1
                     maxItems: 7
                     items:
@@ -275,6 +283,14 @@ properties:
                       followed by 10 power limit values. The order of the
                       channel resource unit settings is RU26, RU52, RU106,
                       RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160.
+                      - For mt7981/mt7986/mt7915/mt7916
+                        - Beamforming entries for BW20~BW160 and OFDM do not
+                          include 1T1ss.
+                        - When 1T1ss is not used, it should be filled with 0.
+                      - For mt7996/mt7992/mt7990
+                        - Beamforming entries for BW20~BW160 and RU include
+                          1T1ss, but OFDM does not include 1T1ss.
+                        - 1T1ss is taken into account, so no need to fill with 0.
                     minItems: 1
                     maxItems: 7
                     items:
-- 
2.45.2


^ permalink raw reply related

* [PATCH v7 1/3] wifi: mt76: fix backoff fields and max_power calculation
From: Ryder Lee @ 2026-02-16 16:01 UTC (permalink / raw)
  To: Felix Fietkau, Rob Herring
  Cc: devicetree, linux-mediatek, linux-wireless, Allen Ye, Ryder Lee

From: Allen Ye <allen.ye@mediatek.com>

The maximum power value may exist in either the data or backoff field.
Previously, backoff power limits were not considered in txpower reporting.
This patch ensures mt76 also considers backoff values in the SKU table.

Also, each RU entry (RU26, RU52, RU106, BW20, ...) in the DTS corresponds
to 10 stream combinations (1T1ss, 2T1ss, 3T1ss, 4T1ss, 2T2ss, 3T2ss,
4T2ss, 3T3ss, 4T3ss, 4T4ss).

For beamforming tables:
- In connac2, beamforming entries for BW20~BW160, and OFDM do not include
  1T1ss.
- In connac3, beamforming entries for BW20~BW160, and RU include 1T1ss,
  but OFDM beamforming does not include 1T1ss.

Non-beamforming and RU entries for both connac2 and connac3 include 1T1ss.

Fixes: b05ab4be9fd7 ("wifi: mt76: mt7915: add bf backoff limit table support")
Signed-off-by: Allen Ye <allen.ye@mediatek.com>
Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
v1:
- Add "wifi:" prefix to the subject.

v2:
- Fix checkpatch errors.
- Remove unnecessary style changes.
- Add explanation for connac2 index adjustment.

v3:
- Fix "case"s for MT76_SKU_BACKOFF_BF_OFFSET and MT76_SKU_BACKOFF.
- add more explanation for connac2/connac3 tables.

v7: add missing dts mailing list and maintainers.
---
 drivers/net/wireless/mediatek/mt76/eeprom.c | 154 ++++++++++++++------
 drivers/net/wireless/mediatek/mt76/mt76.h   |   1 -
 2 files changed, 109 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c
index 573400d57..afdb73661 100644
--- a/drivers/net/wireless/mediatek/mt76/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/eeprom.c
@@ -9,6 +9,13 @@
 #include <linux/nvmem-consumer.h>
 #include <linux/etherdevice.h>
 #include "mt76.h"
+#include "mt76_connac.h"
+
+enum mt76_sku_type {
+	MT76_SKU_RATE,
+	MT76_SKU_BACKOFF,
+	MT76_SKU_BACKOFF_BF_OFFSET,
+};
 
 static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len)
 {
@@ -292,7 +299,6 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
 }
 EXPORT_SYMBOL_GPL(mt76_find_channel_node);
 
-
 static s8
 mt76_get_txs_delta(struct device_node *np, u8 nss)
 {
@@ -306,9 +312,24 @@ mt76_get_txs_delta(struct device_node *np, u8 nss)
 	return be32_to_cpu(val[nss - 1]);
 }
 
+static inline u8 mt76_backoff_n_chains(struct mt76_dev *dev, u8 idx)
+{
+	/* 0:1T1ss, 1:2T1ss, ..., 14:5T5ss */
+	static const u8 connac3_table[] = {
+		1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5};
+	static const u8 connac2_table[] = {
+		1, 2, 3, 4, 2, 3, 4, 3, 4, 4, 0, 0, 0, 0, 0};
+
+	if (idx >= ARRAY_SIZE(connac3_table))
+		return 0;
+
+	return is_mt799x(dev) ? connac3_table[idx] : connac2_table[idx];
+}
+
 static void
-mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,
-		       s8 target_power, s8 nss_delta, s8 *max_power)
+mt76_apply_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
+		       const s8 *data, s8 target_power, s8 nss_delta,
+		       s8 *max_power, int n_chains, enum mt76_sku_type type)
 {
 	int i;
 
@@ -316,18 +337,51 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,
 		return;
 
 	for (i = 0; i < pwr_len; i++) {
-		pwr[i] = min_t(s8, target_power, data[i] + nss_delta);
+		u8 backoff_chain_idx = i;
+		int backoff_n_chains;
+		s8 backoff_delta;
+		s8 delta;
+
+		switch (type) {
+		case MT76_SKU_RATE:
+			delta = 0;
+			backoff_delta = 0;
+			backoff_n_chains = 0;
+			break;
+		case MT76_SKU_BACKOFF_BF_OFFSET:
+			backoff_chain_idx += 1;
+			fallthrough;
+		case MT76_SKU_BACKOFF:
+			delta = mt76_tx_power_path_delta(n_chains);
+			backoff_n_chains = mt76_backoff_n_chains(dev, backoff_chain_idx);
+			backoff_delta = mt76_tx_power_path_delta(backoff_n_chains);
+			break;
+		default:
+			return;
+		}
+
+		pwr[i] = min_t(s8, target_power + delta - backoff_delta, data[i] + nss_delta);
+
+		/* used for padding, doesn't need to be considered */
+		if (data[i] >= S8_MAX - 1)
+			continue;
+
+		/* only consider backoff value for the configured chain number */
+		if (type != MT76_SKU_RATE && n_chains != backoff_n_chains)
+			continue;
+
 		*max_power = max(*max_power, pwr[i]);
 	}
 }
 
 static void
-mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
-			     const s8 *data, size_t len, s8 target_power,
-			     s8 nss_delta)
+mt76_apply_multi_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
+			     s8 pwr_num, const s8 *data, size_t len,
+			     s8 target_power, s8 nss_delta, s8 *max_power,
+			     int n_chains, enum mt76_sku_type type)
 {
+	static const int connac2_backoff_ru_idx = 2;
 	int i, cur;
-	s8 max_power = -128;
 
 	if (!data)
 		return;
@@ -337,8 +391,26 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
 		if (len < pwr_len + 1)
 			break;
 
-		mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1,
-				       target_power, nss_delta, &max_power);
+		/* Each RU entry (RU26, RU52, RU106, BW20, ...) in the DTS
+		 * corresponds to 10 stream combinations (1T1ss, 2T1ss, 3T1ss,
+		 * 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3T3ss, 4T3ss, 4T4ss).
+		 *
+		 * For beamforming tables:
+		 * - In connac2, beamforming entries for BW20~BW160 and OFDM
+		 *   do not include 1T1ss.
+		 * - In connac3, beamforming entries for BW20~BW160 and RU
+		 *   include 1T1ss, but OFDM beamforming does not include 1T1ss.
+		 *
+		 * Non-beamforming and RU entries for both connac2 and connac3
+		 * include 1T1ss.
+		 */
+		if (!is_mt799x(dev) && type == MT76_SKU_BACKOFF &&
+		    i > connac2_backoff_ru_idx)
+			type = MT76_SKU_BACKOFF_BF_OFFSET;
+
+		mt76_apply_array_limit(dev, pwr + pwr_len * i, pwr_len, data + 1,
+				       target_power, nss_delta, max_power,
+				       n_chains, type);
 		if (--cur > 0)
 			continue;
 
@@ -360,18 +432,11 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
 	struct device_node *np;
 	const s8 *val;
 	char name[16];
-	u32 mcs_rates = dev->drv->mcs_rates;
-	u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
 	char band;
 	size_t len;
-	s8 max_power = 0;
-	s8 max_power_backoff = -127;
+	s8 max_power = -127;
 	s8 txs_delta;
 	int n_chains = hweight16(phy->chainmask);
-	s8 target_power_combine = target_power + mt76_tx_power_path_delta(n_chains);
-
-	if (!mcs_rates)
-		mcs_rates = 10;
 
 	memset(dest, target_power, sizeof(*dest) - sizeof(dest->path));
 	memset(&dest->path, 0, sizeof(dest->path));
@@ -409,46 +474,45 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
 	txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));
 
 	val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
-	mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,
-			       target_power, txs_delta, &max_power);
+	mt76_apply_array_limit(dev, dest->cck, ARRAY_SIZE(dest->cck), val,
+			       target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
 
-	val = mt76_get_of_array_s8(np, "rates-ofdm",
-				   &len, ARRAY_SIZE(dest->ofdm));
-	mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
-			       target_power, txs_delta, &max_power);
+	val = mt76_get_of_array_s8(np, "rates-ofdm", &len, ARRAY_SIZE(dest->ofdm));
+	mt76_apply_array_limit(dev, dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
+			       target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
 
-	val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1);
-	mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
-				     ARRAY_SIZE(dest->mcs), val, len,
-				     target_power, txs_delta);
+	val = mt76_get_of_array_s8(np, "rates-mcs", &len, ARRAY_SIZE(dest->mcs[0]) + 1);
+	mt76_apply_multi_array_limit(dev, dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
+				     ARRAY_SIZE(dest->mcs), val, len, target_power,
+				     txs_delta, &max_power, n_chains, MT76_SKU_RATE);
 
-	val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1);
-	mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
-				     ARRAY_SIZE(dest->ru), val, len,
-				     target_power, txs_delta);
+	val = mt76_get_of_array_s8(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
+	mt76_apply_multi_array_limit(dev, dest->ru[0], ARRAY_SIZE(dest->ru[0]),
+				     ARRAY_SIZE(dest->ru), val, len, target_power,
+				     txs_delta, &max_power, n_chains, MT76_SKU_RATE);
 
-	max_power_backoff = max_power;
 	val = mt76_get_of_array_s8(np, "paths-cck", &len, ARRAY_SIZE(dest->path.cck));
-	mt76_apply_array_limit(dest->path.cck, ARRAY_SIZE(dest->path.cck), val,
-			       target_power_combine, txs_delta, &max_power_backoff);
+	mt76_apply_array_limit(dev, dest->path.cck, ARRAY_SIZE(dest->path.cck), val,
+			       target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
 
 	val = mt76_get_of_array_s8(np, "paths-ofdm", &len, ARRAY_SIZE(dest->path.ofdm));
-	mt76_apply_array_limit(dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,
-			       target_power_combine, txs_delta, &max_power_backoff);
+	mt76_apply_array_limit(dev, dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,
+			       target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
 
 	val = mt76_get_of_array_s8(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest->path.ofdm_bf));
-	mt76_apply_array_limit(dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,
-			       target_power_combine, txs_delta, &max_power_backoff);
+	mt76_apply_array_limit(dev, dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,
+			       target_power, txs_delta, &max_power, n_chains,
+			       MT76_SKU_BACKOFF_BF_OFFSET);
 
 	val = mt76_get_of_array_s8(np, "paths-ru", &len, ARRAY_SIZE(dest->path.ru[0]) + 1);
-	mt76_apply_multi_array_limit(dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),
-				     ARRAY_SIZE(dest->path.ru), val, len,
-				     target_power_combine, txs_delta);
+	mt76_apply_multi_array_limit(dev, dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),
+				     ARRAY_SIZE(dest->path.ru), val, len, target_power,
+				     txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
 
 	val = mt76_get_of_array_s8(np, "paths-ru-bf", &len, ARRAY_SIZE(dest->path.ru_bf[0]) + 1);
-	mt76_apply_multi_array_limit(dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),
-				     ARRAY_SIZE(dest->path.ru_bf), val, len,
-				     target_power_combine, txs_delta);
+	mt76_apply_multi_array_limit(dev, dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),
+				     ARRAY_SIZE(dest->path.ru_bf), val, len, target_power,
+				     txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
 
 	return max_power;
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index d05e83ea1..32876eab2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -540,7 +540,6 @@ struct mt76_driver_ops {
 	u32 survey_flags;
 	u16 txwi_size;
 	u16 token_size;
-	u8 mcs_rates;
 
 	unsigned int link_data_size;
 
-- 
2.45.2


^ permalink raw reply related

* Re: [PATCH] wifi: iwlwifi: mld: stop mac80211 TX queues on firmware error
From: Johannes Berg @ 2026-02-16 11:29 UTC (permalink / raw)
  To: Cole Leavitt, Miri Korenblit; +Cc: linux-wireless, linux-kernel, stable
In-Reply-To: <20260214060716.16394-1-cole@unwrap.rs>

On Fri, 2026-02-13 at 23:07 -0700, Cole Leavitt wrote:
> When firmware encounters an error in the iwlmld driver, nothing prevents
> mac80211 from continuing to feed TX packets. The mvm driver uses atomic
> status bits (IWL_MVM_STATUS_HW_RESTART_REQUESTED) checked in its TX path
> to gate transmissions, but the mld driver has no equivalent check --
> iwl_mld_tx_from_txq() only checks mld_txq->status.stop_full.
> 
> This allows TX to proceed while firmware is unresponsive, causing
> spinlock contention and soft lockups lasting 22-26 seconds.
> 
> Add ieee80211_stop_queues()

Using stop_queues()/wake_queues() seems a bit awkward, that API doesn't
interact all that well with the TXQ-based APIs that we use in this
driver. Shouldn't it just stop pulling from the TXQs in that case?

johannes

^ permalink raw reply

* Re: [BUG] Potential Null Pointer Dereference in ieee80211_process_neg_ttlm_req Function
From: Johannes Berg @ 2026-02-16  9:53 UTC (permalink / raw)
  To: 冯嘉仪
  Cc: davem, edumazet, kuba, pabeni, linux-wireless, netdev,
	linux-kernel
In-Reply-To: <tencent_50235033396E84610251D7C1@qq.com>

Hi,

> Our team recently developed a null-pointer-dereference (NPD) vulnerability detection tool

OK, so you decided to write a new tool. Good for you, but keep in mind
that you need to compete with very well-known tools already.

> After manual review,

(and you have:)

> BUILD_BUG_ON(ARRAY_SIZE(direction) != ARRAY_SIZE(elems->ttlm));

So you're either lying, or decided to task someone with this who doesn't
understand C; even state-of-the art LLMs would do better. State of the
art tools (LLMs and not LLMs like coverity) will also give you a
scenario of how the purported bug can actually happen.

I get that you need human feedback to improve your system, but you've
also apparently decided that it's too expensive / too much work / too
hard to really do this review, and you want the Linux community to do it
for you instead. That's cheaper, yay!

But it doesn't work that way. You're not entitled to free feedback for
your under development tool.

Please stop doing this.

johannes

^ permalink raw reply

* Re: wifi: mac80211: question about 20/40 coex support
From: Alexander Wilhelm @ 2026-02-16  9:50 UTC (permalink / raw)
  To: Alex Gavin; +Cc: Johannes Berg, linux-wireless, linux-kernel
In-Reply-To: <261dcee1-e5b9-4b9c-9052-f726fe5beb69@icloud.com>

On Fri, Feb 13, 2026 at 02:01:37PM -0800, Alex Gavin wrote:
> On 2/13/26 13:44, Alex Gavin wrote:
> > On 2/13/26 01:46, Alexander Wilhelm wrote:
> >> On Fri, Feb 13, 2026 at 12:14:16AM -0800, Alex Gavin wrote:
> >>> On 2/12/26 23:05, Alexander Wilhelm wrote:
> >>>>
> >>>> Hello wireless devs,
> >>>>
> >>>> I am analyzing a wireless management frame taken from the beacon of an
> >>>> access point, and in this frame the `20/40 Coexistence Management Support`
> >>>> bit is set to 0, indicating that the feature is not supported. See frame
> >>>> below:
> >>>>
> >>>>     Frame 2: 217 bytes on wire (1736 bits), 217 bytes captured (1736 bits)
> >>>>     Radiotap Header v0, Length 26
> >>>>     802.11 radio information
> >>>>     IEEE 802.11 Beacon frame, Flags: ........
> >>>>     IEEE 802.11 Wireless Management
> >>>>         Fixed parameters (12 bytes)
> >>>>         Tagged parameters (155 bytes)
> >>>>             Tag: SSID parameter set: "SSID"
> >>>>             Tag: Supported Rates 6(B), 9, 12(B), 18, 24(B), 36, 48, 54, [Mbit/sec]
> >>>>             Tag: DS Parameter set: Current Channel: 6
> >>>>             Tag: Traffic Indication Map (TIM): DTIM 0 of 2 bitmap
> >>>>             Tag: Country Information: Country Code DE, Environment All
> >>>>             Tag: ERP Information
> >>>>             Tag: QBSS Load Element 802.11e CCA Version
> >>>>             Tag: Supported Operating Classes
> >>>>             Tag: HT Capabilities (802.11n D1.10)
> >>>>             Tag: HT Information (802.11n D1.10)
> >>>>             Tag: Extended Capabilities (10 octets)
> >>>>                 Tag Number: Extended Capabilities (127)
> >>>>                 Tag length: 10
> >>>>                 Extended Capabilities: 0x04 (octet 1)
> >>>>                     .... ...0 = 20/40 BSS Coexistence Management Support: Not supported
> >>>>                     .... ..0. = General Link (GLK): 0x0
> >>>>                     .... .1.. = Extended Channel Switching: Supported
> >>>>                     .... 0... = GLK-GCR: 0x0
> >>>>                     ...0 .... = PSMP Capability: Not supported
> >>>>                     ..0. .... = Reserved: 0x0
> >>>>                     .0.. .... = S-PSMP Support: Not supported
> >>>>                     0... .... = Event: Not supported
> >>>>                 Extended Capabilities: 0x00 (octet 2)
> >>>>                 Extended Capabilities: 0x00 (octet 3)
> >>>>                 Extended Capabilities: 0x02 (octet 4)
> >>>>                 Extended Capabilities: 0x00 (octet 5)
> >>>>                 Extended Capabilities: 0x00 (octet 6)
> >>>>                 Extended Capabilities: 0x01 (octet 7)
> >>>>                 Extended Capabilities: 0x0040 (octets 8 & 9)
> >>>>                 Extended Capabilities: 0x40 (octet 10)
> >>>>             Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element
> >>>>
> >>>> I reviewed several driver implementations, and none of them seem to
> >>>> advertise this capability. I also could not find any definition for this
> >>>> bit in `include/linux/ieee80211.h`, unlike many other capability bits that
> >>>> are defined (e.g. `WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING` or
> >>>> `WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT`). From what I can see, none of the
> >>>> `mac80211`‑based drivers appear to support this feature, is that correct?
> >>>>
> >>>> Additionally, I want to confirm whether my understanding of the feature is
> >>>> accurate: the 20/40 Coexistence mechanism implements the “good neighbor”
> >>>> policy, meaning that an AP using a 40 MHz channel in the 2.4 GHz band must
> >>>> fall back to 20 MHz when it detects an overlapping BSS (OBSS). Is that
> >>>> right?
> >>>>
> >>>> Any clarification would be greatly appreciated.
> >>>>
> >>>>
> >>>> Best regards
> >>>> Alexander Wilhelm
> >>>>
> >>>
> >>> From my understanding, this is implemented in userspace (i.e. hostapd), at least in upstream code.
> >>
> >> I've alredy seen the code in `hostapd` that implements a fallback to 20
> >> MHz. But that implementation is based only on scan results, not on 20/40
> >> coexistence feautre. Here the snippet from `ieee80211n_check_scan`
> >> function:
> >>
> >>     [...]
> >>     if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
> >>             oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
> >>     else
> >>             oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
> >>     wpa_scan_results_free(scan_res);
> >>
> >>     iface->secondary_ch = iface->conf->secondary_channel;
> >>     if (!oper40) {
> >>             wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
> >>                        "channel pri=%d sec=%d based on overlapping BSSes",
> >>                        iface->conf->channel,
> >>                        iface->conf->channel +
> >>                        iface->conf->secondary_channel * 4);
> >>             iface->conf->secondary_channel = 0;
> >>             if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
> >>                     /*
> >>                      * TODO: Could consider scheduling another scan to check
> >>                      * if channel width can be changed if no coex reports
> >>                      * are received from associating stations.
> >>                      */
> >>             }
> >>     }
> >>     [...]
> > 
> > There are ways the BSS can switch from 40 MHz to 20 MHz operation beyond just scan results.
> > 
> > For example, a newly-associated, 40 MHz intolerant station could cause hostapd to reconfigure to 20
> > MHz operation, assuming the WPA_DRIVER_FLAGS_HT_2040_COEX is set by radio driver capabilities.
> > 
> > Directly handling association:
> > 
> > handle_assoc()
> > -> update_ht_state()
> > -> update_sta_ht()
> > -> ht40_intolerant_add()
> > -> ieee802_11_set_beacons()
> > -> ieee802_11_set_beacon()
> > -> __ieee802_11_set_beacon()
> > -> ieee802_11_build_ap_params()
> > -> hostapd_build_ap_extra_ies()
> > -> hostapd_eid_ext_capab()
> > -> hostapd_ext_capab_byte()
> > 
> > 
> > Or from driver callback:
> > 
> > hostapd_notif_assoc()
> > -> ht40_intolerant_add()
> > -> ieee802_11_set_beacons()
> > ...
> > -> hostapd_ext_capab_byte()
> > 
> > 
> > Additionally, receipt of a 20/40 MHz Coex Management Action frame in 'hostapd_2040_coex_action()'
> > may trigger the AP to reconfigure to 20 MHz using a similar code path.
> > 
> > For testing, wpa_supplicant supports configuring 40 MHz intolerant stations. See below from its
> > config file reference [1]:
> > 
> > # ht40_intolerant: Whether 40 MHz intolerant should be indicated.
> > # 0 = 40 MHz tolerant (default)
> > # 1 = 40 MHz intolerant
> > 
> > I've uploaded some example hostapd and wpa_supplicant configs here [2], if you'd like something to
> > reference or play around with. Associating the intolerant station config should trigger hostapd to
> > switch from 40 MHz to 20 MHz with this configuration, assuming radio driver support as mentioned above.
> > 
> > [1] https://urldefense.com/v3/__https://git.w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf__;!!I9LPvj3b!AsA2QqDGWXpvNJ_Z3N2Trl0qQHOI1jDydzfs8Xjv-GME96gVt-Q4hgdZTkUlQISMAQmn7HqwqqSmayxFDxGc-woJ$ 
> > [2] https://urldefense.com/v3/__https://codeberg.org/a-gavin/hostap-confs/src/branch/main/open/20-40MHz-bss-coexistence__;!!I9LPvj3b!AsA2QqDGWXpvNJ_Z3N2Trl0qQHOI1jDydzfs8Xjv-GME96gVt-Q4hgdZTkUlQISMAQmn7HqwqqSmayxFD70l2TKr$ 
> 
> Since you mentioned packet capture analysis, to observe a 40 MHz BSS switch to 20 MHz operation, pay
> close attention to the HT Operation IE in the Beacon frames.
> 
> Assuming you're using Wireshark, you should see the 'HT Operation Information Subset (1 of 3)'
> section switch from showing 'Supported channel width: Channel of any width supported' to '20 MHz
> channel width only'. I'm sure other programs are similar.
> 
> Using the 40 MHz intolerant association example, you should see this switch immediately after
> station association.
> 
> 
> 40 MHz operation:
> 
> Tag: HT Operation
>     Tag Number: HT Operation (61)
>     Tag length: 22
>     Primary Channel: 1
>     HT Operation Information Subset (1 of 3): 0x05
>         .... ..01 = Secondary channel offset: Secondary channel is above the primary channel (0x1)
>         .... .1.. = Supported channel width: Channel of any width supported
>         .... 0... = Reduced Interframe Spacing (RIFS): Prohibited
>         0000 .... = Reserved: 0x0
>     HT Operation Information Subset (2 of 3): 0x0000
>     HT Operation Information Subset (3 of 3): 0x0000
>     Rx Supported Modulation and Coding Scheme Set: Basic MCS Set
> 
> 
> 20 MHz operation:
> 
> Tag: HT Operation
>     Tag Number: HT Operation (61)
>     Tag length: 22
>     Primary Channel: 1
>     HT Operation Information Subset (1 of 3): 0x00
>         .... ..00 = Secondary channel offset: No secondary channel (0x0)
>         .... .0.. = Supported channel width: 20 MHz channel width only
>         .... 0... = Reduced Interframe Spacing (RIFS): Prohibited
>         0000 .... = Reserved: 0x0
>     HT Operation Information Subset (2 of 3): 0x0000
>     HT Operation Information Subset (3 of 3): 0x0000
>     Basic HT-MCS Set: Reserved: 00000000000000000000000000000000
> 
> 
> Hope this helps!

Hi Alex,

thank you again for a great support. And yes, I'm using Wireshark or tshask
to analyze the packets. Unfortunatelly I'm currently struggling with my
noisy environment. I cannot realy start an 40 MHz AP without force it with
`noscan` option. But then the Coex mechanism does not work as well. But I
think I'll get it working with some workarounds.


Best regards
Alexander Wilhelm

> 
> >>> In hostapd, the '20/40 BSS Coexistence Management Support' bit you reference is set in the
> >>> 'hostapd_ext_capab_byte()' function in 'src/ap/ieee802_11_shared.c' when 'obss_interval' is set in
> >>> the AP config file.
> >>>
> >>> For more information on the 'obss_interval' config item see the following from the hostapd config
> >>> reference here [1]:
> >>>
> >>> # If set non-zero, require stations to perform scans of overlapping
> >>> # channels to test for stations which would be affected by 40 MHz traffic.
> >>> # This parameter sets the interval in seconds between these scans. Setting this
> >>> # to non-zero allows 2.4 GHz band AP to move dynamically to a 40 MHz channel if
> >>> # no co-existence issues with neighboring devices are found.
> >>> #obss_interval=0
> >>
> >> Great, I found the the configuration in my `hostapd` version and the code
> >> that implements the handling of this kind of management frames. I'll give
> >> the configuration option a try.
> >>
> >>> The following sections from the 802.11 standard may be helpful to understand this topic in more
> >>> depth, although I'm sure there's information online that may be easier to digest:
> >>>
> >>> - 9.4.2.58 20/40 BSS Coexistence element
> >>> - 9.4.2.54.2 HT Capability Information field
> >>> - 11.15.12 Switching between 40 MHz and 20 MHz
> >>>
> >>> From 11.15.12:
> >>>
> >>> TE-B: On any of the channels of the channel set defined in Clause 18, reception of a 20/40 BSS
> >>> Coexistence Management, Beacon, Probe Request, or Probe Response frame that contains a value of 1 in
> >>> a Forty MHz Intolerant field and that has the Address 1 field equal to the receiving STA’s address
> >>> or to a group address, with no further addressing qualifications.
> >>
> >> Thank you for the support, Alex. The information helps me a lot.
> >>
> >>
> >> Best regards
> >> Alexander Wilhelm
> > 
> > 
> 

^ permalink raw reply

* Re: [PATCH v6 2/3] dt-bindings: net: wireless: mt76: add more PCI devices
From: Krzysztof Kozlowski @ 2026-02-16  7:30 UTC (permalink / raw)
  To: Ryder Lee, Felix Fietkau; +Cc: linux-mediatek, linux-wireless
In-Reply-To: <5022737c82052132702004ab0fdc073f5cf6df69.1771205424.git.ryder.lee@mediatek.com>

On 16/02/2026 05:47, Ryder Lee wrote:
> This adds support for mt7915/mt7916/mt7990/mt7992/mt7996 PCI devices.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  .../devicetree/bindings/net/wireless/mediatek,mt76.yaml      | 5 +++++
>  1 file changed, 5 insertions(+)


Last time you did not Cc maintainers.

Now, you did not even bother to CC Dt list.

I won't be reviewing it.

Please use scripts/get_maintainers.pl to get a list of necessary people
and lists to CC. It might happen, that command when run on an older
kernel, gives you outdated entries. Therefore please be sure you base
your patches on recent Linux kernel.

Tools like b4 or scripts/get_maintainer.pl provide you proper list of
people, so fix your workflow. Tools might also fail if you work on some
ancient tree (don't, instead use mainline) or work on fork of kernel
(don't, instead use mainline). Just use b4 and everything should be
fine, although remember about `b4 prep --auto-to-cc` if you added new
patches to the patchset.

You missed at least devicetree list (maybe more), so this won't be
tested by automated tooling. Performing review on untested code might be
a waste of time.

Please kindly resend and include all necessary To/Cc entries.

Best regards,
Krzysztof

^ permalink raw reply

* [PATCH v6 3/3] dt-bindings: net: wireless: mt76: clarify backoff limit usage
From: Ryder Lee @ 2026-02-16  4:47 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-mediatek, linux-wireless, Ryder Lee, Allen Ye
In-Reply-To: <8fa8ec500b3d4de7b1966c6887f1dfbe5c46a54c.1771205424.git.ryder.lee@mediatek.com>

Clarify the usage of path backoff limit properties in mt76 binding.
Add explicit documentation for old generation (mt7915, mt7916, mt7981,
mt7986) and new generation (mt7990, mt7992, mt7996) devices, including
the difference in beamforming and non-beamforming entries.

Rephrase the paths-ru/paths-ru-bf description to make them more precise.

Co-developed-by: Allen Ye <allen.ye@mediatek.com>
Signed-off-by: Allen Ye <allen.ye@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
v4:
- revise commit message
- use PCI id as the compatible string to replace "connac2/3"

v5: fix missing starting space in comment(comments)
v6: separate commits with their own separate rationale
---
 .../bindings/net/wireless/mediatek,mt76.yaml     | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
index 72cc30251..20b868f7d 100644
--- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
@@ -257,6 +257,14 @@ properties:
                       followed by 10 power limit values. The order of the
                       channel resource unit settings is RU26, RU52, RU106,
                       RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160.
+                      - For mt7981/mt7986/mt7915/mt7916
+                        - Beamforming entries for BW20~BW160 and OFDM do not
+                          include 1T1ss.
+                        - When 1T1ss is not used, it should be filled with 0.
+                      - For mt7996/mt7992/mt7990
+                        - Beamforming entries for BW20~BW160 and RU include
+                          1T1ss, but OFDM does not include 1T1ss.
+                        - 1T1ss is taken into account, so no need to fill with 0.
                     minItems: 1
                     maxItems: 7
                     items:
@@ -275,6 +283,14 @@ properties:
                       followed by 10 power limit values. The order of the
                       channel resource unit settings is RU26, RU52, RU106,
                       RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160.
+                      - For mt7981/mt7986/mt7915/mt7916
+                        - Beamforming entries for BW20~BW160 and OFDM do not
+                          include 1T1ss.
+                        - When 1T1ss is not used, it should be filled with 0.
+                      - For mt7996/mt7992/mt7990
+                        - Beamforming entries for BW20~BW160 and RU include
+                          1T1ss, but OFDM does not include 1T1ss.
+                        - 1T1ss is taken into account, so no need to fill with 0.
                     minItems: 1
                     maxItems: 7
                     items:
-- 
2.45.2


^ permalink raw reply related

* [PATCH v6 2/3] dt-bindings: net: wireless: mt76: add more PCI devices
From: Ryder Lee @ 2026-02-16  4:47 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-mediatek, linux-wireless, Ryder Lee
In-Reply-To: <8fa8ec500b3d4de7b1966c6887f1dfbe5c46a54c.1771205424.git.ryder.lee@mediatek.com>

This adds support for mt7915/mt7916/mt7990/mt7992/mt7996 PCI devices.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 .../devicetree/bindings/net/wireless/mediatek,mt76.yaml      | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
index ae6b97cdc..72cc30251 100644
--- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
@@ -27,6 +27,11 @@ properties:
       - mediatek,mt7622-wmac
       - mediatek,mt7981-wmac
       - mediatek,mt7986-wmac
+      - pci14c3,7915  # mt7915
+      - pci14c3,7906  # mt7916
+      - pci14c3,7990  # mt7996
+      - pci14c3,7992  # mt7992
+      - pci14c3,7993  # mt7990
 
   reg:
     minItems: 1
-- 
2.45.2


^ permalink raw reply related

* [PATCH v6 1/3] wifi: mt76: fix backoff fields and max_power calculation
From: Ryder Lee @ 2026-02-16  4:47 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-mediatek, linux-wireless, Allen Ye, Ryder Lee

From: Allen Ye <allen.ye@mediatek.com>

The maximum power value may exist in either the data or backoff field.
Previously, backoff power limits were not considered in txpower reporting.
This patch ensures mt76 also considers backoff values in the SKU table.

Also, each RU entry (RU26, RU52, RU106, BW20, ...) in the DTS corresponds
to 10 stream combinations (1T1ss, 2T1ss, 3T1ss, 4T1ss, 2T2ss, 3T2ss,
4T2ss, 3T3ss, 4T3ss, 4T4ss).

For beamforming tables:
- In connac2, beamforming entries for BW20~BW160, and OFDM do not include
  1T1ss.
- In connac3, beamforming entries for BW20~BW160, and RU include 1T1ss,
  but OFDM beamforming does not include 1T1ss.

Non-beamforming and RU entries for both connac2 and connac3 include 1T1ss.

Fixes: b05ab4be9fd7 ("wifi: mt76: mt7915: add bf backoff limit table support")
Signed-off-by: Allen Ye <allen.ye@mediatek.com>
Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
v1:
- Add "wifi:" prefix to the subject.

v2:
- Fix checkpatch errors.
- Remove unnecessary style changes.
- Add explanation for connac2 index adjustment.

v3:
- Fix "case"s for MT76_SKU_BACKOFF_BF_OFFSET and MT76_SKU_BACKOFF.
- add more explanation for connac2/connac3 tables.
---
 drivers/net/wireless/mediatek/mt76/eeprom.c | 154 ++++++++++++++------
 drivers/net/wireless/mediatek/mt76/mt76.h   |   1 -
 2 files changed, 109 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c
index 573400d57..afdb73661 100644
--- a/drivers/net/wireless/mediatek/mt76/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/eeprom.c
@@ -9,6 +9,13 @@
 #include <linux/nvmem-consumer.h>
 #include <linux/etherdevice.h>
 #include "mt76.h"
+#include "mt76_connac.h"
+
+enum mt76_sku_type {
+	MT76_SKU_RATE,
+	MT76_SKU_BACKOFF,
+	MT76_SKU_BACKOFF_BF_OFFSET,
+};
 
 static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len)
 {
@@ -292,7 +299,6 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
 }
 EXPORT_SYMBOL_GPL(mt76_find_channel_node);
 
-
 static s8
 mt76_get_txs_delta(struct device_node *np, u8 nss)
 {
@@ -306,9 +312,24 @@ mt76_get_txs_delta(struct device_node *np, u8 nss)
 	return be32_to_cpu(val[nss - 1]);
 }
 
+static inline u8 mt76_backoff_n_chains(struct mt76_dev *dev, u8 idx)
+{
+	/* 0:1T1ss, 1:2T1ss, ..., 14:5T5ss */
+	static const u8 connac3_table[] = {
+		1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5};
+	static const u8 connac2_table[] = {
+		1, 2, 3, 4, 2, 3, 4, 3, 4, 4, 0, 0, 0, 0, 0};
+
+	if (idx >= ARRAY_SIZE(connac3_table))
+		return 0;
+
+	return is_mt799x(dev) ? connac3_table[idx] : connac2_table[idx];
+}
+
 static void
-mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,
-		       s8 target_power, s8 nss_delta, s8 *max_power)
+mt76_apply_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
+		       const s8 *data, s8 target_power, s8 nss_delta,
+		       s8 *max_power, int n_chains, enum mt76_sku_type type)
 {
 	int i;
 
@@ -316,18 +337,51 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,
 		return;
 
 	for (i = 0; i < pwr_len; i++) {
-		pwr[i] = min_t(s8, target_power, data[i] + nss_delta);
+		u8 backoff_chain_idx = i;
+		int backoff_n_chains;
+		s8 backoff_delta;
+		s8 delta;
+
+		switch (type) {
+		case MT76_SKU_RATE:
+			delta = 0;
+			backoff_delta = 0;
+			backoff_n_chains = 0;
+			break;
+		case MT76_SKU_BACKOFF_BF_OFFSET:
+			backoff_chain_idx += 1;
+			fallthrough;
+		case MT76_SKU_BACKOFF:
+			delta = mt76_tx_power_path_delta(n_chains);
+			backoff_n_chains = mt76_backoff_n_chains(dev, backoff_chain_idx);
+			backoff_delta = mt76_tx_power_path_delta(backoff_n_chains);
+			break;
+		default:
+			return;
+		}
+
+		pwr[i] = min_t(s8, target_power + delta - backoff_delta, data[i] + nss_delta);
+
+		/* used for padding, doesn't need to be considered */
+		if (data[i] >= S8_MAX - 1)
+			continue;
+
+		/* only consider backoff value for the configured chain number */
+		if (type != MT76_SKU_RATE && n_chains != backoff_n_chains)
+			continue;
+
 		*max_power = max(*max_power, pwr[i]);
 	}
 }
 
 static void
-mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
-			     const s8 *data, size_t len, s8 target_power,
-			     s8 nss_delta)
+mt76_apply_multi_array_limit(struct mt76_dev *dev, s8 *pwr, size_t pwr_len,
+			     s8 pwr_num, const s8 *data, size_t len,
+			     s8 target_power, s8 nss_delta, s8 *max_power,
+			     int n_chains, enum mt76_sku_type type)
 {
+	static const int connac2_backoff_ru_idx = 2;
 	int i, cur;
-	s8 max_power = -128;
 
 	if (!data)
 		return;
@@ -337,8 +391,26 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
 		if (len < pwr_len + 1)
 			break;
 
-		mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1,
-				       target_power, nss_delta, &max_power);
+		/* Each RU entry (RU26, RU52, RU106, BW20, ...) in the DTS
+		 * corresponds to 10 stream combinations (1T1ss, 2T1ss, 3T1ss,
+		 * 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3T3ss, 4T3ss, 4T4ss).
+		 *
+		 * For beamforming tables:
+		 * - In connac2, beamforming entries for BW20~BW160 and OFDM
+		 *   do not include 1T1ss.
+		 * - In connac3, beamforming entries for BW20~BW160 and RU
+		 *   include 1T1ss, but OFDM beamforming does not include 1T1ss.
+		 *
+		 * Non-beamforming and RU entries for both connac2 and connac3
+		 * include 1T1ss.
+		 */
+		if (!is_mt799x(dev) && type == MT76_SKU_BACKOFF &&
+		    i > connac2_backoff_ru_idx)
+			type = MT76_SKU_BACKOFF_BF_OFFSET;
+
+		mt76_apply_array_limit(dev, pwr + pwr_len * i, pwr_len, data + 1,
+				       target_power, nss_delta, max_power,
+				       n_chains, type);
 		if (--cur > 0)
 			continue;
 
@@ -360,18 +432,11 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
 	struct device_node *np;
 	const s8 *val;
 	char name[16];
-	u32 mcs_rates = dev->drv->mcs_rates;
-	u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
 	char band;
 	size_t len;
-	s8 max_power = 0;
-	s8 max_power_backoff = -127;
+	s8 max_power = -127;
 	s8 txs_delta;
 	int n_chains = hweight16(phy->chainmask);
-	s8 target_power_combine = target_power + mt76_tx_power_path_delta(n_chains);
-
-	if (!mcs_rates)
-		mcs_rates = 10;
 
 	memset(dest, target_power, sizeof(*dest) - sizeof(dest->path));
 	memset(&dest->path, 0, sizeof(dest->path));
@@ -409,46 +474,45 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
 	txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));
 
 	val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
-	mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,
-			       target_power, txs_delta, &max_power);
+	mt76_apply_array_limit(dev, dest->cck, ARRAY_SIZE(dest->cck), val,
+			       target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
 
-	val = mt76_get_of_array_s8(np, "rates-ofdm",
-				   &len, ARRAY_SIZE(dest->ofdm));
-	mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
-			       target_power, txs_delta, &max_power);
+	val = mt76_get_of_array_s8(np, "rates-ofdm", &len, ARRAY_SIZE(dest->ofdm));
+	mt76_apply_array_limit(dev, dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
+			       target_power, txs_delta, &max_power, n_chains, MT76_SKU_RATE);
 
-	val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1);
-	mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
-				     ARRAY_SIZE(dest->mcs), val, len,
-				     target_power, txs_delta);
+	val = mt76_get_of_array_s8(np, "rates-mcs", &len, ARRAY_SIZE(dest->mcs[0]) + 1);
+	mt76_apply_multi_array_limit(dev, dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
+				     ARRAY_SIZE(dest->mcs), val, len, target_power,
+				     txs_delta, &max_power, n_chains, MT76_SKU_RATE);
 
-	val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1);
-	mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
-				     ARRAY_SIZE(dest->ru), val, len,
-				     target_power, txs_delta);
+	val = mt76_get_of_array_s8(np, "rates-ru", &len, ARRAY_SIZE(dest->ru[0]) + 1);
+	mt76_apply_multi_array_limit(dev, dest->ru[0], ARRAY_SIZE(dest->ru[0]),
+				     ARRAY_SIZE(dest->ru), val, len, target_power,
+				     txs_delta, &max_power, n_chains, MT76_SKU_RATE);
 
-	max_power_backoff = max_power;
 	val = mt76_get_of_array_s8(np, "paths-cck", &len, ARRAY_SIZE(dest->path.cck));
-	mt76_apply_array_limit(dest->path.cck, ARRAY_SIZE(dest->path.cck), val,
-			       target_power_combine, txs_delta, &max_power_backoff);
+	mt76_apply_array_limit(dev, dest->path.cck, ARRAY_SIZE(dest->path.cck), val,
+			       target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
 
 	val = mt76_get_of_array_s8(np, "paths-ofdm", &len, ARRAY_SIZE(dest->path.ofdm));
-	mt76_apply_array_limit(dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,
-			       target_power_combine, txs_delta, &max_power_backoff);
+	mt76_apply_array_limit(dev, dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val,
+			       target_power, txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
 
 	val = mt76_get_of_array_s8(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest->path.ofdm_bf));
-	mt76_apply_array_limit(dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,
-			       target_power_combine, txs_delta, &max_power_backoff);
+	mt76_apply_array_limit(dev, dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val,
+			       target_power, txs_delta, &max_power, n_chains,
+			       MT76_SKU_BACKOFF_BF_OFFSET);
 
 	val = mt76_get_of_array_s8(np, "paths-ru", &len, ARRAY_SIZE(dest->path.ru[0]) + 1);
-	mt76_apply_multi_array_limit(dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),
-				     ARRAY_SIZE(dest->path.ru), val, len,
-				     target_power_combine, txs_delta);
+	mt76_apply_multi_array_limit(dev, dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]),
+				     ARRAY_SIZE(dest->path.ru), val, len, target_power,
+				     txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
 
 	val = mt76_get_of_array_s8(np, "paths-ru-bf", &len, ARRAY_SIZE(dest->path.ru_bf[0]) + 1);
-	mt76_apply_multi_array_limit(dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),
-				     ARRAY_SIZE(dest->path.ru_bf), val, len,
-				     target_power_combine, txs_delta);
+	mt76_apply_multi_array_limit(dev, dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]),
+				     ARRAY_SIZE(dest->path.ru_bf), val, len, target_power,
+				     txs_delta, &max_power, n_chains, MT76_SKU_BACKOFF);
 
 	return max_power;
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index d05e83ea1..32876eab2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -540,7 +540,6 @@ struct mt76_driver_ops {
 	u32 survey_flags;
 	u16 txwi_size;
 	u16 token_size;
-	u8 mcs_rates;
 
 	unsigned int link_data_size;
 
-- 
2.45.2


^ permalink raw reply related

* [PATCH wireless-next v5 2/2] wifi: mac80211_hwsim: add incumbent signal interference detection support
From: Amith A @ 2026-02-16  3:20 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, amith.a, Aditya Kumar Singh
In-Reply-To: <20260216032027.2310956-1-amith.a@oss.qualcomm.com>

From: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>

Add a debugfs ‘simulate_incumbent_signal_interference’ with custom
file_operations and a .write that accepts “<freq_mhz> <bitmap>”. The
handler selects the 6 GHz chanctx whose primary 20 MHz center matches
<freq_mhz> and reports the event via cfg80211_incumbent_signal_notify().
The bitmap marks affected 20 MHz segments within the current chandef
(lowest bit = lowest segment)

Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
Signed-off-by: Amith A <amith.a@oss.qualcomm.com>
---
 drivers/net/wireless/virtual/mac80211_hwsim.c | 80 +++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 4d9f5f87e814..2a61997e8312 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -36,6 +36,9 @@
 #include <linux/virtio.h>
 #include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
+#include <linux/uaccess.h>
+#include <linux/kstrtox.h>
+#include <linux/string.h>
 #include "mac80211_hwsim.h"
 
 #define WARN_QUEUE 100
@@ -1164,6 +1167,80 @@ static int hwsim_write_simulate_radar(void *dat, u64 val)
 DEFINE_DEBUGFS_ATTRIBUTE(hwsim_simulate_radar, NULL,
 			 hwsim_write_simulate_radar, "%llu\n");
 
+struct hwsim_chanctx_iter_arg {
+	struct ieee80211_chanctx_conf **out;
+	u32 freq_mhz;
+};
+
+static void hwsim_6ghz_chanctx_iter(struct ieee80211_hw *hw,
+				    struct ieee80211_chanctx_conf *conf,
+				    void *data)
+{
+	struct hwsim_chanctx_iter_arg *arg = data;
+
+	if (conf->def.chan &&
+	    conf->def.chan->band == NL80211_BAND_6GHZ &&
+	    conf->def.chan->center_freq == arg->freq_mhz)
+		*arg->out = conf;
+}
+
+static ssize_t hwsim_simulate_incumbent_signal_write(struct file *file,
+						     const char __user *ubuf,
+						     size_t len, loff_t *ppos)
+{
+	struct mac80211_hwsim_data *data = file->private_data;
+	struct ieee80211_chanctx_conf *chanctx_conf = NULL;
+	struct hwsim_chanctx_iter_arg arg;
+	u32 freq_mhz, bitmap;
+	char *sptr, *token;
+	char buf[64];
+
+	if (!len || len >= sizeof(buf))
+		return -EINVAL;
+
+	if (copy_from_user(buf, ubuf, len))
+		return -EFAULT;
+	buf[len] = '\0';
+
+	strim(buf);
+	sptr = buf;
+	token = strsep(&sptr, " \t");
+	if (!token)
+		return -EINVAL;
+	if (kstrtou32(token, 0, &freq_mhz))
+		return -EINVAL;
+
+	token = strsep(&sptr, " \t");
+	if (!token)
+		return -EINVAL;
+	if (kstrtou32(token, 0, &bitmap))
+		return -EINVAL;
+
+	if (!freq_mhz)
+		return -EINVAL;
+
+	arg.out = &chanctx_conf;
+	arg.freq_mhz = freq_mhz;
+	ieee80211_iter_chan_contexts_atomic(data->hw,
+					    hwsim_6ghz_chanctx_iter,
+					    &arg);
+
+	if (!chanctx_conf)
+		return -EINVAL;
+
+	cfg80211_incumbent_signal_notify(data->hw->wiphy,
+					 &chanctx_conf->def,
+					 bitmap,
+					 GFP_KERNEL);
+
+	return len;
+}
+
+static const struct file_operations hwsim_simulate_incumbent_signal_fops = {
+	.open	= simple_open,
+	.write	= hwsim_simulate_incumbent_signal_write,
+};
+
 static int hwsim_fops_group_read(void *dat, u64 *val)
 {
 	struct mac80211_hwsim_data *data = dat;
@@ -5832,6 +5909,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
 		debugfs_create_file("dfs_simulate_radar", 0222,
 				    data->debugfs,
 				    data, &hwsim_simulate_radar);
+	debugfs_create_file("simulate_incumbent_signal_interference", 0200,
+			    data->debugfs,
+			    data, &hwsim_simulate_incumbent_signal_fops);
 
 	if (param->pmsr_capa) {
 		data->pmsr_capa = *param->pmsr_capa;
-- 
2.34.1


^ permalink raw reply related

* [PATCH wireless-next v5 1/2] wifi: cfg80211: add support to handle incumbent signal detected event from mac80211/driver
From: Amith A @ 2026-02-16  3:20 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, amith.a, Hari Chandrakanthan
In-Reply-To: <20260216032027.2310956-1-amith.a@oss.qualcomm.com>

From: Hari Chandrakanthan <quic_haric@quicinc.com>

When any incumbent signal is detected by an AP/mesh interface operating
in 6 GHz band, FCC mandates the AP/mesh to vacate the channels affected
by it [1].

Add a new API cfg80211_incumbent_signal_notify() that can be used
by mac80211 or drivers to notify the higher layers about the signal
interference event with the interference bitmap in which each bit
denotes the affected 20 MHz in the operating channel.

Add support for the new nl80211 event and nl80211 attribute as well to
notify userspace on the details about the interference event. Userspace is
expected to process it and take further action - vacate the channel, or
reduce the bandwidth.

[1] - https://apps.fcc.gov/kdb/GetAttachment.html?id=nXQiRC%2B4mfiA54Zha%2BrW4Q%3D%3D&desc=987594%20D02%20U-NII%206%20GHz%20EMC%20Measurement%20v03&tracking_number=277034

Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
Signed-off-by: Amith A <amith.a@oss.qualcomm.com>
---
 include/net/cfg80211.h       | 23 +++++++++++++++++++++
 include/uapi/linux/nl80211.h | 19 +++++++++++++++++
 net/wireless/nl80211.c       | 40 ++++++++++++++++++++++++++++++++++++
 net/wireless/trace.h         | 19 +++++++++++++++++
 4 files changed, 101 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fc01de19c798..2311d852e19e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -10472,4 +10472,27 @@ cfg80211_s1g_get_primary_sibling(struct wiphy *wiphy,
 	return ieee80211_get_channel_khz(wiphy, sibling_1mhz_khz);
 }
 
+
+/**
+ * cfg80211_incumbent_signal_notify - Notify userspace of incumbent signal detection
+ * @wiphy: the wiphy to use
+ * @chandef: channel definition in which the interference was detected
+ * @signal_interference_bitmap: bitmap indicating interference across 20 MHz segments
+ * @gfp: allocation context for message creation and multicast; pass GFP_ATOMIC
+ *	if called from atomic context (e.g. firmware event handler), otherwise
+ *	GFP_KERNEL
+ *
+ * Use this function to notify userspace when an incumbent signal is detected on
+ * the operating channel in the 6 GHz band. The notification includes the
+ * current channel definition and a bitmap representing interference across
+ * the operating bandwidth. Each bit in the bitmap corresponds to a 20 MHz
+ * segment, with the lowest bit representing the lowest frequency segment.
+ * Punctured sub-channels are included in the bitmap structure but are always
+ * set to zero since interference detection is not performed on them.
+ */
+void cfg80211_incumbent_signal_notify(struct wiphy *wiphy,
+				      const struct cfg80211_chan_def *chandef,
+				      u32 signal_interference_bitmap,
+				      gfp_t gfp);
+
 #endif /* __NET_CFG80211_H */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index b63f71850906..b53e2d78c7bb 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1361,6 +1361,12 @@
  *	user space that the NAN new cluster has been joined. The cluster ID is
  *	indicated by %NL80211_ATTR_MAC.
  *
+ * @NL80211_CMD_INCUMBENT_SIGNAL_DETECT: Once any incumbent signal is detected
+ *	on the operating channel in 6 GHz band, userspace is notified with the
+ *	signal interference bitmap using
+ *	%NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP. The current channel
+ *	definition is also sent.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1624,6 +1630,8 @@ enum nl80211_commands {
 	NL80211_CMD_NAN_NEXT_DW_NOTIFICATION,
 	NL80211_CMD_NAN_CLUSTER_JOINED,
 
+	NL80211_CMD_INCUMBENT_SIGNAL_DETECT,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -2984,6 +2992,15 @@ enum nl80211_commands {
  *	this feature during association. This is a flag attribute.
  *	Currently only supported in mac80211 drivers.
  *
+ * @NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP: u32 attribute specifying
+ *	the signal interference bitmap detected on the operating bandwidth for
+ *	%NL80211_CMD_INCUMBENT_SIGNAL_DETECT. Each bit represents a 20 MHz
+ *	segment, lowest bit corresponds to the lowest 20 MHz segment, in the
+ *	operating bandwidth where the interference is detected. Punctured
+ *	sub-channels are included in the bitmap structure; however, since
+ *	interference detection is not performed on these sub-channels, their
+ *	corresponding bits are consistently set to zero.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3557,6 +3574,8 @@ enum nl80211_attrs {
 	NL80211_ATTR_UHR_CAPABILITY,
 	NL80211_ATTR_DISABLE_UHR,
 
+	NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6e58b238a1f8..6de846ae087f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -21129,6 +21129,46 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
 }
 EXPORT_SYMBOL(cfg80211_ch_switch_notify);
 
+void cfg80211_incumbent_signal_notify(struct wiphy *wiphy,
+				      const struct cfg80211_chan_def *chandef,
+				      u32 signal_interference_bitmap,
+				      gfp_t gfp)
+{
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+
+	trace_cfg80211_incumbent_signal_notify(wiphy, chandef, signal_interference_bitmap);
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_INCUMBENT_SIGNAL_DETECT);
+	if (!hdr)
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
+		goto nla_put_failure;
+
+	if (nl80211_send_chandef(msg, chandef))
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP,
+			signal_interference_bitmap))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+				NL80211_MCGRP_MLME, gfp);
+	return;
+
+nla_put_failure:
+	nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_incumbent_signal_notify);
+
 void cfg80211_ch_switch_started_notify(struct net_device *dev,
 				       struct cfg80211_chan_def *chandef,
 				       unsigned int link_id, u8 count,
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 643ccf4f0227..352a57d8b968 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -4225,6 +4225,25 @@ TRACE_EVENT(cfg80211_nan_cluster_joined,
 		  WDEV_PR_ARG, __entry->cluster_id,
 		  __entry->new_cluster ? " [new]" : "")
 );
+
+TRACE_EVENT(cfg80211_incumbent_signal_notify,
+	TP_PROTO(struct wiphy *wiphy,
+		 const struct cfg80211_chan_def *chandef,
+		 u32 signal_interference_bitmap),
+	TP_ARGS(wiphy, chandef, signal_interference_bitmap),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		CHAN_DEF_ENTRY
+		__field(u32, signal_interference_bitmap)
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		CHAN_DEF_ASSIGN(chandef);
+		__entry->signal_interference_bitmap = signal_interference_bitmap;
+	),
+	TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", signal_interference_bitmap=0x%x",
+		  WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->signal_interference_bitmap)
+);
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
-- 
2.34.1


^ permalink raw reply related

* [PATCH wireless-next v5 0/2] wifi: cfg80211/mac80211: add support to handle incumbent signal detected event
From: Amith A @ 2026-02-16  3:20 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, amith.a

This patch series adds support to handle incumbent signal interference
detected event in 6 GHz band. When an incumbent signal is detected by an
AP/mesh interface operating in 6 GHz band, the AP/mesh is expected to
vacate the channels affected by it.

Driver is expected to call the newly introduced API with required
information to notify the interference detection. This information will be
ultimately sent to user space via NL802111 command. User space is expected
to process it and take further action - vacate the channel, or reduce the
bandwidth.

Aditya Kumar Singh (1):
  wifi: mac80211_hwsim: add incumbent signal interference detection
    support

Hari Chandrakanthan (1):
  wifi: cfg80211: add support to handle incumbent signal detected event
    from mac80211/driver
---
Changes in v5:
 - Made chandef const in cfg80211_incumbent_signal_notify()
 - Removed mac80211 wrapper ieee80211_incumbent_signal_detected(). 
   Driver/hwsim calls cfg80211 notify directly.
 - In mac80211_hwsim, switched debugfs to custom fops with .write that
   accepts “freq_mhz bitmap”. Now 6 GHz chanctx is selected by primary
   20 MHz center.

Changes in v4:
 - Restored gfp_t in cfg80211_incumbent_signal_notify().
 - Dropped incumbt_sig_intf_bmap from ieee80211_chanctx_conf and passed
   bitmap directly.
 - Updated trace/call path: api_incumbent_signal_detected() to take bitmap
 - Simplified hwsim: removed helper struct.

Changes in v3:
 - Removed the workqueue mechanism in ieee80211_incumbent_signal_detected(),
   exported the cfg80211_ function that sends the NL80211 command and called
   it from ieee80211_incumbent_signal_detected() directly.
 - Renamed nl80211_incumbent_signal_notify() to
   cfg80211_incumbent_signal_notify() and removed the gfp argument from it.

Changes in v2:
 - Updated the kernel doc of NL80211_ATTR_INCUMBENT_SIGNAL_INTERFERENCE_BITMAP
   to include details of how it interacts with puncturing.
 - Rebased on ToT
---
 drivers/net/wireless/virtual/mac80211_hwsim.c | 80 +++++++++++++++++++
 drivers/net/wireless/virtual/mac80211_hwsim.h |  2 +
 include/net/cfg80211.h                        | 23 ++++++
 include/uapi/linux/nl80211.h                  | 19 +++++
 net/wireless/nl80211.c                        | 40 ++++++++++
 net/wireless/trace.h                          | 19 +++++
 6 files changed, 183 insertions(+)


base-commit: 333225e1e9ead7b06e5363389403bdac72ba3046
-- 
2.34.1


^ permalink raw reply

* Re: [PATCH ath-next] wifi: ath12k: add basic hwmon temperature reporting
From: kernel test robot @ 2026-02-15 17:53 UTC (permalink / raw)
  To: Maharaja Kennadyrajan, ath12k
  Cc: oe-kbuild-all, linux-wireless, Maharaja Kennadyrajan, Aishwarya R
In-Reply-To: <20260214035947.44671-1-maharaja.kennadyrajan@oss.qualcomm.com>

Hi Maharaja,

kernel test robot noticed the following build errors:

[auto build test ERROR on 37a93dd5c49b5fda807fd204edf2547c3493319c]

url:    https://github.com/intel-lab-lkp/linux/commits/Maharaja-Kennadyrajan/wifi-ath12k-add-basic-hwmon-temperature-reporting/20260214-120212
base:   37a93dd5c49b5fda807fd204edf2547c3493319c
patch link:    https://lore.kernel.org/r/20260214035947.44671-1-maharaja.kennadyrajan%40oss.qualcomm.com
patch subject: [PATCH ath-next] wifi: ath12k: add basic hwmon temperature reporting
config: x86_64-randconfig-075-20250806 (https://download.01.org/0day-ci/archive/20260216/202602160145.YQdvbqYY-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260216/202602160145.YQdvbqYY-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602160145.YQdvbqYY-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: vmlinux.o: in function `ath12k_thermal_unregister':
>> drivers/net/wireless/ath/ath12k/thermal.c:118:(.text+0x2df8112): undefined reference to `hwmon_device_unregister'


vim +118 drivers/net/wireless/ath/ath12k/thermal.c

   106	
   107	void ath12k_thermal_unregister(struct ath12k_base *ab)
   108	{
   109		struct ath12k *ar;
   110		int i;
   111	
   112		for (i = 0; i < ab->num_radios; i++) {
   113			ar = ab->pdevs[i].ar;
   114			if (!ar)
   115				continue;
   116	
   117			if (ar->thermal.hwmon_dev) {
 > 118				hwmon_device_unregister(ar->thermal.hwmon_dev);

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v5 2/2] dt-bindings: net: wireless: mt76: clarify backoff limit usage
From: Krzysztof Kozlowski @ 2026-02-15  8:55 UTC (permalink / raw)
  To: Ryder Lee
  Cc: robh@kernel.org, nbd@nbd.name, linux-mediatek@lists.infradead.org,
	devicetree@vger.kernel.org, Allen Ye (葉芷勳),
	linux-wireless@vger.kernel.org
In-Reply-To: <d7e22b328fda50ebbf96f334fc15d63da9e7c19b.camel@mediatek.com>

On 12/02/2026 18:31, Ryder Lee wrote:
>>>  
>>>    reg:
>>>      minItems: 1
>>> @@ -252,6 +257,14 @@ properties:
>>>                        followed by 10 power limit values. The order
>>> of the
>>>                        channel resource unit settings is RU26,
>>> RU52, RU106,
>>>                        RU242/SU20, RU484/SU40, RU996/SU80 and
>>> RU2x996/SU160.
>>> +                      - For mt7981/mt7986/mt7915/mt7916
>>> +                        - Beamforming entries for BW20~BW160 and
>>> OFDM do not
>>> +                          include 1T1ss.
>>> +                        - When 1T1ss is not used, it should be
>>> filled with 0.
>>
>> Shouldn't be skipped in such case? Why filling with 0 matters?
>>
> This logic was already present in driver. The driver determines whether
> to skip 1T1ss based on its value (0), so my update is focused on
> improving the documentation to guide users on the correct DTS format.
> 
> For example, in the paths-ru-bf entries:
> <1 20 22 38 36 24 30 23 21 28 29>,
> <1 20 39 31 25 26 25 28 30 39 39>,
> <1 37 34 26 26 25 21 34 23 34 24>,
> <1 0 20 23 31 23 30 39 28 29 36>,
> <1 0 27 34 33 34 29 38 33 33 22>,
> <1 0 30 23 39 28 21 25 29 28 21>,
> <1 0 34 20 38 32 35 33 37 26 36>;
> (The order of all fields is required by the firmware.)
> 
> The value for 1T1ss is set to 0 when it is not used, and the driver
> will skip it during parsing. So, users should always fill the DTS with
> all 10 values, using 0 for unused entries.
> 
> This ensures that the parsing logic remains simple and uniform,
> avoiding potential errors or misalignment.
> 

OK

Best regards,
Krzysztof

^ permalink raw reply

* RE: iwlmld iwl_mld_change_vif_links can return un-initilized 'err'
From: Korenblit, Miriam Rachel @ 2026-02-15  4:29 UTC (permalink / raw)
  To: Ben Greear, linux-wireless@vger.kernel.org
In-Reply-To: <1cf6d7aa-7ced-4fba-88e1-adb1cfdecadf@candelatech.com>



> -----Original Message-----
> From: Ben Greear <greearb@candelatech.com>
> Sent: Saturday, February 14, 2026 7:15 PM
> To: linux-wireless@vger.kernel.org
> Cc: Korenblit, Miriam Rachel <miriam.rachel.korenblit@intel.com>
> Subject: Re: iwlmld iwl_mld_change_vif_links can return un-initilized 'err'
> 
> On 2/14/26 09:11, Ben Greear wrote:
> > Hello,
> >
> > I believe this method:
> >
> > static int
> > iwl_mld_change_vif_links(struct ieee80211_hw *hw,
> >
> > Can return un-initialized 'err' in case that this return path is taken:
> >
> >      if (WARN_ON(!iwl_mld_error_before_recovery(mld)))
> >          return err;

If we are under remove_added_links, this means that err is initialized.


^ permalink raw reply

* [PATCH AUTOSEL 6.19-6.18] wifi: rtw89: fix potential zero beacon interval in beacon tracking
From: Sasha Levin @ 2026-02-14 21:23 UTC (permalink / raw)
  To: patches, stable
  Cc: Kuan-Chung Chen, Ping-Ke Shih, Sasha Levin, linux-wireless
In-Reply-To: <20260214212452.782265-1-sashal@kernel.org>

From: Kuan-Chung Chen <damon.chen@realtek.com>

[ Upstream commit eb57be32f438c57c88d6ce756101c1dfbcc03bba ]

During fuzz testing, it was discovered that bss_conf->beacon_int
might be zero, which could result in a division by zero error in
subsequent calculations. Set a default value of 100 TU if the
interval is zero to ensure stability.

Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20251231090647.56407-11-pkshih@realtek.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Analysis of commit: "wifi: rtw89: fix potential zero beacon interval
in beacon tracking"

### 1. COMMIT MESSAGE ANALYSIS

The subject line explicitly says "fix" and describes a concrete bug:
**division by zero** when `beacon_int` is zero. The commit message
mentions this was found during **fuzz testing**, which is analogous to
syzbot/syzkaller findings — these are reproducible, real bugs. The
author is from Realtek (the hardware vendor), and the commit was signed
off by the subsystem maintainer (Ping-Ke Shih).

### 2. CODE CHANGE ANALYSIS

The patch makes two related changes:

**Change 1: `rtw89_core_bcn_track_assoc()`**
```c
- beacon_int = bss_conf->beacon_int;
+ beacon_int = bss_conf->beacon_int ?: 100;
```
This uses the GCC ternary shorthand to default to 100 TU if `beacon_int`
is zero. The value 100 TU is a reasonable default (standard beacon
interval). Without this, `beacon_int = 0` flows into:
- `beacons_in_period = period / beacon_int / dtim;` — **division by
  zero**
- `bcn_intvl_us = ieee80211_tu_to_usec(beacon_int);` which becomes 0,
  leading to another division by zero later in `rtw89_vif_rx_bcn_stat()`

**Change 2: `rtw89_vif_rx_bcn_stat()` refactored**
- The function signature drops the `bss_conf` parameter and instead
  reads `beacon_int` from `bcn_track->beacon_int` (which was already set
  with the safe default in the assoc function).
- Adds an explicit guard: `if (!bcn_intvl_us) return;` to handle the
  case where association hasn't happened yet.
- This prevents `div_u64_rem(tsf - append, bcn_intvl_us, ...)` from
  dividing by zero.

**Change 3: Call site update**
```c
- rtw89_vif_rx_bcn_stat(rtwdev, bss_conf, skb);
+ rtw89_vif_rx_bcn_stat(rtwdev, skb);
```
Simply adapts the caller to the new signature.

### 3. BUG CLASSIFICATION

This is a **division by zero** bug — a crash/panic-class issue. On most
kernel configurations, division by zero causes an **Oops or kernel
panic**. This is clearly a real bug that affects system stability.

The bug was found through fuzz testing, meaning there is a concrete
trigger path. While the exact fuzz scenario may be unusual in normal
operation, the `bss_conf->beacon_int` being zero is a real possibility
(malformed beacon frames, race conditions during association, etc.).

### 4. SCOPE AND RISK ASSESSMENT

- **Lines changed**: ~15 lines of actual logic change — very small and
  surgical
- **Files changed**: 1 file
  (`drivers/net/wireless/realtek/rtw89/core.c`)
- **Subsystem**: WiFi driver (rtw89) — contained to one driver
- **Risk**: Very low. The changes are:
  - A defensive default value (100 TU is standard)
  - A guard check for zero before division
  - Using already-stored `bcn_track->beacon_int` instead of re-reading
    from `bss_conf`
- **Regression potential**: Minimal. The only behavioral change is
  preventing a crash and using a sensible default.

### 5. USER IMPACT

The rtw89 driver supports Realtek WiFi chips (RTL8852A, RTL8852B,
RTL8852C, RTL8922A, etc.) which are widely used in modern laptops and
desktops. A kernel crash/panic from a division by zero would be severe
for any user of these chips. Even if the trigger requires unusual beacon
conditions, malicious actors could potentially craft beacon frames to
trigger this remotely.

### 6. STABLE CRITERIA CHECK

- **Obviously correct and tested**: Yes — simple defensive coding, from
  the hardware vendor
- **Fixes a real bug**: Yes — division by zero causing kernel crash
- **Important issue**: Yes — kernel crash/panic
- **Small and contained**: Yes — ~15 lines in one file
- **No new features**: Correct — purely a bug fix
- **No new APIs**: Correct

### 7. DEPENDENCY CHECK

The `rtw89_vif_rx_bcn_stat()` function signature change means the patch
needs to apply as a unit, but it's self-contained within this single
commit. The beacon tracking infrastructure (`bcn_track`) must exist in
the stable tree. This was added relatively recently, so it may only
apply to very recent stable branches. However, if the code exists, this
fix applies cleanly.

### 8. CONCLUSION

This is a clear-cut bug fix: it prevents a division-by-zero kernel crash
in a widely-used WiFi driver. The fix is small, surgical, obviously
correct, and comes from the hardware vendor. It meets all stable kernel
criteria.

**YES**

 drivers/net/wireless/realtek/rtw89/core.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 0824940c91aee..d5b492ea76ef4 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -2785,7 +2785,7 @@ static void rtw89_core_bcn_track_assoc(struct rtw89_dev *rtwdev,
 
 	rcu_read_lock();
 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
-	beacon_int = bss_conf->beacon_int;
+	beacon_int = bss_conf->beacon_int ?: 100;
 	dtim = bss_conf->dtim_period;
 	rcu_read_unlock();
 
@@ -2815,9 +2815,7 @@ static void rtw89_core_bcn_track_reset(struct rtw89_dev *rtwdev)
 	memset(&rtwdev->bcn_track, 0, sizeof(rtwdev->bcn_track));
 }
 
-static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev,
-				  struct ieee80211_bss_conf *bss_conf,
-				  struct sk_buff *skb)
+static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev, struct sk_buff *skb)
 {
 #define RTW89_APPEND_TSF_2GHZ 384
 #define RTW89_APPEND_TSF_5GHZ 52
@@ -2826,7 +2824,7 @@ static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev,
 	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
 	struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat;
 	struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track;
-	u32 bcn_intvl_us = ieee80211_tu_to_usec(bss_conf->beacon_int);
+	u32 bcn_intvl_us = ieee80211_tu_to_usec(bcn_track->beacon_int);
 	u64 tsf = le64_to_cpu(mgmt->u.beacon.timestamp);
 	u8 wp, num = bcn_stat->num;
 	u16 append;
@@ -2834,6 +2832,10 @@ static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev,
 	if (!RTW89_CHK_FW_FEATURE(BEACON_TRACKING, &rtwdev->fw))
 		return;
 
+	/* Skip if not yet associated */
+	if (!bcn_intvl_us)
+		return;
+
 	switch (rx_status->band) {
 	default:
 	case NL80211_BAND_2GHZ:
@@ -2921,7 +2923,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
 		pkt_stat->beacon_rate = desc_info->data_rate;
 		pkt_stat->beacon_len = skb->len;
 
-		rtw89_vif_rx_bcn_stat(rtwdev, bss_conf, skb);
+		rtw89_vif_rx_bcn_stat(rtwdev, skb);
 	}
 
 	if (!ether_addr_equal(bss_conf->addr, hdr->addr1))
-- 
2.51.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.19-6.12] wifi: rtw89: 8922a: set random mac if efuse contains zeroes
From: Sasha Levin @ 2026-02-14 21:23 UTC (permalink / raw)
  To: patches, stable
  Cc: Jose Ignacio Tornos Martinez, Ping-Ke Shih, Sasha Levin,
	linux-wireless
In-Reply-To: <20260214212452.782265-1-sashal@kernel.org>

From: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>

[ Upstream commit 41be33d3efc120f6a2c02d12742655f2aa09e1b6 ]

I have some rtl8922ae devices with no permanent mac stored in efuse.

It could be properly saved and/or configured from user tools like
NetworkManager, but it would be desirable to be able to initialize it
somehow to get the device working by default.

So, in the same way as with other devices, if the mac address read from
efuse contains zeros, a random mac address is assigned to at least allow
operation, and the user is warned about this in case any action needs to
be considered.

Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20251126091905.217951-1-jtornosm@redhat.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The rtw8922a driver was first included in kernel v6.8. This means it's
available in stable trees 6.8.y and later (and likely in 6.6.y LTS if it
was backported, but probably not).

### 8. OVERALL ASSESSMENT

**Arguments FOR backporting (YES):**
- Fixes a real hardware issue — devices with empty efuse are completely
  unusable without this
- Very small, contained change in a single file
- Well-established pattern used in rtw88 driver and other Realtek
  wireless drivers
- Low risk — only affects devices with all-zero MAC (no impact on
  working devices)
- Acked by subsystem maintainer
- Falls under "hardware quirk/workaround" category which is acceptable
  for stable

**Arguments AGAINST backporting (NO):**
- This is technically adding new functionality (random MAC generation)
  rather than fixing a bug in existing code
- The driver was working "as designed" — it just didn't handle the case
  of unprogrammed efuse
- It's not fixing a crash, corruption, or security issue — it's making
  broken hardware work
- The commit message describes this as a "desirable" improvement rather
  than a critical fix
- No Fixes: tag or Cc: stable (expected, but also suggests the author
  didn't consider it critical)

### DECISION

This is a borderline case. While the change is small and low-risk, it's
fundamentally adding new behavior (random MAC assignment) rather than
fixing a bug in existing code. The device doesn't crash without this —
it simply doesn't have a valid MAC address. This is closer to a
"hardware enablement" change than a bug fix.

However, I lean toward YES because:
1. It's a hardware workaround for broken/unprogrammed devices — this
   category is explicitly allowed in stable
2. Without it, the device is completely non-functional (a zero MAC
   address is invalid)
3. The risk is essentially zero for existing users
4. The pattern is proven across the Realtek driver family
5. It's a small, self-contained change

**YES**

 drivers/net/wireless/realtek/rtw89/rtw8922a.c | 22 +++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 4437279c554b0..4bcf20612a455 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -636,16 +636,30 @@ static int rtw8922a_read_efuse_rf(struct rtw89_dev *rtwdev, u8 *log_map)
 static int rtw8922a_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
 			       enum rtw89_efuse_block block)
 {
+	struct rtw89_efuse *efuse = &rtwdev->efuse;
+	int ret;
+
 	switch (block) {
 	case RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO:
-		return rtw8922a_read_efuse_pci_sdio(rtwdev, log_map);
+		ret = rtw8922a_read_efuse_pci_sdio(rtwdev, log_map);
+		break;
 	case RTW89_EFUSE_BLOCK_HCI_DIG_USB:
-		return rtw8922a_read_efuse_usb(rtwdev, log_map);
+		ret = rtw8922a_read_efuse_usb(rtwdev, log_map);
+		break;
 	case RTW89_EFUSE_BLOCK_RF:
-		return rtw8922a_read_efuse_rf(rtwdev, log_map);
+		ret = rtw8922a_read_efuse_rf(rtwdev, log_map);
+		break;
 	default:
-		return 0;
+		ret = 0;
+		break;
+	}
+
+	if (!ret && is_zero_ether_addr(efuse->addr)) {
+		rtw89_info(rtwdev, "efuse mac address is zero, using random mac\n");
+		eth_random_addr(efuse->addr);
 	}
+
+	return ret;
 }
 
 #define THM_TRIM_POSITIVE_MASK BIT(6)
-- 
2.51.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