* Re: [PATCH wireless-next v2 2/2] wifi: mt76: mt7996: Add eMLSR support
From: Christian Marangi @ 2026-01-26 11:03 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Johannes Berg, Ryder Lee, Sean Wang, Matthias Brugger,
AngeloGioacchino Del Regno, linux-wireless, Felix Fietkau,
Shayne Chen, linux-mediatek, linux-arm-kernel, MeiChia Chiu
In-Reply-To: <20260125-mac80211-emlsr-v2-2-466329d61c88@kernel.org>
On Sun, Jan 25, 2026 at 11:51:31AM +0100, Lorenzo Bianconi wrote:
> From: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
>
> Implement set_eml_op_mode mac80211 callback in order to introduce eMLSR
> support.
>
> Signed-off-by: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
> Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
--
Ansuel
^ permalink raw reply
* [PATCH ath-current] wifi: ath12k: fix wrong TID passed when stopping AMPDU session
From: Pablo MARTIN-GOMEZ @ 2026-01-26 11:35 UTC (permalink / raw)
To: ath12k, Jeff Johnson; +Cc: linux-wireless
When handling a DELBA request, ath12k_dp_rx_ampdu_stop() calls
ath12k_peer_rx_tid_reo_update() to tear down the BA session for the
specified TID. However, it currently passes peer->rx_tid instead of the
entry corresponding to params->tid.
Since peer->rx_tid is an array, this decays to a pointer to the first
element, effectively operating on TID 0 regardless of the TID in the
DELBA request. As a result, the BA session for TID 0 is stopped while
the intended TID remains active.
This leads to incorrect BA session state and may significantly reduce
RX throughput, as traffic that should use aggregation falls back to a
BA window size of 1 on TID 0.
Fix this by passing the correct TID entry:
&peer->rx_tid[params->tid]
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Pablo Martin-Gomez <pmartin-gomez@freebox.fr>
---
drivers/net/wireless/ath/ath12k/dp_rx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c
b/drivers/net/wireless/ath/ath12k/dp_rx.c
index d28d8ffec0f8..f2327c82953b 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -1289,7 +1289,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
return 0;
}
- ret = ath12k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0,
false);
+ ret = ath12k_peer_rx_tid_reo_update(ar, peer,
&peer->rx_tid[params->tid], 1, 0, false);
spin_unlock_bh(&ab->base_lock);
if (ret) {
ath12k_warn(ab, "failed to update reo for rx tid %d: %d\n",
--
2.43.0
^ permalink raw reply related
* [PATCH ath-current] wifi: ath11k: fix wrong TID passed when stopping AMPDU session
From: Pablo MARTIN-GOMEZ @ 2026-01-26 11:42 UTC (permalink / raw)
To: ath11k, Jeff Johnson; +Cc: linux-wireless
When handling a DELBA request, ath11k_dp_rx_ampdu_stop() calls
ath11k_peer_rx_tid_reo_update() to tear down the BA session for the
specified TID. However, it currently passes peer->rx_tid instead of the
entry corresponding to params->tid.
Since peer->rx_tid is an array, this decays to a pointer to the first
element, effectively operating on TID 0 regardless of the TID in the
DELBA request. As a result, the BA session for TID 0 is stopped while
the intended TID remains active.
This leads to incorrect BA session state and may significantly reduce
RX throughput, as traffic that should use aggregation falls back to a
BA window size of 1 on TID 0.
Fix this by passing the correct TID entry:
&peer->rx_tid[params->tid]
Fixes: fe201947f8bd ("ath11k: update bawindow size in delba process")
Signed-off-by: Pablo Martin-Gomez <pmartin-gomez@freebox.fr>
---
drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c
b/drivers/net/wireless/ath/ath11k/dp_rx.c
index b9e976ddcbbf..8db04c38dfba 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -1132,7 +1132,7 @@ int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
return 0;
}
- ret = ath11k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0,
false);
+ ret = ath11k_peer_rx_tid_reo_update(ar, peer,
&peer->rx_tid[params->tid], 1, 0, false);
spin_unlock_bh(&ab->base_lock);
if (ret) {
ath11k_warn(ab, "failed to update reo for rx tid %d: %d\n",
--
2.43.0
^ permalink raw reply related
* RE: [PATCH] Revert "wifi: iwlwifi: trans: remove STATUS_SUSPENDED"
From: Korenblit, Miriam Rachel @ 2026-01-26 13:45 UTC (permalink / raw)
To: Chris Bainbridge
Cc: kvalo@kernel.org, Berg, Johannes, benjamin@sipsolutions.net,
gustavoars@kernel.org, linux-intel-wifi@intel.com,
linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org
In-Reply-To: <aXcovK8uhsiaHumT@debian.local>
[-- Attachment #1: Type: text/plain, Size: 887 bytes --]
> -----Original Message-----
> From: Chris Bainbridge <chris.bainbridge@gmail.com>
> Sent: Monday, January 26, 2026 10:42 AM
> To: Korenblit, Miriam Rachel <miriam.rachel.korenblit@intel.com>
> Cc: kvalo@kernel.org; Berg, Johannes <johannes.berg@intel.com>;
> benjamin@sipsolutions.net; gustavoars@kernel.org; linux-intel-wifi@intel.com;
> linux-wireless@vger.kernel.org; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org; stable@vger.kernel.org
> Subject: Re: [PATCH] Revert "wifi: iwlwifi: trans: remove STATUS_SUSPENDED"
>
> On Mon, Jan 26, 2026 at 07:15:54AM +0000, Korenblit, Miriam Rachel wrote:
> >
> > Hi Chris, could you please provide the full log?
> >
> > Miri
>
> Sure, for 6.18.0 see https://lore.kernel.org/linux-
> wireless/aTDoDiD55qlUZ0pn@debian.local/
>
>
Thanks!
could you please test if the attached patch eliminates the panic?
[-- Attachment #2: 0001-wifi-iwlwifi-mvm-cleanup-IWL_MVM_STATUS_IN_HW_RESTAR.patch --]
[-- Type: application/octet-stream, Size: 1754 bytes --]
From 42490ba7e9adecd3a4f67f3aa748b5868c90bd49 Mon Sep 17 00:00:00 2001
From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Date: Mon, 26 Jan 2026 15:36:24 +0200
Subject: [PATCH] wifi: iwlwifi: mvm: cleanup IWL_MVM_STATUS_IN_HW_RESTART in
resume
Organization: Intel Israel (74) Limited
In suspend without wowlan, if we had an assert before resume, then
restart_work is pending and IWL_MVM_STATUS_HW_RESTART_REQUESTED is set.
Since restart work is on the system_freezable_wq, it will not be executed
before the resume.
In resume, mac80211 cancels the pending restart work, becuase the resume
process restarts the hw anyway.
Then drv_start is called, in which iwlmvm sets
IWL_MVM_STATUS_IN_HW_RESTART, but doesn't clear it anywhere if we were
able to restart the hw.
Fix it by clearing IWL_MVM_STATUS_IN_HW_RESTART also when
iwl_mvm_mac_reconfig_complete is called with IEEE80211_RECONFIG_TYPE_SUSPEND,
and not just with IEEE80211_RECONFIG_TYPE_RESTART.
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Change-Id: I6435100c880975ce95cac2dbdf5ec160098a2291
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index d806b8e50ec0..a6d0c53b94e0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1467,6 +1467,8 @@ void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
+
switch (reconfig_type) {
case IEEE80211_RECONFIG_TYPE_RESTART:
iwl_mvm_restart_complete(mvm);
--
2.34.1
^ permalink raw reply related
* Re: [PATCH] wifi: rtw89: usb: fix TX flow control by tracking in-flight URBs
From: Bitterblue Smith @ 2026-01-26 14:09 UTC (permalink / raw)
To: Lucid Duck, linux-wireless; +Cc: Ping-Ke Shih
In-Reply-To: <20260125221943.36001-1-lucid_duck@justthetip.ca>
On 26/01/2026 00:19, Lucid Duck wrote:
> rtw89_usb_ops_check_and_reclaim_tx_resource() currently returns a
> hardcoded placeholder value of 42, violating mac80211's TX flow control
> contract. This causes uncontrolled URB accumulation under sustained TX
> load since mac80211 believes resources are always available.
>
> Fix this by implementing proper TX backpressure:
>
> - Add per-channel atomic counters (tx_inflight[]) to track URBs between
> submission and completion
> - Increment counter before usb_submit_urb() with rollback on failure
> - Decrement counter in completion callback
> - Return available slots (max - inflight) to mac80211, or 0 at capacity
> - Exclude firmware command channel (CH12) from flow control
>
> Tested on D-Link DWA-X1850 (RTL8832AU) with:
> - Sustained high-throughput traffic
> - Module load/unload stress tests
> - Hot-unplug during active transmission
> - 30-minute soak test verifying counters balance at idle
>
> Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca>
> ---
> drivers/net/wireless/realtek/rtw89/usb.c | 27 ++++++++++++++++++++++--
> drivers/net/wireless/realtek/rtw89/usb.h | 6 ++++++
> 2 files changed, 31 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
> index e77561a4d..6fcf32603 100644
> --- a/drivers/net/wireless/realtek/rtw89/usb.c
> +++ b/drivers/net/wireless/realtek/rtw89/usb.c
> @@ -161,16 +161,25 @@ static u32
> rtw89_usb_ops_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev,
> u8 txch)
> {
> + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
> + int inflight;
> +
> + /* Firmware command channel is not flow-controlled */
> if (txch == RTW89_TXCH_CH12)
> return 1;
>
> - return 42; /* TODO some kind of calculation? */
> + inflight = atomic_read(&rtwusb->tx_inflight[txch]);
> + if (inflight >= RTW89_USB_MAX_TX_URBS_PER_CH)
> + return 0;
> +
> + return RTW89_USB_MAX_TX_URBS_PER_CH - inflight;
> }
>
> static void rtw89_usb_write_port_complete(struct urb *urb)
> {
> struct rtw89_usb_tx_ctrl_block *txcb = urb->context;
> struct rtw89_dev *rtwdev = txcb->rtwdev;
> + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
> struct ieee80211_tx_info *info;
> struct rtw89_txwd_body *txdesc;
> struct sk_buff *skb;
> @@ -229,6 +238,10 @@ static void rtw89_usb_write_port_complete(struct urb *urb)
> break;
> }
>
> + /* Decrement in-flight counter (skip firmware command channel) */
> + if (txcb->txch != RTW89_TXCH_CH12)
You don't need to add these checks because there is one in
rtw89_usb_ops_check_and_reclaim_tx_resource().
> + atomic_dec(&rtwusb->tx_inflight[txcb->txch]);
> +
> kfree(txcb);
> }
>
> @@ -306,9 +319,17 @@ static void rtw89_usb_ops_tx_kick_off(struct rtw89_dev *rtwdev, u8 txch)
>
> skb_queue_tail(&txcb->tx_ack_queue, skb);
>
> + /* Increment BEFORE submit to avoid race with completion */
> + if (txch != RTW89_TXCH_CH12)
> + atomic_inc(&rtwusb->tx_inflight[txch]);
> +
> ret = rtw89_usb_write_port(rtwdev, txch, skb->data, skb->len,
> txcb);
> if (ret) {
> + /* Rollback increment on failure */
> + if (txch != RTW89_TXCH_CH12)
> + atomic_dec(&rtwusb->tx_inflight[txch]);
> +
> if (ret != -ENODEV)
> rtw89_err(rtwdev, "write port txch %d failed: %d\n",
> txch, ret);
> @@ -666,8 +687,10 @@ static void rtw89_usb_init_tx(struct rtw89_dev *rtwdev)
> struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
> int i;
>
> - for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++)
> + for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) {
> skb_queue_head_init(&rtwusb->tx_queue[i]);
> + atomic_set(&rtwusb->tx_inflight[i], 0);
> + }
> }
>
> static void rtw89_usb_deinit_tx(struct rtw89_dev *rtwdev)
> diff --git a/drivers/net/wireless/realtek/rtw89/usb.h b/drivers/net/wireless/realtek/rtw89/usb.h
> index 203ec8e99..f72a8b1b2 100644
> --- a/drivers/net/wireless/realtek/rtw89/usb.h
> +++ b/drivers/net/wireless/realtek/rtw89/usb.h
> @@ -20,6 +20,9 @@
> #define RTW89_MAX_ENDPOINT_NUM 9
> #define RTW89_MAX_BULKOUT_NUM 7
>
> +/* TX flow control: max in-flight URBs per channel */
> +#define RTW89_USB_MAX_TX_URBS_PER_CH 32
> +
> struct rtw89_usb_info {
> u32 usb_host_request_2;
> u32 usb_wlan0_1;
> @@ -63,6 +66,9 @@ struct rtw89_usb {
> struct usb_anchor tx_submitted;
>
> struct sk_buff_head tx_queue[RTW89_TXCH_NUM];
> +
> + /* TX flow control: track in-flight URBs per channel */
> + atomic_t tx_inflight[RTW89_TXCH_NUM];
Is there a reason to add a new counter instead of just using
the length of each tx_queue?
> };
>
> static inline struct rtw89_usb *rtw89_usb_priv(struct rtw89_dev *rtwdev)
^ permalink raw reply
* Re: [PATCH ath-current] wifi: ath12k: fix wrong TID passed when stopping AMPDU session
From: Jeff Johnson @ 2026-01-26 17:28 UTC (permalink / raw)
To: Pablo MARTIN-GOMEZ, ath12k; +Cc: linux-wireless
In-Reply-To: <2633095a-9555-45bf-b143-ad2bdaa1ab01@freebox.fr>
On 1/26/2026 3:35 AM, Pablo MARTIN-GOMEZ wrote:
> When handling a DELBA request, ath12k_dp_rx_ampdu_stop() calls
> ath12k_peer_rx_tid_reo_update() to tear down the BA session for the
> specified TID. However, it currently passes peer->rx_tid instead of the
> entry corresponding to params->tid.
>
> Since peer->rx_tid is an array, this decays to a pointer to the first
> element, effectively operating on TID 0 regardless of the TID in the
> DELBA request. As a result, the BA session for TID 0 is stopped while
> the intended TID remains active.
>
> This leads to incorrect BA session state and may significantly reduce
> RX throughput, as traffic that should use aggregation falls back to a
> BA window size of 1 on TID 0.
>
> Fix this by passing the correct TID entry:
> &peer->rx_tid[params->tid]
>
> Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
> Signed-off-by: Pablo Martin-Gomez <pmartin-gomez@freebox.fr>
> ---
> drivers/net/wireless/ath/ath12k/dp_rx.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c
> b/drivers/net/wireless/ath/ath12k/dp_rx.c
> index d28d8ffec0f8..f2327c82953b 100644
> --- a/drivers/net/wireless/ath/ath12k/dp_rx.c
> +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
> @@ -1289,7 +1289,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
> return 0;
> }
>
> - ret = ath12k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0,
> false);
> + ret = ath12k_peer_rx_tid_reo_update(ar, peer,
> &peer->rx_tid[params->tid], 1, 0, false);
FYI your e-mail client is munging your patch, adding a line break.
And using "view source" it looks like other artifacts are being added.
My tooling (using 'b4') cannot process your patch...
Applying: wifi: ath12k: fix wrong TID passed when stopping AMPDU session
error: git diff header lacks filename information when removing 1 leading pathname component (line 6)
Suggest using https://b4.docs.kernel.org/en/latest/contributor/overview.html
> spin_unlock_bh(&ab->base_lock);
> if (ret) {
> ath12k_warn(ab, "failed to update reo for rx tid %d: %d\n",
^ permalink raw reply
* Re: [PATCH v5 15/36] srcu: Support Clang's context analysis
From: Bart Van Assche @ 2026-01-26 17:31 UTC (permalink / raw)
To: Marco Elver, Peter Zijlstra, Boqun Feng, Ingo Molnar, Will Deacon
Cc: David S. Miller, Luc Van Oostenryck, Chris Li, Paul E. McKenney,
Alexander Potapenko, Arnd Bergmann, Christoph Hellwig,
Dmitry Vyukov, Eric Dumazet, Frederic Weisbecker,
Greg Kroah-Hartman, Herbert Xu, Ian Rogers, Jann Horn,
Joel Fernandes, Johannes Berg, Jonathan Corbet, Josh Triplett,
Justin Stitt, Kees Cook, Kentaro Takeda, Lukas Bulwahn,
Mark Rutland, Mathieu Desnoyers, Miguel Ojeda, Nathan Chancellor,
Neeraj Upadhyay, Nick Desaulniers, Steven Rostedt, Tetsuo Handa,
Thomas Gleixner, Thomas Graf, Uladzislau Rezki, Waiman Long,
kasan-dev, linux-crypto, linux-doc, linux-kbuild, linux-kernel,
linux-mm, linux-security-module, linux-sparse, linux-wireless,
llvm, rcu
In-Reply-To: <20251219154418.3592607-16-elver@google.com>
On 12/19/25 7:40 AM, Marco Elver wrote:
> +/*
> + * No-op helper to denote that ssp must be held. Because SRCU-protected pointers
> + * should still be marked with __rcu_guarded, and we do not want to mark them
> + * with __guarded_by(ssp) as it would complicate annotations for writers, we
> + * choose the following strategy: srcu_dereference_check() calls this helper
> + * that checks that the passed ssp is held, and then fake-acquires 'RCU'.
> + */
> +static inline void __srcu_read_lock_must_hold(const struct srcu_struct *ssp) __must_hold_shared(ssp) { }
>
> /**
> * srcu_dereference_check - fetch SRCU-protected pointer for later dereferencing
> @@ -223,9 +233,15 @@ static inline int srcu_read_lock_held(const struct srcu_struct *ssp)
> * to 1. The @c argument will normally be a logical expression containing
> * lockdep_is_held() calls.
> */
> -#define srcu_dereference_check(p, ssp, c) \
> - __rcu_dereference_check((p), __UNIQUE_ID(rcu), \
> - (c) || srcu_read_lock_held(ssp), __rcu)
> +#define srcu_dereference_check(p, ssp, c) \
> +({ \
> + __srcu_read_lock_must_hold(ssp); \
> + __acquire_shared_ctx_lock(RCU); \
> + __auto_type __v = __rcu_dereference_check((p), __UNIQUE_ID(rcu), \
> + (c) || srcu_read_lock_held(ssp), __rcu); \
> + __release_shared_ctx_lock(RCU); \
> + __v; \
> +})
Hi Marco,
The above change is something I'm not happy about. The original
implementation of the srcu_dereference_check() macro shows that it is
sufficient to either hold an SRCU reader lock or the updater lock ('c').
The addition of "__srcu_read_lock_must_hold()" will cause compilation to
fail if the caller doesn't hold an SRCU reader lock. I'm concerned that
this will either lead to adding __no_context_analysis to SRCU updater
code that uses srcu_dereference_check() or to adding misleading
__assume_ctx_lock(ssp) annotations in SRCU updater code.
Thanks,
Bart.
^ permalink raw reply
* [PATCH ath-current v2] wifi: ath12k: fix wrong TID passed when stopping AMPDU session
From: Pablo Martin-Gomez @ 2026-01-26 17:36 UTC (permalink / raw)
To: ath12k, jeff.johnson; +Cc: linux-wireless, Pablo Martin-Gomez
When handling a DELBA request, ath12k_dp_rx_ampdu_stop() calls
ath12k_peer_rx_tid_reo_update() to tear down the BA session for the
specified TID. However, it currently passes peer->rx_tid instead of the
entry corresponding to params->tid.
Since peer->rx_tid is an array, this decays to a pointer to the first
element, effectively operating on TID 0 regardless of the TID in the
DELBA request. As a result, the BA session for TID 0 is stopped while
the intended TID remains active.
This leads to incorrect BA session state and may significantly reduce
RX throughput, as traffic that should use aggregation falls back to a
BA window size of 1 on TID 0.
Fix this by passing the correct TID entry:
&peer->rx_tid[params->tid]
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Pablo Martin-Gomez <pmartin-gomez@freebox.fr>
---
drivers/net/wireless/ath/ath12k/dp_rx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index d28d8ffec0f8..f2327c82953b 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -1289,7 +1289,7 @@ int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
return 0;
}
- ret = ath12k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0, false);
+ ret = ath12k_peer_rx_tid_reo_update(ar, peer, &peer->rx_tid[params->tid], 1, 0, false);
spin_unlock_bh(&ab->base_lock);
if (ret) {
ath12k_warn(ab, "failed to update reo for rx tid %d: %d\n",
--
2.43.0
^ permalink raw reply related
* [PATCH ath-current v2] wifi: ath11k: fix wrong TID passed when stopping AMPDU session
From: Pablo Martin-Gomez @ 2026-01-26 17:40 UTC (permalink / raw)
To: ath11k, jeff.johnson; +Cc: linux-wireless, Pablo Martin-Gomez
When handling a DELBA request, ath11k_dp_rx_ampdu_stop() calls
ath11k_peer_rx_tid_reo_update() to tear down the BA session for the
specified TID. However, it currently passes peer->rx_tid instead of the
entry corresponding to params->tid.
Since peer->rx_tid is an array, this decays to a pointer to the first
element, effectively operating on TID 0 regardless of the TID in the
DELBA request. As a result, the BA session for TID 0 is stopped while
the intended TID remains active.
This leads to incorrect BA session state and may significantly reduce
RX throughput, as traffic that should use aggregation falls back to a
BA window size of 1 on TID 0.
Fix this by passing the correct TID entry:
&peer->rx_tid[params->tid]
Fixes: fe201947f8bd ("ath11k: update bawindow size in delba process")
Signed-off-by: Pablo Martin-Gomez <pmartin-gomez@freebox.fr>
---
drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index b9e976ddcbbf..8db04c38dfba 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -1132,7 +1132,7 @@ int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
return 0;
}
- ret = ath11k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0, false);
+ ret = ath11k_peer_rx_tid_reo_update(ar, peer, &peer->rx_tid[params->tid], 1, 0, false);
spin_unlock_bh(&ab->base_lock);
if (ret) {
ath11k_warn(ab, "failed to update reo for rx tid %d: %d\n",
--
2.43.0
^ permalink raw reply related
* Re: [PATCH ath-current] wifi: ath12k: fix wrong TID passed when stopping AMPDU session
From: Pablo MARTIN-GOMEZ @ 2026-01-26 17:41 UTC (permalink / raw)
To: Jeff Johnson, ath12k; +Cc: linux-wireless
In-Reply-To: <9c6369f4-c80c-4a59-a17a-7b4ed0d8a032@oss.qualcomm.com>
Hello,
On 26/01/2026 18:28, Jeff Johnson wrote:
> On 1/26/2026 3:35 AM, Pablo MARTIN-GOMEZ wrote:
>
> - ret = ath12k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0,
> false);
> + ret = ath12k_peer_rx_tid_reo_update(ar, peer,
> &peer->rx_tid[params->tid], 1, 0, false);
> FYI your e-mail client is munging your patch, adding a line break.
> And using "view source" it looks like other artifacts are being added.
> My tooling (using 'b4') cannot process your patch...
Oh, my bad. I've resent both my patches for ath11k & ath12k with git
send-email to be sure.
> Applying: wifi: ath12k: fix wrong TID passed when stopping AMPDU session
> error: git diff header lacks filename information when removing 1 leading pathname component (line 6)
>
> Suggest using https://b4.docs.kernel.org/en/latest/contributor/overview.html
>> spin_unlock_bh(&ab->base_lock);
>> if (ret) {
>> ath12k_warn(ab, "failed to update reo for rx tid %d: %d\n",
Best regards,
Pablo MG
^ permalink raw reply
* [PATCH] wifi: mt76: mt7921: fix potential deadlock in mt7921_roc_abort_sync
From: Sean Wang @ 2026-01-26 18:00 UTC (permalink / raw)
To: nbd, lorenzo
Cc: allan.wang, quan.zhou, leon.yen, linux-wireless, linux-mediatek,
Sean Wang
From: Sean Wang <sean.wang@mediatek.com>
roc_abort_sync() can deadlock with roc_work(). roc_work() holds
dev->mt76.mutex, while cancel_work_sync() waits for roc_work()
to finish. If the caller already owns the same mutex, both
sides block and no progress is possible.
This deadlock can occur during station removal when
mt76_sta_state() -> mt76_sta_remove() -> mt7921_mac_sta_remove() ->
mt7921_roc_abort_sync() invokes cancel_work_sync() while
roc_work() is still running and holding dev->mt76.mutex.
This avoids the mutex deadlock and preserves exactly-once
work ownership.
Fixes: 352d966126e6 ("wifi: mt76: mt7921: fix a potential association failure upon resuming")
Co-developed-by: Quan Zhou <quan.zhou@mediatek.com>
Signed-off-by: Quan Zhou <quan.zhou@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7921/main.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 05793a786644..ddb81ca6bda0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -371,12 +371,15 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev)
{
struct mt792x_phy *phy = &dev->phy;
+ if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
+ return;
+
timer_delete_sync(&phy->roc_timer);
- cancel_work_sync(&phy->roc_work);
- if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
- ieee80211_iterate_interfaces(mt76_hw(dev),
- IEEE80211_IFACE_ITER_RESUME_ALL,
- mt7921_roc_iter, (void *)phy);
+ cancel_work(&phy->roc_work);
+
+ ieee80211_iterate_interfaces(mt76_hw(dev),
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt7921_roc_iter, (void *)phy);
}
EXPORT_SYMBOL_GPL(mt7921_roc_abort_sync);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v5 15/36] srcu: Support Clang's context analysis
From: Marco Elver @ 2026-01-26 18:35 UTC (permalink / raw)
To: Bart Van Assche
Cc: Peter Zijlstra, Boqun Feng, Ingo Molnar, Will Deacon,
David S. Miller, Luc Van Oostenryck, Chris Li, Paul E. McKenney,
Alexander Potapenko, Arnd Bergmann, Christoph Hellwig,
Dmitry Vyukov, Eric Dumazet, Frederic Weisbecker,
Greg Kroah-Hartman, Herbert Xu, Ian Rogers, Jann Horn,
Joel Fernandes, Johannes Berg, Jonathan Corbet, Josh Triplett,
Justin Stitt, Kees Cook, Kentaro Takeda, Lukas Bulwahn,
Mark Rutland, Mathieu Desnoyers, Miguel Ojeda, Nathan Chancellor,
Neeraj Upadhyay, Nick Desaulniers, Steven Rostedt, Tetsuo Handa,
Thomas Gleixner, Thomas Graf, Uladzislau Rezki, Waiman Long,
kasan-dev, linux-crypto, linux-doc, linux-kbuild, linux-kernel,
linux-mm, linux-security-module, linux-sparse, linux-wireless,
llvm, rcu
In-Reply-To: <dd65bb7b-0dac-437a-a370-38efeb4737ba@acm.org>
On Mon, Jan 26, 2026 at 09:31AM -0800, Bart Van Assche wrote:
> On 12/19/25 7:40 AM, Marco Elver wrote:
> > +/*
> > + * No-op helper to denote that ssp must be held. Because SRCU-protected pointers
> > + * should still be marked with __rcu_guarded, and we do not want to mark them
> > + * with __guarded_by(ssp) as it would complicate annotations for writers, we
> > + * choose the following strategy: srcu_dereference_check() calls this helper
> > + * that checks that the passed ssp is held, and then fake-acquires 'RCU'.
> > + */
> > +static inline void __srcu_read_lock_must_hold(const struct srcu_struct *ssp) __must_hold_shared(ssp) { }
> > /**
> > * srcu_dereference_check - fetch SRCU-protected pointer for later dereferencing
> > @@ -223,9 +233,15 @@ static inline int srcu_read_lock_held(const struct srcu_struct *ssp)
> > * to 1. The @c argument will normally be a logical expression containing
> > * lockdep_is_held() calls.
> > */
> > -#define srcu_dereference_check(p, ssp, c) \
> > - __rcu_dereference_check((p), __UNIQUE_ID(rcu), \
> > - (c) || srcu_read_lock_held(ssp), __rcu)
> > +#define srcu_dereference_check(p, ssp, c) \
> > +({ \
> > + __srcu_read_lock_must_hold(ssp); \
> > + __acquire_shared_ctx_lock(RCU); \
> > + __auto_type __v = __rcu_dereference_check((p), __UNIQUE_ID(rcu), \
> > + (c) || srcu_read_lock_held(ssp), __rcu); \
> > + __release_shared_ctx_lock(RCU); \
> > + __v; \
> > +})
>
> Hi Marco,
>
> The above change is something I'm not happy about. The original
> implementation of the srcu_dereference_check() macro shows that it is
> sufficient to either hold an SRCU reader lock or the updater lock ('c').
> The addition of "__srcu_read_lock_must_hold()" will cause compilation to
> fail if the caller doesn't hold an SRCU reader lock. I'm concerned that
> this will either lead to adding __no_context_analysis to SRCU updater
> code that uses srcu_dereference_check() or to adding misleading
> __assume_ctx_lock(ssp) annotations in SRCU updater code.
Right, and it doesn't help 'c' is an arbitrary condition. But it's
fundamentally difficult to say "hold either this or that lock".
That being said, I don't think it's wrong to write e.g.:
spin_lock(&updater_lock);
__acquire_shared(ssp);
...
// writes happen through rcu_assign_pointer()
// reads can happen through srcu_dereference_check()
...
__release_shared(ssp);
spin_unlock(&updater_lock);
, given holding the updater lock implies reader access.
And given the analysis is opt-in (CONTEXT_ANALYSIS := y), I think
it's a manageable problem.
If you have a different idea how we can solve this, please let us know.
One final note, usage of srcu_dereference_check() is rare enough:
arch/x86/kvm/hyperv.c: irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu,
arch/x86/kvm/x86.c: kvm_free_msr_filter(srcu_dereference_check(kvm->arch.msr_filter, &kvm->srcu, 1));
arch/x86/kvm/x86.c: kfree(srcu_dereference_check(kvm->arch.pmu_event_filter, &kvm->srcu, 1));
drivers/gpio/gpiolib.c: label = srcu_dereference_check(desc->label, &desc->gdev->desc_srcu,
drivers/hv/mshv_irq.c: girq_tbl = srcu_dereference_check(partition->pt_girq_tbl,
drivers/hwtracing/stm/core.c: link = srcu_dereference_check(src->link, &stm_source_srcu, 1);
drivers/infiniband/hw/hfi1/user_sdma.c: pq = srcu_dereference_check(fd->pq, &fd->pq_srcu,
fs/quota/dquot.c: struct dquot *dquot = srcu_dereference_check(
fs/quota/dquot.c: struct dquot *dquot = srcu_dereference_check(
fs/quota/dquot.c: put[cnt] = srcu_dereference_check(dquots[cnt], &dquot_srcu,
fs/quota/dquot.c: transfer_from[cnt] = srcu_dereference_check(dquots[cnt],
include/linux/kvm_host.h: return srcu_dereference_check(kvm->memslots[as_id], &kvm->srcu,
virt/kvm/irqchip.c: irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu,
, that I think it's easy enough to annotate these places with the above
suggestions in case you're trying out global enablement.
^ permalink raw reply
* Re: [PATCH v5 15/36] srcu: Support Clang's context analysis
From: Bart Van Assche @ 2026-01-26 18:54 UTC (permalink / raw)
To: Marco Elver
Cc: Peter Zijlstra, Boqun Feng, Ingo Molnar, Will Deacon,
David S. Miller, Luc Van Oostenryck, Chris Li, Paul E. McKenney,
Alexander Potapenko, Arnd Bergmann, Christoph Hellwig,
Dmitry Vyukov, Eric Dumazet, Frederic Weisbecker,
Greg Kroah-Hartman, Herbert Xu, Ian Rogers, Jann Horn,
Joel Fernandes, Johannes Berg, Jonathan Corbet, Josh Triplett,
Justin Stitt, Kees Cook, Kentaro Takeda, Lukas Bulwahn,
Mark Rutland, Mathieu Desnoyers, Miguel Ojeda, Nathan Chancellor,
Neeraj Upadhyay, Nick Desaulniers, Steven Rostedt, Tetsuo Handa,
Thomas Gleixner, Thomas Graf, Uladzislau Rezki, Waiman Long,
kasan-dev, linux-crypto, linux-doc, linux-kbuild, linux-kernel,
linux-mm, linux-security-module, linux-sparse, linux-wireless,
llvm, rcu
In-Reply-To: <aXez9fSxdfu5-Boo@elver.google.com>
On 1/26/26 10:35 AM, Marco Elver wrote:
> That being said, I don't think it's wrong to write e.g.:
>
> spin_lock(&updater_lock);
> __acquire_shared(ssp);
> ...
> // writes happen through rcu_assign_pointer()
> // reads can happen through srcu_dereference_check()
> ...
> __release_shared(ssp);
> spin_unlock(&updater_lock);
>
> , given holding the updater lock implies reader access.
>
> And given the analysis is opt-in (CONTEXT_ANALYSIS := y), I think
> it's a manageable problem.
I'd like to make context-analysis mandatory for the entire kernel tree.
> If you have a different idea how we can solve this, please let us know.
>
> One final note, usage of srcu_dereference_check() is rare enough:
>
> arch/x86/kvm/hyperv.c: irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu,
> arch/x86/kvm/x86.c: kvm_free_msr_filter(srcu_dereference_check(kvm->arch.msr_filter, &kvm->srcu, 1));
> arch/x86/kvm/x86.c: kfree(srcu_dereference_check(kvm->arch.pmu_event_filter, &kvm->srcu, 1));
> drivers/gpio/gpiolib.c: label = srcu_dereference_check(desc->label, &desc->gdev->desc_srcu,
> drivers/hv/mshv_irq.c: girq_tbl = srcu_dereference_check(partition->pt_girq_tbl,
> drivers/hwtracing/stm/core.c: link = srcu_dereference_check(src->link, &stm_source_srcu, 1);
> drivers/infiniband/hw/hfi1/user_sdma.c: pq = srcu_dereference_check(fd->pq, &fd->pq_srcu,
> fs/quota/dquot.c: struct dquot *dquot = srcu_dereference_check(
> fs/quota/dquot.c: struct dquot *dquot = srcu_dereference_check(
> fs/quota/dquot.c: put[cnt] = srcu_dereference_check(dquots[cnt], &dquot_srcu,
> fs/quota/dquot.c: transfer_from[cnt] = srcu_dereference_check(dquots[cnt],
> include/linux/kvm_host.h: return srcu_dereference_check(kvm->memslots[as_id], &kvm->srcu,
> virt/kvm/irqchip.c: irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu,
>
> , that I think it's easy enough to annotate these places with the above
> suggestions in case you're trying out global enablement.
Has it ever been considered to add support in the clang compiler for a
variant of __must_hold() that expresses that one of two capabilities
must be held by the caller? I think that would remove the need to
annotate SRCU update-side code with __acquire_shared(ssp) and
__release_shared(ssp).
Thanks,
Bart.
^ permalink raw reply
* Re: [PATCH] wifi: iwlegacy: add missing mutex protection in il4965_store_tx_power()
From: Stanislaw Gruszka @ 2026-01-26 19:03 UTC (permalink / raw)
To: Ziyi Guo; +Cc: linux-wireless, linux-kernel
In-Reply-To: <20260125194039.1196488-1-n7l8m4@u.northwestern.edu>
On Sun, Jan 25, 2026 at 07:40:39PM +0000, Ziyi Guo wrote:
> il4965_store_tx_power() calls il_set_tx_power() without holding il->mutex.
> However, il_set_tx_power() has lockdep_assert_held(&il->mutex) indicating
> that callers must hold this lock.
>
> All other callers of il_set_tx_power() properly acquire the mutex:
> - il_bg_scan_completed() acquires mutex at common.c:1683
> - il_mac_config() acquires mutex at common.c:5006
> - il3945_commit_rxon() and il4965_commit_rxon() are called via work
> queues that hold the mutex (like il4965_bg_alive_start)
>
> Add mutex_lock()/mutex_unlock() around the il_set_tx_power() call in
> the sysfs store function to fix the missing lock protection.
>
> Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
> ---
> drivers/net/wireless/intel/iwlegacy/4965-mac.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
> index 3588dec75ebd..57fa866efd9f 100644
> --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
> +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
> @@ -4606,7 +4606,9 @@ il4965_store_tx_power(struct device *d, struct device_attribute *attr,
> if (ret)
> IL_INFO("%s is not in decimal form.\n", buf);
> else {
> + mutex_lock(&il->mutex);
> ret = il_set_tx_power(il, val, false);
> + mutex_unlock(&il->mutex);
> if (ret)
> IL_ERR("failed setting tx power (0x%08x).\n", ret);
> else
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH] wifi: iwlegacy: add missing mutex protection in il3945_store_measurement()
From: Stanislaw Gruszka @ 2026-01-26 18:58 UTC (permalink / raw)
To: Ziyi Guo; +Cc: linux-wireless, linux-kernel
In-Reply-To: <20260125193005.1090429-1-n7l8m4@u.northwestern.edu>
On Sun, Jan 25, 2026 at 07:30:05PM +0000, Ziyi Guo wrote:
> il3945_store_measurement() calls il3945_get_measurement() which internally
> calls il_send_cmd_sync() without holding il->mutex. However,
> il_send_cmd_sync() has lockdep_assert_held(&il->mutex) indicating that
> callers must hold this lock.
>
> Other sysfs store functions in the same file properly acquire the mutex:
> - il3945_store_flags() acquires mutex at 3945-mac.c:3110
> - il3945_store_filter_flags() acquires mutex at 3945-mac.c:3144
>
> Add mutex_lock()/mutex_unlock() around the il3945_get_measurement() call
> in the sysfs store function to fix the missing lock protection.
>
> Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
> ---
> drivers/net/wireless/intel/iwlegacy/3945-mac.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
> index 104748fcdc33..54991f31c52c 100644
> --- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
> +++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
> @@ -3224,7 +3224,9 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr,
>
> D_INFO("Invoking measurement of type %d on " "channel %d (for '%s')\n",
> type, params.channel, buf);
> + mutex_lock(&il->mutex);
> il3945_get_measurement(il, ¶ms, type);
> + mutex_unlock(&il->mutex);
>
> return count;
> }
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH v5 15/36] srcu: Support Clang's context analysis
From: Peter Zijlstra @ 2026-01-26 21:35 UTC (permalink / raw)
To: Bart Van Assche
Cc: Marco Elver, Boqun Feng, Ingo Molnar, Will Deacon,
David S. Miller, Luc Van Oostenryck, Chris Li, Paul E. McKenney,
Alexander Potapenko, Arnd Bergmann, Christoph Hellwig,
Dmitry Vyukov, Eric Dumazet, Frederic Weisbecker,
Greg Kroah-Hartman, Herbert Xu, Ian Rogers, Jann Horn,
Joel Fernandes, Johannes Berg, Jonathan Corbet, Josh Triplett,
Justin Stitt, Kees Cook, Kentaro Takeda, Lukas Bulwahn,
Mark Rutland, Mathieu Desnoyers, Miguel Ojeda, Nathan Chancellor,
Neeraj Upadhyay, Nick Desaulniers, Steven Rostedt, Tetsuo Handa,
Thomas Gleixner, Thomas Graf, Uladzislau Rezki, Waiman Long,
kasan-dev, linux-crypto, linux-doc, linux-kbuild, linux-kernel,
linux-mm, linux-security-module, linux-sparse, linux-wireless,
llvm, rcu
In-Reply-To: <8c1bbab4-4615-4518-b773-a006d1402b8b@acm.org>
On Mon, Jan 26, 2026 at 10:54:56AM -0800, Bart Van Assche wrote:
> Has it ever been considered to add support in the clang compiler for a
> variant of __must_hold() that expresses that one of two capabilities
> must be held by the caller? I think that would remove the need to
> annotate SRCU update-side code with __acquire_shared(ssp) and
> __release_shared(ssp).
Right, I think I've asked for logical operators like that. Although I
think it was in the __guarded_by() clause rather than the __must_hold().
Both || and && would be nice to have ;-)
Specifically, I think I asked for something like:
cpumask_t cpus_allowed __guarded_by(pi_lock && rq->__lock)
__guarded_shared_by(pi_lock || rq->__lock);
I think Marco's suggestion was to use 'fake' locks to mimic those
semantics.
^ permalink raw reply
* Re: [PATCH] Revert "wifi: iwlwifi: trans: remove STATUS_SUSPENDED"
From: Chris Bainbridge @ 2026-01-26 22:04 UTC (permalink / raw)
To: Korenblit, Miriam Rachel
Cc: kvalo@kernel.org, Berg, Johannes, benjamin@sipsolutions.net,
gustavoars@kernel.org, linux-intel-wifi@intel.com,
linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org
In-Reply-To: <DM3PPF63A6024A907097A88AEB32669C1E5A393A@DM3PPF63A6024A9.namprd11.prod.outlook.com>
On Mon, 26 Jan 2026 at 13:45, Korenblit, Miriam Rachel
<miriam.rachel.korenblit@intel.com> wrote:
>
>
>
> > -----Original Message-----
> > From: Chris Bainbridge <chris.bainbridge@gmail.com>
> > Sent: Monday, January 26, 2026 10:42 AM
> > To: Korenblit, Miriam Rachel <miriam.rachel.korenblit@intel.com>
> > Cc: kvalo@kernel.org; Berg, Johannes <johannes.berg@intel.com>;
> > benjamin@sipsolutions.net; gustavoars@kernel.org; linux-intel-wifi@intel.com;
> > linux-wireless@vger.kernel.org; netdev@vger.kernel.org; linux-
> > kernel@vger.kernel.org; stable@vger.kernel.org
> > Subject: Re: [PATCH] Revert "wifi: iwlwifi: trans: remove STATUS_SUSPENDED"
> >
> > On Mon, Jan 26, 2026 at 07:15:54AM +0000, Korenblit, Miriam Rachel wrote:
> > >
> > > Hi Chris, could you please provide the full log?
> > >
> > > Miri
> >
> > Sure, for 6.18.0 see https://lore.kernel.org/linux-
> > wireless/aTDoDiD55qlUZ0pn@debian.local/
> >
> >
> Thanks!
>
> could you please test if the attached patch eliminates the panic?
Yes, that seems to work fine.
Reported-and-tested-by: Chris Bainbridge <chris.bainbridge@gmail.com>
^ permalink raw reply
* Re: [PATCH wireless-next v2 1/2] wifi: mac80211: Add eMLSR/eMLMR action frame parsing support
From: Lorenzo Bianconi @ 2026-01-26 22:41 UTC (permalink / raw)
To: Johannes Berg
Cc: Ryder Lee, Sean Wang, Matthias Brugger,
AngeloGioacchino Del Regno, linux-wireless, Felix Fietkau,
Shayne Chen, Christian Marangi, linux-mediatek, linux-arm-kernel
In-Reply-To: <01e62344994a34daae0666b3873aa98e72fb5850.camel@sipsolutions.net>
[-- Attachment #1: Type: text/plain, Size: 7895 bytes --]
> On Sun, 2026-01-25 at 11:51 +0100, Lorenzo Bianconi wrote:
> >
> > +static inline u8 ieee80211_get_emlsr_pad_delay_update(u8 param)
> > +{
> > + u8 pad_delay = FIELD_GET(IEEE80211_EML_EMLSR_PAD_DELAY, param);
>
> I generally prefer the typed versions and mac80211 (mostly?) uses those,
> i.e. u8_get_bits() and friends, since they also cover endian conversions
> where needed. Is there any reason you use FIELD_* versions here?
ack, I will fix it in v3.
>
> > + if (pad_delay > IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_256US)
> > + pad_delay = 0;
>
> Seems that should use a constant, rather than =0?
>
> Also, is that really the right thing to do (also below) to just silently
> cap it? Maybe that should be up to the caller? In some(/most/all)? cases
> we should probably even just _reject_ frames that carry an invalid
> value, which you can't do with this helper?
I guess we can just move this code in the caller and reject the frame if the
values are not valid. I will fix it in v3.
>
> > +static inline u32 ieee80211_get_emlsr_trans_delay_update(u8 param)
> > +{
> > + u16 trans_delay = FIELD_GET(IEEE80211_EML_EMLSR_TRANS_DELAY, param);
> > +
> > + if (trans_delay > IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_256US)
> > + trans_delay = 0;
> > +
> > + return trans_delay;
>
> why does that use _three_ different types? Wouldn't u8 be sufficient?
>
> > --- a/include/net/mac80211.h
> > +++ b/include/net/mac80211.h
> > @@ -1902,6 +1902,21 @@ enum ieee80211_offload_flags {
> > IEEE80211_OFFLOAD_DECAP_ENABLED = BIT(2),
> > };
> >
> > +struct ieee80211_eml_params {
> > + u8 control;
> > + u16 link_bitmap;
> > + union {
> > + struct {
> > + u16 emlsr_pad_delay;
> > + u16 emlsr_trans_delay;
> > + };
> > + struct {
> > + u8 mcs_map_count;
> > + u8 mcs_map_bw[9];
> > + };
> > + };
> > +};
>
> Maybe add kernel-doc? Also not sure the union really is worth it? It's a
> tiny thing. Especially since you don't even label it - maybe if the
> parts were labled emlsr and emlmr, and then you had emlsr.pad_delay?
>
> (I'd label them anyway, of course, even if not a union.)
ack, I will add kernel-doc in v3.
>
> Also now the emlsr pad/trans delay are duplicated in the station info,
> is that worth doing? You have to and do track them there too, anyway, as
> we discussed on IRC, could just have the driver use them from there?
I agree, I guess we can drop emlsr_pad_delay and emlsr_trans_delay in
ieee80211_eml_params struct and just rely on sta values. I will fix it in v3.
>
> Per spec I'm also not sure what the MCS map should be when it's not
> included in the frame?
IIUC the mcs map value are supposed to be in Operation mode notification frame
just for eMLMR. I think the driver should check if the bit is set in
ieee80211_eml_params control field to verify if mcs_map_bw values are valid.
>
> > + * @set_eml_op_mode: Configure eMLSR/eMLMR operation mode in the underlay
> > + * driver according to the parameter received in the EML Operating mode
> > + * notification frame.
>
> Maybe describe the link_id here, or move it to the params and describe
> it in kernel-doc there?
ack, I will fix it in v3.
>
> > +static inline int drv_set_eml_op_mode(struct ieee80211_sub_if_data *sdata,
> > + struct ieee80211_sta *sta,
> > + unsigned int link_id,
> > + struct ieee80211_eml_params *eml_params)
> > +{
> > + struct ieee80211_local *local = sdata->local;
> > + int ret = 0;
>
> Shouldn't that be -EOPNOTSUPP?
ack, I will fix it in v3.
>
> > +static void
> > +ieee80211_send_eml_op_mode_notif(struct ieee80211_sub_if_data *sdata,
> > + struct ieee80211_mgmt *req, u8 act_len)
> > +{
> > + int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.eml_omn);
> > + struct ieee80211_local *local = sdata->local;
> > + struct ieee80211_mgmt *mgmt;
> > + struct sk_buff *skb;
> > +
> > + skb = dev_alloc_skb(local->tx_headroom + hdr_len + act_len);
> > + if (!skb)
> > + return;
> > +
> > + skb_reserve(skb, local->tx_headroom);
> > + mgmt = skb_put_zero(skb, hdr_len);
> > + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
> > + IEEE80211_STYPE_ACTION);
> > + memcpy(mgmt->da, req->sa, ETH_ALEN);
> > + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
> > + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
> > +
> > + mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
> > + memcpy(&mgmt->u.action.u.eml_omn, &req->u.action.u.eml_omn, act_len);
> > + mgmt->u.action.u.eml_omn.control &=
> > + ~(IEEE80211_EML_CTRL_EMLSR_PARAM_UPDATE |
> > + IEEE80211_EML_CTRL_INDEV_COEX_ACT);
> > + ieee80211_tx_skb(sdata, skb);
>
> It seems to me that it'd be better to not copy the request, but rather
> build the response. It's not _that_ much data, and from the spec it
> seems to me that e.g. the MCS map should be included in the response,
> but you do that now, I think?
ack for avoiding memcpy().
Reading the standard, it is not clear to me if mcs map values are supposed to be
added in the Notification frame sent by the AP. What do you think?
>
> > +void ieee80211_rx_eml_op_mode_notif(struct ieee80211_sub_if_data *sdata,
> > + struct sk_buff *skb)
> > +{
> > + int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.eml_omn);
> > + enum nl80211_iftype type = ieee80211_vif_type_p2p(&sdata->vif);
> > + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
> > + const struct wiphy_iftype_ext_capab *ift_ext_capa;
> > + struct ieee80211_mgmt *mgmt = (void *)skb->data;
> > + struct ieee80211_local *local = sdata->local;
> > + u8 control = mgmt->u.action.u.eml_omn.control;
> > + u8 *ptr = mgmt->u.action.u.eml_omn.variable;
> > + struct ieee80211_eml_params eml_params = {};
> > + struct sta_info *sta;
> > + u8 act_len = 3; /* action_code + dialog_token + control */
> > +
> > + if (!ieee80211_vif_is_mld(&sdata->vif))
> > + return;
> > +
> > + /* eMLSR and eMLMR can't be enabled at the same time */
> > + if ((control & IEEE80211_EML_CTRL_EMLSR_MODE) &&
> > + (control & IEEE80211_EML_CTRL_EMLMR_MODE))
> > + return;
> > +
> > + if ((control & IEEE80211_EML_CTRL_EMLMR_MODE) &&
> > + (control & IEEE80211_EML_CTRL_EMLSR_PARAM_UPDATE))
> > + return;
> > +
> > + ift_ext_capa = cfg80211_get_iftype_ext_capa(local->hw.wiphy, type);
> > + if (!ift_ext_capa)
> > + return;
> > +
> > + if (!status->link_valid)
> > + return;
> > +
> > + sta = sta_info_get_bss(sdata, mgmt->sa);
> > + if (!sta)
> > + return;
> > +
> > + if (control & IEEE80211_EML_CTRL_EMLSR_MODE) {
> > + if (!(ift_ext_capa->eml_capabilities &
> > + IEEE80211_EML_CAP_EMLSR_SUPP))
> > + return;
> > +
> > + if (control & IEEE80211_EML_CTRL_EMLSR_PARAM_UPDATE) {
> > + u16 eml_cap = sta->sta.eml_cap;
> > + u8 pad_delay, trans_delay;
> > +
> > + /* Update sta padding and transition delay */
> > + pad_delay =
> > + ieee80211_get_emlsr_pad_delay_update(ptr[3]);
> > + trans_delay =
> > + ieee80211_get_emlsr_pad_delay_update(ptr[3]);
>
> It seems to me you're missing a bunch of input validation?
ack, I will fix it in v3.
>
> > +
> > + eml_cap &= ~(IEEE80211_EML_CAP_EMLSR_PADDING_DELAY |
> > + IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY);
> > + eml_cap |= FIELD_PREP(IEEE80211_EML_EMLSR_PAD_DELAY,
> > + pad_delay) |
> > + FIELD_PREP(IEEE80211_EML_EMLSR_TRANS_DELAY,
> > + trans_delay);
> > + sta->sta.eml_cap = eml_cap;
>
> Same comment about typed bitfield accessors, and u8_replace_bits() would
> even shorten that quite a bit.
ack, I will fix it in v3.
>
> > + if (skb->len < hdr_len + act_len)
> > + return;
>
> bit late that :)
ack, I will fix it in v3.
Regards,
Lorenzo
>
> johannes
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v5 15/36] srcu: Support Clang's context analysis
From: Marco Elver @ 2026-01-26 23:46 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Bart Van Assche, Boqun Feng, Ingo Molnar, Will Deacon,
David S. Miller, Luc Van Oostenryck, Chris Li, Paul E. McKenney,
Alexander Potapenko, Arnd Bergmann, Christoph Hellwig,
Dmitry Vyukov, Eric Dumazet, Frederic Weisbecker,
Greg Kroah-Hartman, Herbert Xu, Ian Rogers, Jann Horn,
Joel Fernandes, Johannes Berg, Jonathan Corbet, Josh Triplett,
Justin Stitt, Kees Cook, Kentaro Takeda, Lukas Bulwahn,
Mark Rutland, Mathieu Desnoyers, Miguel Ojeda, Nathan Chancellor,
Neeraj Upadhyay, Nick Desaulniers, Steven Rostedt, Tetsuo Handa,
Thomas Gleixner, Thomas Graf, Uladzislau Rezki, Waiman Long,
kasan-dev, linux-crypto, linux-doc, linux-kbuild, linux-kernel,
linux-mm, linux-security-module, linux-sparse, linux-wireless,
llvm, rcu
In-Reply-To: <20260126213556.GQ171111@noisy.programming.kicks-ass.net>
On Mon, 26 Jan 2026 at 22:36, Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Mon, Jan 26, 2026 at 10:54:56AM -0800, Bart Van Assche wrote:
>
> > Has it ever been considered to add support in the clang compiler for a
> > variant of __must_hold() that expresses that one of two capabilities
> > must be held by the caller? I think that would remove the need to
> > annotate SRCU update-side code with __acquire_shared(ssp) and
> > __release_shared(ssp).
>
> Right, I think I've asked for logical operators like that. Although I
> think it was in the __guarded_by() clause rather than the __must_hold().
> Both || and && would be nice to have ;-)
Some attributes take multiple arguments (__must_hold does), though
__guarded_by doesn't. Yet, && can still be had with adding it multiple
times e.g. '__guarded_by(pi_lock) __guarded_by(rq->__lock)'.
Only thing that doesn't exist is ||. I think the syntax you ask for
won't fly, but I can add it to the backlog to investigate an _any
variant of these attributes. Don't hold your breath though, given the
time it takes to land all that in a released Clang version.
> Specifically, I think I asked for something like:
>
> cpumask_t cpus_allowed __guarded_by(pi_lock && rq->__lock)
> __guarded_shared_by(pi_lock || rq->__lock);
>
>
> I think Marco's suggestion was to use 'fake' locks to mimic those
> semantics.
^ permalink raw reply
* Re: [PATCH] wifi: mt76: connac: fix txpower_cur not being updated
From: Nick @ 2026-01-27 1:59 UTC (permalink / raw)
To: Lucid Duck; +Cc: linux-wireless, Felix Fietkau, Lorenzo Bianconi, Ryder Lee
In-Reply-To: <20260125222235.36565-1-lucid_duck@justthetip.ca>
> The mt76_connac_mcu_set_rate_txpower() function sends TX power settings
> to the firmware but never updates phy->txpower_cur. This causes
> mt76_get_txpower() to return stale or incorrect values (typically
> showing 3 dBm regardless of actual transmit power) when userspace
> queries TX power via nl80211.
>
> This affects MT7921 and other connac-based devices. Users observe:
> $ iw dev wlan0 info
> ...
> txpower 3.00 dBm
>
> The firmware receives and applies the correct power level, but the
> reported value is wrong because txpower_cur is never set.
>
> Fix by updating phy->txpower_cur after successfully configuring TX
> power, matching the behavior of other mt76 drivers like mt7915.
>
> Signed-off-by: Lucid Duck <lucid_duck@justthetip.ca>
> ---
> drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> index 045771228..7cd357419 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> @@ -2251,7 +2251,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
>
> int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
> {
> - int err;
> + int err, tx_power;
>
> if (phy->cap.has_2ghz) {
> err = mt76_connac_mcu_rate_txpower_band(phy,
> @@ -2272,6 +2272,12 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
> return err;
> }
>
> + /* Update txpower_cur for accurate reporting via nl80211 */
> + tx_power = 2 * phy->hw->conf.power_level;
> + if (!tx_power)
> + tx_power = 127;
> + phy->txpower_cur = tx_power;
> +
> return 0;
> }
> EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower);
> --
> 2.52.0
>
Tested on kernel 6.18.7
$ iw dev
phy#0
Unnamed/non-netdev interface
wdev 0x2
addr 76:19:f8:16:a4:48
type P2P-device
txpower 67.00 dBm
Interface wlan0
ifindex 3
wdev 0x1
addr 74:19:f8:16:a4:48
type managed
txpower 67.00 dBm
...
Device tested is a USB WiFi adapter using the mt7921u driver. The
txpower output is not correct.
This is a problem that really needs to be fixed. My hope is that those
that know how to help, do so.
^ permalink raw reply
* Re: [PATCH v2 1/2] wifi: ath12k: Remove frequency range filtering for single-phy devices
From: Baochen Qiang @ 2026-01-27 3:22 UTC (permalink / raw)
To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
In-Reply-To: <20260126095244.113301-2-bjsaikiran@gmail.com>
On 1/26/2026 5:52 PM, Saikiran wrote:
> The frequency range filtering added in commit acc152f9be20 was designed
> for split-phy devices where multiple radios with overlapping frequency
> ranges within the same band are combined into a single wiphy. Each radio
> in such setups handles only a subset of channels within a band (e.g., two
> 5GHz radios covering 5GHz-low and 5GHz-high separately).
>
> However, this filtering breaks single-phy devices like WCN7850 that use
> a single radio to handle both 2.4GHz and 5GHz bands. On these devices,
To be accurate, WCN7850 still gets two phys in hardware, it is just in host that we treat
it as single.
> the freq_range is set to cover the entire supported spectrum, but the
exactly
> filtering logic incorrectly restricts channels, causing 5GHz to become
> completely unusable.
how? what are the actual values of freq_range when you hit the issue and how are they
calculated?
>
> The issue manifests as:
> - All 5GHz channels filtered out during channel list updates
> - No 5GHz SSIDs visible in scans
> - Only 2.4GHz networks functional
>
> Remove the frequency range filtering entirely and rely on the firmware
> to handle frequency restrictions based on actual hardware capabilities.
> This approach works correctly for both split-phy and single-phy devices,
> as the firmware has complete knowledge of what the hardware supports.
>
> Fixes: acc152f9be20 ("wifi: ath12k: combine channel list for split-phy devices in single-wiphy")
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> ---
> drivers/net/wireless/ath/ath12k/reg.c | 13 -------------
> 1 file changed, 13 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
> index 7898f6981e5a..48c362a86524 100644
> --- a/drivers/net/wireless/ath/ath12k/reg.c
> +++ b/drivers/net/wireless/ath/ath12k/reg.c
> @@ -153,12 +153,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
> if (bands[band]->channels[i].flags &
> IEEE80211_CHAN_DISABLED)
> continue;
> - /* Skip Channels that are not in current radio's range */
> - if (bands[band]->channels[i].center_freq <
> - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
> - bands[band]->channels[i].center_freq >
> - KHZ_TO_MHZ(ar->freq_range.end_freq))
> - continue;
>
> num_channels++;
> }
> @@ -190,13 +184,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
> if (channel->flags & IEEE80211_CHAN_DISABLED)
> continue;
>
> - /* Skip Channels that are not in current radio's range */
> - if (bands[band]->channels[i].center_freq <
> - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
> - bands[band]->channels[i].center_freq >
> - KHZ_TO_MHZ(ar->freq_range.end_freq))
> - continue;
> -
> /* TODO: Set to true/false based on some condition? */
> ch->allow_ht = true;
> ch->allow_vht = true;
^ permalink raw reply
* Re: [PATCH v2 2/2] wifi: ath12k: Fix firmware stats leak when pdev list is empty
From: Baochen Qiang @ 2026-01-27 3:27 UTC (permalink / raw)
To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
In-Reply-To: <20260126095244.113301-3-bjsaikiran@gmail.com>
On 1/26/2026 5:52 PM, Saikiran wrote:
> The commits bd6ec8111e65 and 2977567b244f changed firmware stats handling
> to be caller-driven, requiring explicit ath12k_fw_stats_reset() calls
> after using ath12k_mac_get_fw_stats().
>
> In ath12k_mac_op_get_txpower(), when ath12k_mac_get_fw_stats() succeeds
> but the pdev stats list is empty, the function exits without calling
> ath12k_fw_stats_reset(). Even though the pdev list is empty, the firmware
> may have populated other stats lists (vdevs, beacons, etc.) in the
'may' is not enough, we need to be 100% sure whether other stats are populated. This is
critical for us to find the root cause.
> ar->fw_stats structure.
>
> Without resetting the stats buffer, this data accumulates across multiple
> calls, eventually causing the stats buffer to overflow and leading to
> firmware communication failures (error -71/EPROTO) during subsequent
> operations.
>
> The issue manifests during 5GHz scanning which triggers multiple TX power
> queries. Symptoms include:
> - "failed to pull fw stats: -71" errors in dmesg
still, can you please check the logs to see at which exact place is this printed?
> - 5GHz networks not detected despite hardware support
> - 2.4GHz networks work normally
>
> Fix by calling ath12k_fw_stats_reset() when the pdev list is empty,
> ensuring the stats buffer is properly cleaned up even when only partial
> stats data is received from firmware.
>
> Fixes: bd6ec8111e65 ("wifi: ath12k: Make firmware stats reset caller-driven")
> Link: https://bugs.launchpad.net/ubuntu-concept/+bug/2138308
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> ---
> drivers/net/wireless/ath/ath12k/mac.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index e0e49f782bf8..6e35c3ee9864 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -5169,6 +5169,7 @@ static int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
> struct ath12k_fw_stats_pdev, list);
> if (!pdev) {
> spin_unlock_bh(&ar->data_lock);
> + ath12k_fw_stats_reset(ar);
> goto err_fallback;
> }
>
^ permalink raw reply
* [PATCH ath-next] wifi: ath12k: clear stale link mapping of ahvif->links_map
From: Aaradhana Sahu @ 2026-01-27 3:34 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, Aaradhana Sahu
When an arvif is initialized in non-AP STA mode but MLO connection
preparation fails before the arvif is created
(arvif->is_created remains false), the error path attempts to delete all
links. However, link deletion only executes when arvif->is_created is true.
As a result, ahvif retains a stale entry of arvif that is initialized but
not created.
When a new arvif is initialized with the same link id, this stale mapping
triggers the following WARN_ON.
WARNING: drivers/net/wireless/ath/ath12k/mac.c:4271 at ath12k_mac_op_change_vif_links+0x140/0x180 [ath12k], CPU#3: wpa_supplicant/275
Call trace:
ath12k_mac_op_change_vif_links+0x140/0x180 [ath12k] (P)
drv_change_vif_links+0xbc/0x1a4 [mac80211]
ieee80211_vif_update_links+0x54c/0x6a0 [mac80211]
ieee80211_vif_set_links+0x40/0x70 [mac80211]
ieee80211_prep_connection+0x84/0x450 [mac80211]
ieee80211_mgd_auth+0x200/0x480 [mac80211]
ieee80211_auth+0x14/0x20 [mac80211]
cfg80211_mlme_auth+0x90/0xf0 [cfg80211]
nl80211_authenticate+0x32c/0x380 [cfg80211]
genl_family_rcv_msg_doit+0xc8/0x134
Fix this issue by unassigning the link vif and clearing ahvif->links_map
if arvif is only initialized but not created.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1
Fixes: 81e4be30544e ("wifi: ath12k: handle link removal in change_vif_links()")
Signed-off-by: Aaradhana Sahu <aaradhana.sahu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index cdb72439dcf4..9a926f5b7e8a 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -4281,8 +4281,10 @@ ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw,
if (WARN_ON(!arvif))
return -EINVAL;
- if (!arvif->is_created)
+ if (!arvif->is_created) {
+ ath12k_mac_unassign_link_vif(arvif);
continue;
+ }
if (WARN_ON(!arvif->ar))
return -EINVAL;
base-commit: 13f9e5344a517048f3d8c61e49a9a72f97410de3
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v2 1/2] wifi: ath12k: Remove frequency range filtering for single-phy devices
From: Saikiran B @ 2026-01-27 4:04 UTC (permalink / raw)
To: Baochen Qiang; +Cc: ath12k, linux-wireless, kvalo
In-Reply-To: <776ae681-9db7-4051-abe1-07530f87d485@oss.qualcomm.com>
Hi Baochen,
I checked the logs again.
The issue seems to be coming from how
[ath12k_regd_update()](drivers/net/wireless/ath/ath12k/reg.c) handles
frequency range updates for this device. WCN7850 is a single-phy
device (single [ar](drivers/net/wireless/ath/ath12k/mac.c) that
supports both 2.4GHz and 5GHz/6GHz.
In ath12k_regd_update():
1. It updates the range for 2GHz capabilities (sets range to ~2.4GHz).
2. It then attempts to update for 5GHz capabilities.
3. Because `ar->supports_6ghz` is true, it uses the 6GHz path logic.
4. However, `ab->reg_freq_6ghz` appears to be uninitialized/invalid at
this stage (possibly due to regulatory init timing or country code
issues, On Lenovo Yoga Slim 7x, SMBIOS does not seem to provide a
valid country code. The driver attempts to set an invalid country code
which the firmware rejects. This inturn triggers this issue. Fixing
SMBIOS parsing/defaults is a separate, complex issue that varies by
vendor.), causing the 5GHz range update to be skipped or invalid.
[ 11.699027] ath12k_pci 0004:01:00.0: Failed to set the requested
Country regulatory setting
[ 31.111995] ath12k_pci 0004:01:00.0: Failed to set the requested
Country regulatory setting
As a result, `ar->freq_range` remains effectively set for only the 2.4GHz band.
When ath12k_reg_update_chan_list() runs:
It compares 5GHz channels (e.g., 5180 MHz) against a
[freq_range](drivers/net/wireless/ath/ath12k/reg.c) that only covers
2.4GHz.
Result: `center_freq > end_freq` is TRUE -> Channel is filtered out.
The filtering logic added in acc152f9be20 works for split-phy topology
where each host ar covers a specific range. For WCN7850, where a
single host ar covers disjoint bands (2.4G + 5G), [freq_range] but
[freq_range](drivers/net/wireless/ath/ath12k/reg.c) (start/end) cannot
represent multiple disjoint bands at the same time.
Removing this driver-level filter allows the firmware (which knows the
true capabilities) to handle the channel list correctly.
Thanks & Regards,
Saikiran
On Tue, Jan 27, 2026 at 8:52 AM Baochen Qiang
<baochen.qiang@oss.qualcomm.com> wrote:
>
>
>
> On 1/26/2026 5:52 PM, Saikiran wrote:
> > The frequency range filtering added in commit acc152f9be20 was designed
> > for split-phy devices where multiple radios with overlapping frequency
> > ranges within the same band are combined into a single wiphy. Each radio
> > in such setups handles only a subset of channels within a band (e.g., two
> > 5GHz radios covering 5GHz-low and 5GHz-high separately).
> >
> > However, this filtering breaks single-phy devices like WCN7850 that use
> > a single radio to handle both 2.4GHz and 5GHz bands. On these devices,
>
> To be accurate, WCN7850 still gets two phys in hardware, it is just in host that we treat
> it as single.
>
> > the freq_range is set to cover the entire supported spectrum, but the
>
> exactly
>
> > filtering logic incorrectly restricts channels, causing 5GHz to become
> > completely unusable.
>
> how? what are the actual values of freq_range when you hit the issue and how are they
> calculated?
>
> >
> > The issue manifests as:
> > - All 5GHz channels filtered out during channel list updates
> > - No 5GHz SSIDs visible in scans
> > - Only 2.4GHz networks functional
> >
> > Remove the frequency range filtering entirely and rely on the firmware
> > to handle frequency restrictions based on actual hardware capabilities.
> > This approach works correctly for both split-phy and single-phy devices,
> > as the firmware has complete knowledge of what the hardware supports.
> >
> > Fixes: acc152f9be20 ("wifi: ath12k: combine channel list for split-phy devices in single-wiphy")
> > Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
> > Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> > ---
> > drivers/net/wireless/ath/ath12k/reg.c | 13 -------------
> > 1 file changed, 13 deletions(-)
> >
> > diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
> > index 7898f6981e5a..48c362a86524 100644
> > --- a/drivers/net/wireless/ath/ath12k/reg.c
> > +++ b/drivers/net/wireless/ath/ath12k/reg.c
> > @@ -153,12 +153,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
> > if (bands[band]->channels[i].flags &
> > IEEE80211_CHAN_DISABLED)
> > continue;
> > - /* Skip Channels that are not in current radio's range */
> > - if (bands[band]->channels[i].center_freq <
> > - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
> > - bands[band]->channels[i].center_freq >
> > - KHZ_TO_MHZ(ar->freq_range.end_freq))
> > - continue;
> >
> > num_channels++;
> > }
> > @@ -190,13 +184,6 @@ int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
> > if (channel->flags & IEEE80211_CHAN_DISABLED)
> > continue;
> >
> > - /* Skip Channels that are not in current radio's range */
> > - if (bands[band]->channels[i].center_freq <
> > - KHZ_TO_MHZ(ar->freq_range.start_freq) ||
> > - bands[band]->channels[i].center_freq >
> > - KHZ_TO_MHZ(ar->freq_range.end_freq))
> > - continue;
> > -
> > /* TODO: Set to true/false based on some condition? */
> > ch->allow_ht = true;
> > ch->allow_vht = true;
>
^ permalink raw reply
* Re: [PATCH v2 2/2] wifi: ath12k: Fix firmware stats leak when pdev list is empty
From: Saikiran B @ 2026-01-27 4:17 UTC (permalink / raw)
To: Baochen Qiang; +Cc: ath12k, linux-wireless, kvalo
In-Reply-To: <9ca7ceac-2799-4993-844c-8427508c7d9b@oss.qualcomm.com>
Hi Baochen,
Regarding your questions:
"Are other stats populated?"
Yes. When ath12k_mac_get_fw_stats() returns success (0), it means the
firmware response was received and valid WMI events were processed.
The firmware response to WMI_REQUEST_PDEV_STAT typically includes
multiple stats TLVs (vdev stats, beacon stats, etc.). Even if the
"pdev stats" list ends up empty (e.g., due to specific filtering or
availability), the firmware should have populated other lists (like
vdevs or beacons) in the ar->fw_stats structure. If we don't reset,
these valid entries leak and accumulate.
"Where exactly is -71 (EPROTO) printed?"
The log "failed to pull fw stats: -71" is printed in
ath12k_update_stats_event() (wmi.c line 8500 in my tree). This error
code (-EPROTO) propagates from ath12k_wmi_tlv_fw_stats_data_parse(),
where it is returned when buffer validation checks fail (e.g., if (len
< sizeof(*src))). This failure suggests that the accumulated state or
memory corruption from the leak eventually causes the parser to fail
on subsequent events.
So, fixing the leak is necessary for correctness regardless of the
specific side-effect error code.
Thanks & Regards,
Saikiran
On Tue, Jan 27, 2026 at 8:57 AM Baochen Qiang
<baochen.qiang@oss.qualcomm.com> wrote:
>
>
>
> On 1/26/2026 5:52 PM, Saikiran wrote:
> > The commits bd6ec8111e65 and 2977567b244f changed firmware stats handling
> > to be caller-driven, requiring explicit ath12k_fw_stats_reset() calls
> > after using ath12k_mac_get_fw_stats().
> >
> > In ath12k_mac_op_get_txpower(), when ath12k_mac_get_fw_stats() succeeds
> > but the pdev stats list is empty, the function exits without calling
> > ath12k_fw_stats_reset(). Even though the pdev list is empty, the firmware
> > may have populated other stats lists (vdevs, beacons, etc.) in the
>
> 'may' is not enough, we need to be 100% sure whether other stats are populated. This is
> critical for us to find the root cause.
>
> > ar->fw_stats structure.
> >
> > Without resetting the stats buffer, this data accumulates across multiple
> > calls, eventually causing the stats buffer to overflow and leading to
> > firmware communication failures (error -71/EPROTO) during subsequent
> > operations.
> >
> > The issue manifests during 5GHz scanning which triggers multiple TX power
> > queries. Symptoms include:
> > - "failed to pull fw stats: -71" errors in dmesg
>
> still, can you please check the logs to see at which exact place is this printed?
>
> > - 5GHz networks not detected despite hardware support
> > - 2.4GHz networks work normally
> >
> > Fix by calling ath12k_fw_stats_reset() when the pdev list is empty,
> > ensuring the stats buffer is properly cleaned up even when only partial
> > stats data is received from firmware.
> >
> > Fixes: bd6ec8111e65 ("wifi: ath12k: Make firmware stats reset caller-driven")
> > Link: https://bugs.launchpad.net/ubuntu-concept/+bug/2138308
> > Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302 (Lenovo Yoga Slim 7x)
> > Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> > ---
> > drivers/net/wireless/ath/ath12k/mac.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> > index e0e49f782bf8..6e35c3ee9864 100644
> > --- a/drivers/net/wireless/ath/ath12k/mac.c
> > +++ b/drivers/net/wireless/ath/ath12k/mac.c
> > @@ -5169,6 +5169,7 @@ static int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
> > struct ath12k_fw_stats_pdev, list);
> > if (!pdev) {
> > spin_unlock_bh(&ar->data_lock);
> > + ath12k_fw_stats_reset(ar);
> > goto err_fallback;
> > }
> >
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox