Linux wireless drivers development
 help / color / mirror / Atom feed
* 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

* Re: [PATCH wireless-next v2 1/2] wifi: mac80211: Add eMLSR/eMLMR action frame parsing support
From: Johannes Berg @ 2026-01-26 10:59 UTC (permalink / raw)
  To: Lorenzo Bianconi, Ryder Lee, Sean Wang, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: linux-wireless, Felix Fietkau, Shayne Chen, Christian Marangi,
	linux-mediatek, linux-arm-kernel
In-Reply-To: <20260125-mac80211-emlsr-v2-1-466329d61c88@kernel.org>

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?

> +	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?

> +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.)

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?

Per spec I'm also not sure what the MCS map should be when it's not
included in the frame?

> + * @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?

> +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?

> +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?

> +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?

> +
> +			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.

> +	if (skb->len < hdr_len + act_len)
> +		return;

bit late that :)

johannes

^ permalink raw reply

* Re: [PATCH ath-next] wifi: ath12k: avoid setting 320MHZ support on non 6GHz band
From: Johannes Berg @ 2026-01-26 10:36 UTC (permalink / raw)
  To: Nicolas Escande, Pablo MARTIN-GOMEZ, ath12k; +Cc: linux-wireless
In-Reply-To: <DFYFUQNL5YRY.24VJC5QJMQFVF@gmail.com>

On Mon, 2026-01-26 at 11:11 +0100, Nicolas Escande wrote:
> > Ah, you're asking why mac80211 doesn't clear those bits ... I guess it
> > just doesn't matter. If you're not on 320 MHz I'd guess the bits are
> > never checked, so it's not really relevant at all, although then could
> > argue that you only need the first line here as well.
> 
> I you want Johannes, I can post a patch that also clears those bits in mac80211
> 

I don't think it really matters much, though I think in some older cases
we might be clearing more related bits.

johannes

^ permalink raw reply

* RE: [PATCH] wifi: rtw89: usb: fix TX flow control by tracking in-flight URBs
From: Mh_chen @ 2026-01-26 10:14 UTC (permalink / raw)
  To: Ping-Ke Shih, Lucid Duck, linux-wireless@vger.kernel.org,
	Bitterblue Smith, Isaiah
In-Reply-To: <290226f1d7144477a668f045cbd8eb56@realtek.com>

+Isaiah for Wi-Fi USB driver,

-----Original Message-----
From: Ping-Ke Shih <pkshih@realtek.com> 
Sent: Monday, January 26, 2026 11:40 AM
To: Lucid Duck <lucid_duck@justthetip.ca>; linux-wireless@vger.kernel.org; Bitterblue Smith <rtl8821cerfe2@gmail.com>; Mh_chen <mh_chen@realtek.com>
Subject: RE: [PATCH] wifi: rtw89: usb: fix TX flow control by tracking in-flight URBs

+ developers of WiFi USB adapters

Lucid Duck <lucid_duck@justthetip.ca> 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.

Then URB becomes exhausted? 

> 
> 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>

[...]

> 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

Curiously. How did you decide this value? Have you tested USB2 and USB3 devices?
How about their throughput before/after this patch?

> +
>  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 */

I feel we don't need repeatedly adding this comment. If you like it, just keep one.

> +       atomic_t tx_inflight[RTW89_TXCH_NUM];
>  };
> 
>  static inline struct rtw89_usb *rtw89_usb_priv(struct rtw89_dev 
> *rtwdev)
> --
> 2.52.0
> 


^ permalink raw reply

* Re: [PATCH ath-next] wifi: ath12k: avoid setting 320MHZ support on non 6GHz band
From: Nicolas Escande @ 2026-01-26 10:11 UTC (permalink / raw)
  To: Johannes Berg, Pablo MARTIN-GOMEZ, Nicolas Escande, ath12k; +Cc: linux-wireless
In-Reply-To: <26bfd810c1dabc9ed86d4ba68cd20f6434c1d3a2.camel@sipsolutions.net>

On Fri Jan 23, 2026 at 8:29 PM CET, Johannes Berg wrote:
> On Fri, 2026-01-23 at 20:21 +0100, Pablo MARTIN-GOMEZ wrote:
>> 
>> > > > +	} else {
>> > > > +		phy_cap[0] &= ~IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
>> > > > +		phy_cap[1] &= ~IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK;
>> > > > +		phy_cap[2] &= ~IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK;
>> > > > +		phy_cap[6] &= ~IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_320MHZ;
>> > > > +	}
>> > > If you want to clear all 320 MHz fields, you'll also have to clear
>> > > IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ and
>> > > IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ (not sure why it is not done
>> > > in mac80211)
>> > > 

If the QCA guys are interrested I can post a v2 with the additionnal bits also
cleared.

>> > This is, effectively, a firmware workaround. It doesn't belong into
>> > mac80211. All other drivers just have their capabilities managed in the
>> > driver anyway.
>> > 
>> > johannes
>> 

Yep you made me realize that. So I tracked how to fix it in the underlying
driver and posted this patch.

>> I wasn't talking about putting this patch in mac80211 (I've seen the 
>> discussion on the patch Nicolas sent on linux-wireless), I'm talking 
>> about the function `ieee80211_put_eht_cap` clearing the Beamformee SS 
>> and Sounding Dimension fields but not the Non-OFDMA UL MU-MIMO and MU 
>> Beamformer fields for each bandwidth.
>
> Ah, you're asking why mac80211 doesn't clear those bits ... I guess it
> just doesn't matter. If you're not on 320 MHz I'd guess the bits are
> never checked, so it's not really relevant at all, although then could
> argue that you only need the first line here as well.

I you want Johannes, I can post a patch that also clears those bits in mac80211
>
> johannes

Nico,

^ permalink raw reply

* Re: [PATCH v1] wifi: mt76: fix backoff fields and max_power calculation
From: Sven Eckelmann @ 2026-01-26  9:54 UTC (permalink / raw)
  To: Felix Fietkau, Ryder Lee
  Cc: linux-wireless, linux-mediatek, Allen Ye, Ryder Lee
In-Reply-To: <e92213f793f9cb9f509c26205e7ecb2be6ce77aa.1769156922.git.ryder.lee@mediatek.com>

[-- Attachment #1: Type: text/plain, Size: 14245 bytes --]

Please change your prefix from [PATCH v1] to [PATCH mt76 v1].

On Friday, 23 January 2026 10:32:34 CET Ryder Lee wrote:
> From: Allen Ye <allen.ye@mediatek.com>
> 
> The maximum power value may exist in data or backoff field.
> To reponse the correct value of txpower, mt76 should also consider
> these values in sku table.
> 
> Fixes: b05ab4be9fd7 (wifi: mt76: mt7915: add bf backoff limit table support)
> Signed-off-by: Allen Ye <allen.ye@mediatek.com>
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
> v1 - add "wifi:" prefix into subject


Please send your patches before submission through checkpatch. Tools like 
b4 [1] can help you to have a good workflow by reminding your about this
(and provide good templates for many other things)


WARNING: 'reponse' may be misspelled - perhaps 'response'?
#126: 
To reponse the correct value of txpower, mt76 should also consider
   ^^^^^^^

WARNING: Please use correct Fixes: style 'Fixes: <12+ chars of sha1> ("<title line>")' - ie: 'Fixes: b05ab4be9fd7 ("wifi: mt76: mt7915: add bf backoff limit table support")'
#129: 
Fixes: b05ab4be9fd7 (wifi: mt76: mt7915: add bf backoff limit table support)

ERROR: that open brace { should be on the previous line
#173: FILE: drivers/net/wireless/mediatek/mt76/eeprom.c:319:
+       static const u8 connac3_table[] =
+               {1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5};

ERROR: that open brace { should be on the previous line
#175: FILE: drivers/net/wireless/mediatek/mt76/eeprom.c:321:
+       static const u8 connac2_table[] =
+               {1, 2, 3, 4, 2, 3, 4, 3, 4, 4, 0, 0, 0, 0, 0};

CHECK: Macro argument reuse 'arr' - possible side-effects?
#288: FILE: drivers/net/wireless/mediatek/mt76/eeprom.c:462:
+#define __apply_array_limit(arr, type)                                         \
+       mt76_apply_array_limit(dev, (arr), ARRAY_SIZE(arr), val, target_power,  \
+                              txs_delta, &max_power, n_chains, type)

CHECK: Macro argument reuse 'arr' - possible side-effects?
#292: FILE: drivers/net/wireless/mediatek/mt76/eeprom.c:466:
+#define __apply_multi_array_limit(arr, type)                                   \
+       mt76_apply_multi_array_limit(dev, (arr)[0], ARRAY_SIZE((arr)[0]),       \
+                                    ARRAY_SIZE(arr), val, len, target_power,   \
+                                    txs_delta, &max_power, n_chains, type)

total: 2 errors, 2 warnings, 2 checks, 233 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.


>  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,50 @@ 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);
> +		s8 backoff_delta, delta = mt76_tx_power_path_delta(n_chains);

Please avoid multiple function declarations per line. "To this end, use just 
one data declaration per line (no commas for multiple data declarations)"

This also looks on the first glance like destructuring (which doesn't exist 
in C).

> +		int backoff_n_chains = 0;
> +
> +		switch (type) {
> +		case MT76_SKU_RATE:
> +			pwr[i] = min_t(s8, target_power, data[i] + nss_delta);
> +			break;
> +		case MT76_SKU_BACKOFF:
> +			backoff_n_chains = mt76_backoff_n_chains(dev, i);
> +			backoff_delta = mt76_tx_power_path_delta(backoff_n_chains);
> +			pwr[i] = min_t(s8, target_power + delta - backoff_delta,
> +				       data[i] + nss_delta);
> +			break;
> +		case MT76_SKU_BACKOFF_BF_OFFSET:
> +			backoff_n_chains = mt76_backoff_n_chains(dev, i + 1);
> +			backoff_delta = mt76_tx_power_path_delta(backoff_n_chains);
> +			pwr[i] = min_t(s8, target_power + delta - backoff_delta,
> +				       data[i] + nss_delta);
> +			break;
> +		default:
> +			return;
> +		}

Instead of calculating something different in every case, couldn't this be harmonized as

		int backoff_n_chains;
		s8 backoff_delta;
		s8 delta;

		switch (type) {
		case MT76_SKU_RATE:
			delta = 0;
			backoff_n_chains = 0;
			backoff_delta = 0;
			break;
		case MT76_SKU_BACKOFF:
			delta = mt76_tx_power_path_delta(n_chains);
			backoff_n_chains = mt76_backoff_n_chains(dev, i);
			backoff_delta = mt76_tx_power_path_delta(backoff_n_chains);
			break;
		case MT76_SKU_BACKOFF_BF_OFFSET:
			delta = mt76_tx_power_path_delta(n_chains);
			backoff_n_chains = mt76_backoff_n_chains(dev, i + 1);
			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);

or

		u8 backoff_chain_idx = i;
		int backoff_n_chains;
		s8 backoff_delta;
		s8 delta;

		switch (type) {
		case MT76_SKU_RATE:
			delta = 0;
			backoff_n_chains = 0;
			backoff_delta = 0;
			break;
		case MT76_SKU_BACKOFF:
			backoff_chain_index += 1;
			fallthrough;
		case MT76_SKU_BACKOFF_BF_OFFSET:
			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);

[...]
>  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)
>  {
>  	int i, cur;
> -	s8 max_power = -128;
> +
> +#define connac2_backoff_ru_idx	2

why this define in the middle of the function? Should this be in a header? 
Should it just be a const?

>  
>  	if (!data)
>  		return;
> @@ -337,8 +390,13 @@ 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);
> +		if (!is_mt799x(dev) && type == MT76_SKU_BACKOFF &&
> +		    i > connac2_backoff_ru_idx)
> +			type = MT76_SKU_BACKOFF_BF_OFFSET;

Can you please explain in the commit message how this format is structured. So 
why everything after the third line of the expanded multi-array limit must be 
considered a MT76_SKU_BACKOFF_BF_OFFSET? Adding some kernel-doc to each item in
enum mt76_sku_type might help too.

I have only seen one device in the wild (MT7905DAN + MT7975DN) which actually 
uses the DT for the limits
https://github.com/openwrt/openwrt/blob/17d45f677b0eb1da3c8190a2778fcdfcd9ecd234/target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts#L11
And there, it just uses the 2T1ss to the place where 1T1ss might be for beamforming.
And this field doesn't seem to make a lot of sense (beamforming with 1 antennna?)
and needs to be skipped.

So yes, I can answer it by looking at some code I've used before for converting 
some CSV [2] to DT entries:

    rates_table = {
        "paths-cck": [
            row[0:4],
        ],
        "paths-ofdm": [
            row[4:8],
        ],
        "paths-ofdm-bf": [
            [
                row[8],
                *row[8:11],
            ],  # duplicating first entry because it is needed in DTS but will not actually be used
        ],
        "paths-ru": compress_rates(
            [
                [1, *row[87:97]],  # RU26
                [1, *row[107:117]],  # RU52
                [1, *row[127:137]],  # RU106
                [1, *row[11:21]],  # BW20 (HT/VHT)
                [1, *row[30:40]],  # BW40 (HT/VHT)
                [1, *row[49:59]],  # BW80 (HT/VHT)
                [1, *row[68:78]],  # BW160 (HT/VHT)
            ]
        ),
        "paths-ru-bf": compress_rates(
            [
                [1, *row[97:107]],  # RU26
                [1, *row[117:127]],  # RU52
                [1, *row[137:147]],  # RU106
                [
                    1,
                    row[21],
                    *row[21:30],
                ],  # BW20 (HT/VHT), duplicating first entry
                [
                    1,
                    row[40],
                    *row[40:49],
                ],  # BW40 (HT/VHT), duplicating first entry
                [
                    1,
                    row[59],
                    *row[59:68],
                ],  # BW80 (HT/VHT), duplicating first entry
                [
                    1,
                    row[78],
                    *row[78:87],
                ],  # BW160 (HT/VHT), duplicating first entry
            ]
        ),
    }

But it would be good to have this written down somewhere.



> @@ -360,18 +418,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));
> @@ -408,47 +459,51 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
>  
>  	txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));
>  
> +#define __apply_array_limit(arr, type)						\
> +	mt76_apply_array_limit(dev, (arr), ARRAY_SIZE(arr), val, target_power,	\
> +			       txs_delta, &max_power, n_chains, type)
> +
> +#define __apply_multi_array_limit(arr, type)					\
> +	mt76_apply_multi_array_limit(dev, (arr)[0], ARRAY_SIZE((arr)[0]),	\
> +				     ARRAY_SIZE(arr), val, len, target_power,	\
> +				     txs_delta, &max_power, n_chains, type)
> +
>  	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);
> -
> -	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-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-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);
> -
> -	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);
> -
> -	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);
> -
> -	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);
> -
> -	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);
> -
> -	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);
> +	__apply_array_limit(dest->cck, MT76_SKU_RATE);
> +
> +	val = mt76_get_of_array_s8(np, "rates-ofdm", &len, ARRAY_SIZE(dest->ofdm));
> +	__apply_array_limit(dest->ofdm, MT76_SKU_RATE);
> +
> +	val = mt76_get_of_array_s8(np, "rates-mcs", &len,
> +				   ARRAY_SIZE(dest->mcs[0]) + 1);
> +	__apply_multi_array_limit(dest->mcs, MT76_SKU_RATE);
> +
> +	val = mt76_get_of_array_s8(np, "rates-ru", &len,
> +				   ARRAY_SIZE(dest->ru[0]) + 1);
> +	__apply_multi_array_limit(dest->ru, MT76_SKU_RATE);
> +
> +	val = mt76_get_of_array_s8(np, "paths-cck", &len,
> +				   ARRAY_SIZE(dest->path.cck));
> +	__apply_array_limit(dest->path.cck, MT76_SKU_BACKOFF);
> +
> +	val = mt76_get_of_array_s8(np, "paths-ofdm", &len,
> +				   ARRAY_SIZE(dest->path.ofdm));
> +	__apply_array_limit(dest->path.ofdm, MT76_SKU_BACKOFF);
> +
> +	val = mt76_get_of_array_s8(np, "paths-ofdm-bf", &len,
> +				   ARRAY_SIZE(dest->path.ofdm_bf));
> +	__apply_array_limit(dest->path.ofdm_bf, MT76_SKU_BACKOFF_BF_OFFSET);
> +
> +	val = mt76_get_of_array_s8(np, "paths-ru", &len,
> +				   ARRAY_SIZE(dest->path.ru[0]) + 1);
> +	__apply_multi_array_limit(dest->path.ru, MT76_SKU_BACKOFF);
> +
> +	val = mt76_get_of_array_s8(np, "paths-ru-bf", &len,
> +				   ARRAY_SIZE(dest->path.ru_bf[0]) + 1);
> +	__apply_multi_array_limit(dest->path.ru_bf, MT76_SKU_BACKOFF);
> +
> +#undef __apply_array_limit
> +#undef __apply_multi_array_limit

Is such a big style change really necessary for a patch which is a fix 
(according to you)? This might just make it harder to spot the differences and 
might (in some cases) make it harder to backport it to stable kernels.


Regards,
	Sven

[1] https://b4.docs.kernel.org/en/latest/
[2] https://github.com/openwrt/openwrt/pull/20152#issuecomment-3341491145

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* [PATCH v2 2/2] wifi: ath12k: Fix firmware stats leak when pdev list is empty
From: Saikiran @ 2026-01-26  9:52 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless, kvalo, Saikiran
In-Reply-To: <20260126095244.113301-1-bjsaikiran@gmail.com>

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
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
- 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;
 	}
 
-- 
2.51.0


^ permalink raw reply related

* [PATCH v2 1/2] wifi: ath12k: Remove frequency range filtering for single-phy devices
From: Saikiran @ 2026-01-26  9:52 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless, kvalo, Saikiran
In-Reply-To: <20260126095244.113301-1-bjsaikiran@gmail.com>

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,
the freq_range is set to cover the entire supported spectrum, but the
filtering logic incorrectly restricts channels, causing 5GHz to become
completely unusable.

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;
-- 
2.51.0


^ permalink raw reply related

* [PATCH v2 0/2] wifi: ath12k: Fix 5GHz issues on WCN7850
From: Saikiran @ 2026-01-26  9:52 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless, kvalo, Saikiran

This series addresses two critical issues affecting 5GHz WiFi functionality
on WCN7850 devices, particularly on the Lenovo Yoga Slim 7x.

Changes in v2:
- Patch 1: Simplified approach - remove frequency range filtering entirely
  instead of trying to work around race conditions. Testing confirmed the
  filtering is fundamentally incompatible with single-phy devices.
- Patch 2: Refined based on maintainer feedback - only reset stats buffer
  when pdev list is empty (not on request failure). Improved commit message
  to explain why reset is needed even with empty pdev list.
- Dropped 3 patches from v1 that were either unnecessary or already fixed
  upstream.

The first patch fixes the primary issue where all 5GHz channels were being
filtered out, making 5GHz completely unusable. The second patch addresses
a firmware stats buffer leak that could cause communication failures during
scanning operations.

Both patches have been tested on WCN7850 hw2.0 PCI with firmware
WLAN.HMT.1.1.c5-00302 on the Lenovo Yoga Slim 7x.

v1: https://lore.kernel.org/ath12k/20260123155750.6007-1-bjsaikiran@gmail.com/

Saikiran (2):
  wifi: ath12k: Remove frequency range filtering for single-phy devices
  wifi: ath12k: Fix firmware stats leak when pdev list is empty

 drivers/net/wireless/ath/ath12k/mac.c |  1 +
 drivers/net/wireless/ath/ath12k/reg.c | 13 -------------
 2 files changed, 1 insertion(+), 13 deletions(-)

-- 
2.51.0

^ permalink raw reply

* Re: [PATCH] Revert "wifi: iwlwifi: trans: remove STATUS_SUSPENDED"
From: Chris Bainbridge @ 2026-01-26  8:41 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: <DM3PPF63A6024A93B1437A144E82CC38B7AA393A@DM3PPF63A6024A9.namprd11.prod.outlook.com>

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/

For a more recent commit, this time with KASAN enabled:

[ 3706.202608] ACPI: EC: interrupt unblocked
[ 3706.274784] [drm] PCIE GART of 1024M enabled.
[ 3706.274793] [drm] PTB located at 0x000000F41FC00000
[ 3706.274842] amdgpu 0000:03:00.0: amdgpu: SMU is resuming...
[ 3706.276624] amdgpu 0000:03:00.0: amdgpu: dpm has been disabled
[ 3706.277785] amdgpu 0000:03:00.0: amdgpu: SMU is resumed successfully!
[ 3706.370297] [drm] DM_MST: Differing MST start on aconnector: 000000001fdf7997 [id: 116]
[ 3706.383907] nvme nvme0: 8/0/0 default/read/poll queues
[ 3706.594989] usb 1-3: reset high-speed USB device number 3 using xhci_hcd
[ 3706.935077] usb 1-1: reset high-speed USB device number 2 using xhci_hcd
[ 3707.315021] amdgpu 0000:03:00.0: amdgpu: ring gfx uses VM inv eng 0 on hub 0
[ 3707.315029] amdgpu 0000:03:00.0: amdgpu: ring comp_1.0.0 uses VM inv eng 1 on hub 0
[ 3707.315032] amdgpu 0000:03:00.0: amdgpu: ring comp_1.1.0 uses VM inv eng 4 on hub 0
[ 3707.315034] amdgpu 0000:03:00.0: amdgpu: ring comp_1.2.0 uses VM inv eng 5 on hub 0
[ 3707.315036] amdgpu 0000:03:00.0: amdgpu: ring comp_1.3.0 uses VM inv eng 6 on hub 0
[ 3707.315038] amdgpu 0000:03:00.0: amdgpu: ring comp_1.0.1 uses VM inv eng 7 on hub 0
[ 3707.315039] amdgpu 0000:03:00.0: amdgpu: ring comp_1.1.1 uses VM inv eng 8 on hub 0
[ 3707.315041] amdgpu 0000:03:00.0: amdgpu: ring comp_1.2.1 uses VM inv eng 9 on hub 0
[ 3707.315043] amdgpu 0000:03:00.0: amdgpu: ring comp_1.3.1 uses VM inv eng 10 on hub 0
[ 3707.315045] amdgpu 0000:03:00.0: amdgpu: ring kiq_0.2.1.0 uses VM inv eng 11 on hub 0
[ 3707.315047] amdgpu 0000:03:00.0: amdgpu: ring sdma0 uses VM inv eng 0 on hub 8
[ 3707.315049] amdgpu 0000:03:00.0: amdgpu: ring vcn_dec uses VM inv eng 1 on hub 8
[ 3707.315051] amdgpu 0000:03:00.0: amdgpu: ring vcn_enc0 uses VM inv eng 4 on hub 8
[ 3707.315053] amdgpu 0000:03:00.0: amdgpu: ring vcn_enc1 uses VM inv eng 5 on hub 8
[ 3707.315055] amdgpu 0000:03:00.0: amdgpu: ring jpeg_dec uses VM inv eng 6 on hub 8
[ 3707.448025] usb 1-1.5: reset high-speed USB device number 6 using xhci_hcd
[ 3707.636137] usb 1-1.3: reset high-speed USB device number 4 using xhci_hcd
[ 3707.655263] iwlwifi 0000:01:00.0: Error sending SYSTEM_STATISTICS_CMD: time out after 2000ms.
[ 3707.655322] iwlwifi 0000:01:00.0: Current CMD queue read_ptr 6126 write_ptr 6127
[ 3707.656132] iwlwifi 0000:01:00.0: Start IWL Error Log Dump:
[ 3707.656135] iwlwifi 0000:01:00.0: Transport status: 0x00000042, valid: 6
[ 3707.656139] iwlwifi 0000:01:00.0: Loaded firmware version: 89.7f71c7f4.0 ty-a0-gf-a0-89.ucode
[ 3707.656144] iwlwifi 0000:01:00.0: 0x01000071 | ADVANCED_SYSASSERT          
[ 3707.656148] iwlwifi 0000:01:00.0: 0x000002F0 | trm_hw_status0
[ 3707.656151] iwlwifi 0000:01:00.0: 0x00000000 | trm_hw_status1
[ 3707.656153] iwlwifi 0000:01:00.0: 0x004DAD04 | branchlink2
[ 3707.656156] iwlwifi 0000:01:00.0: 0x004D092A | interruptlink1
[ 3707.656159] iwlwifi 0000:01:00.0: 0x004D092A | interruptlink2
[ 3707.656161] iwlwifi 0000:01:00.0: 0x00016AD2 | data1
[ 3707.656164] iwlwifi 0000:01:00.0: 0x00000010 | data2
[ 3707.656167] iwlwifi 0000:01:00.0: 0x00000000 | data3
[ 3707.656169] iwlwifi 0000:01:00.0: 0x00000000 | beacon time
[ 3707.656172] iwlwifi 0000:01:00.0: 0xDA85A336 | tsf low
[ 3707.656175] iwlwifi 0000:01:00.0: 0x00000000 | tsf hi
[ 3707.656177] iwlwifi 0000:01:00.0: 0x00000000 | time gp1
[ 3707.656180] iwlwifi 0000:01:00.0: 0xDA872EF8 | time gp2
[ 3707.656182] iwlwifi 0000:01:00.0: 0x00000001 | uCode revision type
[ 3707.656185] iwlwifi 0000:01:00.0: 0x00000059 | uCode version major
[ 3707.656188] iwlwifi 0000:01:00.0: 0x7F71C7F4 | uCode version minor
[ 3707.656190] iwlwifi 0000:01:00.0: 0x00000000 | hw version
[ 3707.656193] iwlwifi 0000:01:00.0: 0x00000000 | board version
[ 3707.656196] iwlwifi 0000:01:00.0: 0x804AF800 | hcmd
[ 3707.656198] iwlwifi 0000:01:00.0: 0x00020000 | isr0
[ 3707.656201] iwlwifi 0000:01:00.0: 0x00000000 | isr1
[ 3707.656203] iwlwifi 0000:01:00.0: 0x48F04002 | isr2
[ 3707.656206] iwlwifi 0000:01:00.0: 0x00C3000C | isr3
[ 3707.656208] iwlwifi 0000:01:00.0: 0x00000000 | isr4
[ 3707.656211] iwlwifi 0000:01:00.0: 0x00C90103 | last cmd Id
[ 3707.656214] iwlwifi 0000:01:00.0: 0x00016AD2 | wait_event
[ 3707.656216] iwlwifi 0000:01:00.0: 0x00000000 | l2p_control
[ 3707.656219] iwlwifi 0000:01:00.0: 0x00000000 | l2p_duration
[ 3707.656221] iwlwifi 0000:01:00.0: 0x00000000 | l2p_mhvalid
[ 3707.656224] iwlwifi 0000:01:00.0: 0x00000000 | l2p_addr_match
[ 3707.656226] iwlwifi 0000:01:00.0: 0x00000018 | lmpm_pmg_sel
[ 3707.656229] iwlwifi 0000:01:00.0: 0x00000000 | timestamp
[ 3707.656231] iwlwifi 0000:01:00.0: 0x00003054 | flow_handler
[ 3707.656566] iwlwifi 0000:01:00.0: Start IWL Error Log Dump:
[ 3707.656568] iwlwifi 0000:01:00.0: Transport status: 0x00000042, valid: 7
[ 3707.656571] iwlwifi 0000:01:00.0: 0x211010B8 | ADVANCED_SYSASSERT
[ 3707.656574] iwlwifi 0000:01:00.0: 0x00000000 | umac branchlink1
[ 3707.656577] iwlwifi 0000:01:00.0: 0x804838BE | umac branchlink2
[ 3707.656580] iwlwifi 0000:01:00.0: 0xC00814E0 | umac interruptlink1
[ 3707.656582] iwlwifi 0000:01:00.0: 0x00000000 | umac interruptlink2
[ 3707.656585] iwlwifi 0000:01:00.0: 0x00000002 | umac data1
[ 3707.656587] iwlwifi 0000:01:00.0: 0xDEADBEEF | umac data2
[ 3707.656590] iwlwifi 0000:01:00.0: 0xDEADBEEF | umac data3
[ 3707.656593] iwlwifi 0000:01:00.0: 0x00000059 | umac major
[ 3707.656595] iwlwifi 0000:01:00.0: 0x7F71C7F4 | umac minor
[ 3707.656598] iwlwifi 0000:01:00.0: 0xDA872EF3 | frame pointer
[ 3707.656600] iwlwifi 0000:01:00.0: 0xC0886C04 | stack pointer
[ 3707.656603] iwlwifi 0000:01:00.0: 0x00ED01D3 | last host cmd
[ 3707.656606] iwlwifi 0000:01:00.0: 0x00000000 | isr status reg
[ 3707.656926] iwlwifi 0000:01:00.0: IML/ROM dump:
[ 3707.656928] iwlwifi 0000:01:00.0: 0x00000B03 | IML/ROM error/state
[ 3707.657055] iwlwifi 0000:01:00.0: 0x00008E8A | IML/ROM data1
[ 3707.657184] iwlwifi 0000:01:00.0: 0x00000090 | IML/ROM WFPM_AUTH_KEY_0
[ 3707.657309] iwlwifi 0000:01:00.0: Fseq Registers:
[ 3707.657593] iwlwifi 0000:01:00.0: 0x60000000 | FSEQ_ERROR_CODE
[ 3707.657655] iwlwifi 0000:01:00.0: 0x00440007 | FSEQ_TOP_INIT_VERSION
[ 3707.657717] iwlwifi 0000:01:00.0: 0x00080009 | FSEQ_CNVIO_INIT_VERSION
[ 3707.657780] iwlwifi 0000:01:00.0: 0x0000A652 | FSEQ_OTP_VERSION
[ 3707.657842] iwlwifi 0000:01:00.0: 0x00000002 | FSEQ_TOP_CONTENT_VERSION
[ 3707.657903] iwlwifi 0000:01:00.0: 0x4552414E | FSEQ_ALIVE_TOKEN
[ 3707.657965] iwlwifi 0000:01:00.0: 0x00400410 | FSEQ_CNVI_ID
[ 3707.658027] iwlwifi 0000:01:00.0: 0x00400410 | FSEQ_CNVR_ID
[ 3707.658089] iwlwifi 0000:01:00.0: 0x00400410 | CNVI_AUX_MISC_CHIP
[ 3707.658155] iwlwifi 0000:01:00.0: 0x00400410 | CNVR_AUX_MISC_CHIP
[ 3707.658219] iwlwifi 0000:01:00.0: 0x00009061 | CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM
[ 3707.658283] iwlwifi 0000:01:00.0: 0x00000061 | CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR
[ 3707.658345] iwlwifi 0000:01:00.0: 0x00080009 | FSEQ_PREV_CNVIO_INIT_VERSION
[ 3707.658406] iwlwifi 0000:01:00.0: 0x00440007 | FSEQ_WIFI_FSEQ_VERSION
[ 3707.658468] iwlwifi 0000:01:00.0: 0x00440007 | FSEQ_BT_FSEQ_VERSION
[ 3707.658529] iwlwifi 0000:01:00.0: 0x000000E6 | FSEQ_CLASS_TP_VERSION
[ 3707.658894] iwlwifi 0000:01:00.0: UMAC CURRENT PC: 0xc0080040
[ 3707.658956] iwlwifi 0000:01:00.0: LMAC1 CURRENT PC: 0xd0
[ 3707.660021] iwlwifi 0000:01:00.0: iwl_mvm_check_rt_status failed, device is gone during suspend
[ 3707.660495] iwlwifi 0000:01:00.0: Start IWL Error Log Dump:
[ 3707.660498] iwlwifi 0000:01:00.0: Transport status: 0x00000642, valid: 6
[ 3707.660501] iwlwifi 0000:01:00.0: Loaded firmware version: 89.7f71c7f4.0 ty-a0-gf-a0-89.ucode
[ 3707.660504] iwlwifi 0000:01:00.0: 0x01000071 | ADVANCED_SYSASSERT          
[ 3707.660507] iwlwifi 0000:01:00.0: 0x000002F0 | trm_hw_status0
[ 3707.660510] iwlwifi 0000:01:00.0: 0x00000000 | trm_hw_status1
[ 3707.660512] iwlwifi 0000:01:00.0: 0x004DAD04 | branchlink2
[ 3707.660515] iwlwifi 0000:01:00.0: 0x004D092A | interruptlink1
[ 3707.660518] iwlwifi 0000:01:00.0: 0x004D092A | interruptlink2
[ 3707.660521] iwlwifi 0000:01:00.0: 0x00016AD2 | data1
[ 3707.660523] iwlwifi 0000:01:00.0: 0x00000010 | data2
[ 3707.660526] iwlwifi 0000:01:00.0: 0x00000000 | data3
[ 3707.660529] iwlwifi 0000:01:00.0: 0x00000000 | beacon time
[ 3707.660531] iwlwifi 0000:01:00.0: 0xDA85A336 | tsf low
[ 3707.660534] iwlwifi 0000:01:00.0: 0x00000000 | tsf hi
[ 3707.660537] iwlwifi 0000:01:00.0: 0x00000000 | time gp1
[ 3707.660539] iwlwifi 0000:01:00.0: 0xDA872EF8 | time gp2
[ 3707.660542] iwlwifi 0000:01:00.0: 0x00000001 | uCode revision type
[ 3707.660545] iwlwifi 0000:01:00.0: 0x00000059 | uCode version major
[ 3707.660547] iwlwifi 0000:01:00.0: 0x7F71C7F4 | uCode version minor
[ 3707.660550] iwlwifi 0000:01:00.0: 0x00000000 | hw version
[ 3707.660553] iwlwifi 0000:01:00.0: 0x00000000 | board version
[ 3707.660555] iwlwifi 0000:01:00.0: 0x804AF800 | hcmd
[ 3707.660558] iwlwifi 0000:01:00.0: 0x00020000 | isr0
[ 3707.660561] iwlwifi 0000:01:00.0: 0x00000000 | isr1
[ 3707.660563] iwlwifi 0000:01:00.0: 0x48F04002 | isr2
[ 3707.660566] iwlwifi 0000:01:00.0: 0x00C3000C | isr3
[ 3707.660568] iwlwifi 0000:01:00.0: 0x00000000 | isr4
[ 3707.660571] iwlwifi 0000:01:00.0: 0x00C90103 | last cmd Id
[ 3707.660574] iwlwifi 0000:01:00.0: 0x00016AD2 | wait_event
[ 3707.660576] iwlwifi 0000:01:00.0: 0x00000000 | l2p_control
[ 3707.660579] iwlwifi 0000:01:00.0: 0x00000000 | l2p_duration
[ 3707.660581] iwlwifi 0000:01:00.0: 0x00000000 | l2p_mhvalid
[ 3707.660584] iwlwifi 0000:01:00.0: 0x00000000 | l2p_addr_match
[ 3707.660587] iwlwifi 0000:01:00.0: 0x00000018 | lmpm_pmg_sel
[ 3707.660589] iwlwifi 0000:01:00.0: 0x00000000 | timestamp
[ 3707.660592] iwlwifi 0000:01:00.0: 0x00003054 | flow_handler
[ 3707.660931] iwlwifi 0000:01:00.0: Start IWL Error Log Dump:
[ 3707.660934] iwlwifi 0000:01:00.0: Transport status: 0x00000642, valid: 7
[ 3707.660937] iwlwifi 0000:01:00.0: 0x211010B8 | ADVANCED_SYSASSERT
[ 3707.660940] iwlwifi 0000:01:00.0: 0x00000000 | umac branchlink1
[ 3707.660943] iwlwifi 0000:01:00.0: 0x804838BE | umac branchlink2
[ 3707.660945] iwlwifi 0000:01:00.0: 0xC00814E0 | umac interruptlink1
[ 3707.660948] iwlwifi 0000:01:00.0: 0x00000000 | umac interruptlink2
[ 3707.660951] iwlwifi 0000:01:00.0: 0x00000002 | umac data1
[ 3707.660953] iwlwifi 0000:01:00.0: 0xDEADBEEF | umac data2
[ 3707.660956] iwlwifi 0000:01:00.0: 0xDEADBEEF | umac data3
[ 3707.660959] iwlwifi 0000:01:00.0: 0x00000059 | umac major
[ 3707.660961] iwlwifi 0000:01:00.0: 0x7F71C7F4 | umac minor
[ 3707.660964] iwlwifi 0000:01:00.0: 0xDA872EF3 | frame pointer
[ 3707.660967] iwlwifi 0000:01:00.0: 0xC0886C04 | stack pointer
[ 3707.660970] iwlwifi 0000:01:00.0: 0x00ED01D3 | last host cmd
[ 3707.660972] iwlwifi 0000:01:00.0: 0x00000000 | isr status reg
[ 3707.661290] iwlwifi 0000:01:00.0: IML/ROM dump:
[ 3707.661293] iwlwifi 0000:01:00.0: 0x00000B03 | IML/ROM error/state
[ 3707.661418] iwlwifi 0000:01:00.0: 0x00008E8A | IML/ROM data1
[ 3707.661546] iwlwifi 0000:01:00.0: 0x00000090 | IML/ROM WFPM_AUTH_KEY_0
[ 3707.661669] iwlwifi 0000:01:00.0: Fseq Registers:
[ 3707.661905] iwlwifi 0000:01:00.0: 0x60000000 | FSEQ_ERROR_CODE
[ 3707.661967] iwlwifi 0000:01:00.0: 0x00440007 | FSEQ_TOP_INIT_VERSION
[ 3707.662029] iwlwifi 0000:01:00.0: 0x00080009 | FSEQ_CNVIO_INIT_VERSION
[ 3707.662091] iwlwifi 0000:01:00.0: 0x0000A652 | FSEQ_OTP_VERSION
[ 3707.662153] iwlwifi 0000:01:00.0: 0x00000002 | FSEQ_TOP_CONTENT_VERSION
[ 3707.662214] iwlwifi 0000:01:00.0: 0x4552414E | FSEQ_ALIVE_TOKEN
[ 3707.662276] iwlwifi 0000:01:00.0: 0x00400410 | FSEQ_CNVI_ID
[ 3707.662338] iwlwifi 0000:01:00.0: 0x00400410 | FSEQ_CNVR_ID
[ 3707.662401] iwlwifi 0000:01:00.0: 0x00400410 | CNVI_AUX_MISC_CHIP
[ 3707.662466] iwlwifi 0000:01:00.0: 0x00400410 | CNVR_AUX_MISC_CHIP
[ 3707.662541] iwlwifi 0000:01:00.0: 0x00009061 | CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM
[ 3707.662770] iwlwifi 0000:01:00.0: 0x00000061 | CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR
[ 3707.662832] iwlwifi 0000:01:00.0: 0x00080009 | FSEQ_PREV_CNVIO_INIT_VERSION
[ 3707.662893] iwlwifi 0000:01:00.0: 0x00440007 | FSEQ_WIFI_FSEQ_VERSION
[ 3707.662956] iwlwifi 0000:01:00.0: 0x00440007 | FSEQ_BT_FSEQ_VERSION
[ 3707.663017] iwlwifi 0000:01:00.0: 0x000000E6 | FSEQ_CLASS_TP_VERSION
[ 3707.663203] iwlwifi 0000:01:00.0: UMAC CURRENT PC: 0xc0080040
[ 3707.663267] iwlwifi 0000:01:00.0: LMAC1 CURRENT PC: 0xd0
[ 3707.663331] iwlwifi 0000:01:00.0: WRT: Collecting data: ini trigger 4 fired (delay=0ms).
[ 3708.074557] usb 1-1.3.5: reset high-speed USB device number 10 using xhci_hcd
[ 3708.225056] iwlwifi 0000:01:00.0: WRT: Collecting data: ini trigger 4 fired (delay=0ms).
[ 3708.270765] usb 1-1.3.4: reset high-speed USB device number 8 using xhci_hcd
[ 3708.801001] usb 1-1.3.2: reset high-speed USB device number 7 using xhci_hcd
[ 3709.034210] iwlwifi 0000:01:00.0: WFPM_UMAC_PD_NOTIFICATION: 0x20
[ 3709.034301] iwlwifi 0000:01:00.0: WFPM_LMAC2_PD_NOTIFICATION: 0x1f
[ 3709.034374] iwlwifi 0000:01:00.0: WFPM_AUTH_KEY_0: 0x90
[ 3709.034454] iwlwifi 0000:01:00.0: CNVI_SCU_SEQ_DATA_DW9: 0x0
[ 3709.257815] usb 1-1.3.2.1: reset full-speed USB device number 9 using xhci_hcd
[ 3709.447487] usb 1-1.3.2.3: reset full-speed USB device number 11 using xhci_hcd
[ 3709.635731] usb 1-1.3.2.4: reset high-speed USB device number 12 using xhci_hcd
[ 3710.026286] usb 1-1.3.2.3.1: reset low-speed USB device number 13 using xhci_hcd
[ 3710.566575] usb 1-1.3.2.3.4: reset low-speed USB device number 14 using xhci_hcd
[ 3710.931672] OOM killer enabled.
[ 3710.931678] Restarting tasks: Starting
[ 3710.932001] usb 1-4: USB disconnect, device number 15
[ 3710.938201] Restarting tasks: Done
[ 3710.938271] efivarfs: resyncing variable state
[ 3710.957965] efivarfs: finished resyncing variable state
[ 3710.958074] random: crng reseeded on system resumption
[ 3711.059848] PM: suspend exit
[ 3711.094289] usb 1-4: new full-speed USB device number 16 using xhci_hcd
[ 3711.107258] Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN
[ 3711.107285] KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
[ 3711.107297] CPU: 1 UID: 0 PID: 1560 Comm: wpa_supplicant Not tainted 6.19.0-rc6-00339-g62085877ae65 #373 PREEMPT(voluntary) 
[ 3711.107307] Hardware name: HP HP Pavilion Aero Laptop 13-be0xxx/8916, BIOS F.17 12/18/2024
[ 3711.107314] RIP: 0010:iwl_mvm_get_wd_timeout+0x10a/0x180 [iwlmvm]
[ 3711.107379] Code: df 48 c1 ea 03 80 3c 02 00 75 6d 49 8b 85 30 01 00 00 48 0f ba e0 26 73 27 48 b8 00 00 00 00 00 fc ff df 48 89 ea 48 c1 ea 03 <0f> b6 04 02 84 c0 74 04 3c 03 7e 21 31 c0 83 7d 00 03 44 0f 44 e0
[ 3711.107388] RSP: 0018:ffff888128caeb68 EFLAGS: 00010256
[ 3711.107399] RAX: dffffc0000000000 RBX: ffff88812864c140 RCX: ffffffffc56a2bf4
[ 3711.107404] RDX: 0000000000000000 RSI: 0000000000000008 RDI: ffff88812864c140
[ 3711.107410] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffed10250c9828
[ 3711.107414] R10: ffff88812864c147 R11: 0000000000000002 R12: 0000000000002710
[ 3711.107418] R13: ffff88812864c010 R14: dffffc0000000000 R15: ffff888136ffb0e8
[ 3711.107423] FS:  00007f76a0ff9880(0000) GS:ffff8883e7d30000(0000) knlGS:0000000000000000
[ 3711.107430] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 3711.107434] CR2: 0000357c0c75f000 CR3: 00000001215c2000 CR4: 0000000000750ef0
[ 3711.107440] PKRU: 55555554
[ 3711.107445] Call Trace:
[ 3711.107458]  <TASK>
[ 3711.107466]  iwl_mvm_realloc_queues_after_restart+0x96/0x5a0 [iwlmvm]
[ 3711.107499]  ? kasan_save_stack+0x3b/0x50
[ 3711.107521]  ? kasan_save_stack+0x2c/0x50
[ 3711.107526]  ? kasan_save_track+0x10/0x30
[ 3711.107534]  ? sta_info_insert_rcu+0x6fc/0x22e0 [mac80211]
[ 3711.107688]  ? iwl_mvm_sta_alloc_queue_tvqm.isra.0+0x2f0/0x2f0 [iwlmvm]
[ 3711.107720]  ? genl_family_rcv_msg_doit+0x1dd/0x2b0
[ 3711.107735]  ? lock_is_held_type+0xd5/0x130
[ 3711.107751]  iwl_mvm_mld_add_sta+0x499/0xf60 [iwlmvm]
[ 3711.107781]  iwl_mvm_mac_sta_state_common+0x390/0x2590 [iwlmvm]
[ 3711.107814]  drv_sta_state+0x288/0x16b0 [mac80211]
[ 3711.107934]  sta_info_insert_rcu+0x11e5/0x22e0 [mac80211]
[ 3711.108025]  ? drv_link_info_changed+0x3ea/0x6c0 [mac80211]
[ 3711.108113]  sta_info_insert+0xb/0x70 [mac80211]
[ 3711.108197]  ieee80211_prep_connection+0xc44/0x1300 [mac80211]
[ 3711.108294]  ieee80211_mgd_auth+0xa28/0x1530 [mac80211]
[ 3711.108383]  ? ieee80211_mlme_notify_scan_completed+0x430/0x430 [mac80211]
[ 3711.108466]  ? __local_bh_enable_ip+0xab/0x130
[ 3711.108479]  ? rcu_is_watching+0x11/0xb0
[ 3711.108494]  ? __cfg80211_get_bss+0x687/0xcf0 [cfg80211]
[ 3711.108646]  ? lock_is_held_type+0xd5/0x130
[ 3711.108662]  cfg80211_mlme_auth+0x457/0x8e0 [cfg80211]
[ 3711.108751]  nl80211_authenticate+0xa25/0x1050 [cfg80211]
[ 3711.108836]  ? nl80211_parse_key+0xe80/0xe80 [cfg80211]
[ 3711.108923]  ? nl80211_pre_doit+0x50a/0x7a0 [cfg80211]
[ 3711.109000]  genl_family_rcv_msg_doit+0x1dd/0x2b0
[ 3711.109017]  ? genl_family_rcv_msg_attrs_parse.isra.0+0x230/0x230
[ 3711.109025]  ? genl_get_cmd+0x339/0x740
[ 3711.109035]  ? apparmor_capable+0xf0/0x2e0
[ 3711.109047]  ? security_capable+0x7b/0x150
[ 3711.109057]  genl_rcv_msg+0x428/0x6f0
[ 3711.109064]  ? genl_family_rcv_msg_dumpit+0x2c0/0x2c0
[ 3711.109072]  ? nl80211_join_mesh+0x1060/0x1060 [cfg80211]
[ 3711.109152]  ? nl80211_parse_key+0xe80/0xe80 [cfg80211]
[ 3711.109229]  ? nlmsg_trim+0x60/0x60 [cfg80211]
[ 3711.109308]  ? __lock_acquire+0x459/0x2170
[ 3711.109319]  netlink_rcv_skb+0x123/0x380
[ 3711.109328]  ? genl_family_rcv_msg_dumpit+0x2c0/0x2c0
[ 3711.109335]  ? lock_acquire+0x178/0x2f0
[ 3711.109343]  ? netlink_ack+0xd80/0xd80
[ 3711.109353]  ? netlink_deliver_tap+0xcb/0xa70
[ 3711.109360]  ? netlink_deliver_tap+0x14c/0xa70
[ 3711.109368]  genl_rcv+0x24/0x40
[ 3711.109375]  netlink_unicast+0x5bf/0x970
[ 3711.109382]  ? netlink_attachskb+0x940/0x940
[ 3711.109391]  ? __check_object_size+0x3bc/0x630
[ 3711.109403]  netlink_sendmsg+0x754/0xc10
[ 3711.109412]  ? netlink_unicast+0x970/0x970
[ 3711.109420]  ? find_held_lock+0x2b/0x80
[ 3711.109428]  ? netlink_unicast+0x970/0x970
[ 3711.109435]  __sock_sendmsg+0xc1/0x150
[ 3711.109447]  ____sys_sendmsg+0x617/0x900
[ 3711.109453]  ? copy_msghdr_from_user+0x26f/0x430
[ 3711.109460]  ? kernel_sendmsg+0x30/0x30
[ 3711.109465]  ? move_addr_to_kernel+0xf0/0xf0
[ 3711.109472]  ? lock_acquire+0x178/0x2f0
[ 3711.109481]  ? __lock_acquire+0x459/0x2170
[ 3711.109488]  ? lock_acquire+0x178/0x2f0
[ 3711.109494]  ___sys_sendmsg+0xfc/0x180
[ 3711.109501]  ? copy_msghdr_from_user+0x430/0x430
[ 3711.109506]  ? lock_acquire+0x178/0x2f0
[ 3711.109516]  ? _copy_from_user+0x3e/0x90
[ 3711.109533]  __sys_sendmsg+0x120/0x1b0
[ 3711.109541]  ? __sys_sendmsg_sock+0x20/0x20
[ 3711.109551]  ? lock_release+0x17b/0x2a0
[ 3711.109560]  do_syscall_64+0x95/0x830
[ 3711.109571]  ? rcu_is_watching+0x11/0xb0
[ 3711.109580]  ? kfree+0x2d2/0x5c0
[ 3711.109588]  ? do_syscall_64+0x1dc/0x830
[ 3711.109596]  ? do_sock_setsockopt+0x1be/0x3a0
[ 3711.109603]  ? do_sock_setsockopt+0x1be/0x3a0
[ 3711.109610]  ? move_addr_to_user+0x140/0x140
[ 3711.109617]  ? entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 3711.109624]  ? lockdep_hardirqs_on+0x78/0x100
[ 3711.109635]  ? __sys_setsockopt+0x141/0x1f0
[ 3711.109644]  ? entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 3711.109649]  ? lockdep_hardirqs_on+0x78/0x100
[ 3711.109656]  ? do_syscall_64+0x1dc/0x830
[ 3711.109662]  ? entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 3711.109668]  ? lockdep_hardirqs_on+0x78/0x100
[ 3711.109675]  ? do_syscall_64+0x1dc/0x830
[ 3711.109680]  ? lockdep_hardirqs_on+0x78/0x100
[ 3711.109686]  ? do_syscall_64+0x1dc/0x830
[ 3711.109692]  ? do_syscall_64+0x1dc/0x830
[ 3711.109698]  ? lockdep_hardirqs_on+0x78/0x100
[ 3711.109704]  ? do_syscall_64+0x1dc/0x830
[ 3711.109709]  ? irqentry_exit+0xec/0x670
[ 3711.109718]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 3711.109723] RIP: 0033:0x7f76a129a687
[ 3711.109735] Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
[ 3711.109742] RSP: 002b:00007ffd261d3450 EFLAGS: 00000202 ORIG_RAX: 000000000000002e
[ 3711.109751] RAX: ffffffffffffffda RBX: 00007f76a0ff9880 RCX: 00007f76a129a687
[ 3711.109756] RDX: 0000000000000000 RSI: 00007ffd261d34d0 RDI: 0000000000000006
[ 3711.109761] RBP: 000056466bf8abc0 R08: 0000000000000000 R09: 0000000000000000
[ 3711.109766] R10: 0000000000000000 R11: 0000000000000202 R12: 000056466bed6140
[ 3711.109770] R13: 00007ffd261d34d0 R14: 0000000000000000 R15: 00007ffd261d35b4
[ 3711.109779]  </TASK>
[ 3711.109784] Modules linked in: snd_seq_dummy snd_hrtimer snd_seq xt_conntrack nft_chain_nat xt_MASQUERADE nf_nat nf_conntrack_netlink nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 xfrm_user xfrm_algo xt_addrtype nft_compat x_tables nf_tables br_netfilter bridge stp llc ccm overlay qrtr rfcomm cmac algif_hash algif_skcipher af_alg bnep binfmt_misc ext4 mbcache jbd2 nls_ascii nls_cp437 vfat fat iwlmvm snd_hda_codec_generic snd_hda_codec_hdmi amd_atl mac80211 intel_rapl_msr snd_acp3x_pdm_dma intel_rapl_common snd_acp3x_rn snd_soc_dmic snd_hda_intel snd_usb_audio snd_soc_core snd_hda_codec snd_usbmidi_lib libarc4 snd_intel_dspcfg uvcvideo kvm_amd snd_compress snd_hwdep snd_rawmidi btusb videobuf2_vmalloc btrtl videobuf2_memops snd_seq_device snd_pci_acp6x snd_hda_core kvm btintel uvc snd_pci_acp5x iwlwifi btbcm videobuf2_v4l2 snd_pcm irqbypass btmtk videodev snd_rn_pci_acp3x bluetooth snd_timer rapl snd_acp_config ecdh_generic cfg80211 pcspkr snd wmi_bmof ecc videobuf2_common snd_soc_acpi ee1004 k10temp snd_pci_acp3x sg mc
[ 3711.110032]  rfkill ccp soundcore battery ac button amd_pmc acpi_tad joydev evdev msr parport_pc ppdev lp parport fuse nvme_fabrics efi_pstore configfs nfnetlink efivarfs autofs4 crc32c_cryptoapi btrfs blake2b libblake2b xor raid6_pq dm_crypt hid_microsoft ff_memless hid_cmedia r8153_ecm cdc_ether usbnet dm_mod r8152 mii libphy mdio_bus sd_mod uas usb_storage scsi_mod usbhid scsi_common amdgpu drm_client_lib i2c_algo_bit drm_ttm_helper ttm drm_exec drm_suballoc_helper drm_buddy drm_panel_backlight_quirks gpu_sched amdxcp hid_multitouch drm_display_helper ucsi_acpi hid_generic typec_ucsi drm_kms_helper xhci_pci roles cec xhci_hcd sp5100_tco i2c_hid_acpi nvme ghash_clmulni_intel typec rc_core serio_raw amd_sfh watchdog i2c_hid usbcore nvme_core i2c_piix4 crc16 video thunderbolt i2c_smbus hid fan usb_common wmi drm aesni_intel
[ 3711.110300] ---[ end trace 0000000000000000 ]---
[ 3711.312579] usb 1-4: New USB device found, idVendor=04f3, idProduct=0c00, bcdDevice= 2.83
[ 3711.312602] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 3711.312607] usb 1-4: Product: ELAN:ARM-M4
[ 3711.312613] usb 1-4: Manufacturer: ELAN
[ 3711.422307] RIP: 0010:iwl_mvm_get_wd_timeout+0x10a/0x180 [iwlmvm]
[ 3711.422432] Code: df 48 c1 ea 03 80 3c 02 00 75 6d 49 8b 85 30 01 00 00 48 0f ba e0 26 73 27 48 b8 00 00 00 00 00 fc ff df 48 89 ea 48 c1 ea 03 <0f> b6 04 02 84 c0 74 04 3c 03 7e 21 31 c0 83 7d 00 03 44 0f 44 e0
[ 3711.422441] RSP: 0018:ffff888128caeb68 EFLAGS: 00010256
[ 3711.422454] RAX: dffffc0000000000 RBX: ffff88812864c140 RCX: ffffffffc56a2bf4
[ 3711.422459] RDX: 0000000000000000 RSI: 0000000000000008 RDI: ffff88812864c140
[ 3711.422464] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffed10250c9828
[ 3711.422469] R10: ffff88812864c147 R11: 0000000000000002 R12: 0000000000002710
[ 3711.422473] R13: ffff88812864c010 R14: dffffc0000000000 R15: ffff888136ffb0e8
[ 3711.422478] FS:  00007f76a0ff9880(0000) GS:ffff8883e7d30000(0000) knlGS:0000000000000000
[ 3711.422485] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 3711.422490] CR2: 0000357c0c75f000 CR3: 00000001215c2000 CR4: 0000000000750ef0
[ 3711.422497] PKRU: 55555554
[ 3711.592217] ==================================================================
[ 3711.592242] BUG: KASAN: slab-use-after-free in mutex_can_spin_on_owner+0x197/0x1b0
[ 3711.592264] Read of size 4 at addr ffff888133300034 by task kworker/3:2/425817

[ 3711.592283] CPU: 3 UID: 0 PID: 425817 Comm: kworker/3:2 Tainted: G      D             6.19.0-rc6-00339-g62085877ae65 #373 PREEMPT(voluntary) 
[ 3711.592291] Tainted: [D]=DIE
[ 3711.592293] Hardware name: HP HP Pavilion Aero Laptop 13-be0xxx/8916, BIOS F.17 12/18/2024
[ 3711.592298] Workqueue: events iwl_mvm_tcm_work [iwlmvm]
[ 3711.592348] Call Trace:
[ 3711.592351]  <TASK>
[ 3711.592354]  dump_stack_lvl+0x6a/0x90
[ 3711.592364]  print_report+0x174/0x4f2
[ 3711.592371]  ? __virt_addr_valid+0x208/0x420
[ 3711.592380]  ? mutex_can_spin_on_owner+0x197/0x1b0
[ 3711.592385]  kasan_report+0xdb/0x180
[ 3711.592394]  ? mutex_can_spin_on_owner+0x197/0x1b0
[ 3711.592402]  mutex_can_spin_on_owner+0x197/0x1b0
[ 3711.592407]  __mutex_lock+0x32c/0x2150
[ 3711.592415]  ? psi_avgs_work+0x9c/0x200
[ 3711.592422]  ? iwl_mvm_recalc_tcm+0xa14/0x1990 [iwlmvm]
[ 3711.592445]  ? collect_percpu_times+0x554/0x960
[ 3711.592452]  ? mutex_lock_io_nested+0x1cc0/0x1cc0
[ 3711.592457]  ? collect_percpu_times+0x135/0x960
[ 3711.592466]  ? iwl_mvm_recalc_tcm+0x1ab/0x1990 [iwlmvm]
[ 3711.592490]  ? rcu_is_watching+0x11/0xb0
[ 3711.592498]  ? lock_release+0x211/0x2a0
[ 3711.592506]  ? iwl_mvm_recalc_tcm+0xa14/0x1990 [iwlmvm]
[ 3711.592527]  iwl_mvm_recalc_tcm+0xa14/0x1990 [iwlmvm]
[ 3711.592554]  ? update_load_avg+0x1e6/0x2020
[ 3711.592560]  ? sched_clock+0xc/0x20
[ 3711.592565]  ? sched_clock_cpu+0x68/0x530
[ 3711.592571]  ? iwl_mvm_tcm_load_percentage+0x20/0x20 [iwlmvm]
[ 3711.592593]  ? rcu_is_watching+0x11/0xb0
[ 3711.592598]  ? lock_acquire+0x2aa/0x2f0
[ 3711.592602]  ? rcu_is_watching+0x11/0xb0
[ 3711.592607]  ? _raw_spin_unlock_irq+0x24/0x50
[ 3711.592615]  process_one_work+0x849/0x1420
[ 3711.592624]  ? pwq_dec_nr_in_flight+0xe00/0xe00
[ 3711.592632]  ? assign_work+0x168/0x240
[ 3711.592638]  worker_thread+0x5ef/0xfd0
[ 3711.592646]  ? process_one_work+0x1420/0x1420
[ 3711.592650]  kthread+0x3ad/0x760
[ 3711.592655]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3711.592659]  ? ret_from_fork+0x71/0x800
[ 3711.592663]  ? ret_from_fork+0x71/0x800
[ 3711.592668]  ? _raw_spin_unlock_irq+0x24/0x50
[ 3711.592673]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3711.592678]  ret_from_fork+0x54a/0x800
[ 3711.592682]  ? exit_thread+0x70/0x70
[ 3711.592687]  ? __switch_to+0x36f/0xd60
[ 3711.592693]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3711.592698]  ret_from_fork_asm+0x11/0x20
[ 3711.592708]  </TASK>

[ 3711.592789] Allocated by task 1:
[ 3711.592796]  kasan_save_stack+0x2c/0x50
[ 3711.592804]  kasan_save_track+0x10/0x30
[ 3711.592810]  __kasan_slab_alloc+0x62/0x70
[ 3711.592817]  kmem_cache_alloc_node_noprof+0x249/0x730
[ 3711.592825]  copy_process+0x36f/0x65f0
[ 3711.592832]  kernel_clone+0xca/0x6d0
[ 3711.592839]  __do_sys_clone3+0x168/0x1b0
[ 3711.592846]  do_syscall_64+0x95/0x830
[ 3711.592853]  entry_SYSCALL_64_after_hwframe+0x4b/0x53

[ 3711.592863] Freed by task 0:
[ 3711.592868]  kasan_save_stack+0x2c/0x50
[ 3711.592875]  kasan_save_track+0x10/0x30
[ 3711.592882]  kasan_save_free_info+0x37/0x50
[ 3711.592889]  __kasan_slab_free+0x3b/0x60
[ 3711.592895]  kmem_cache_free+0x187/0x630
[ 3711.592901]  rcu_do_batch+0x37a/0xd90
[ 3711.592908]  rcu_core+0x6e1/0xaa0
[ 3711.592914]  handle_softirqs+0x1e0/0x780
[ 3711.592921]  __irq_exit_rcu+0xff/0x200
[ 3711.592928]  irq_exit_rcu+0xa/0x20
[ 3711.592934]  sysvec_apic_timer_interrupt+0x89/0xb0
[ 3711.592941]  asm_sysvec_apic_timer_interrupt+0x16/0x20

[ 3711.592952] Last potentially related work creation:
[ 3711.592957]  kasan_save_stack+0x2c/0x50
[ 3711.592963]  kasan_record_aux_stack+0x88/0x90
[ 3711.592970]  __call_rcu_common.constprop.0+0xc9/0x1090
[ 3711.592977]  rcu_do_batch+0x37a/0xd90
[ 3711.592983]  rcu_core+0x6e1/0xaa0
[ 3711.592989]  handle_softirqs+0x1e0/0x780
[ 3711.592996]  run_ksoftirqd+0x37/0x60
[ 3711.593002]  smpboot_thread_fn+0x2f7/0x990
[ 3711.593010]  kthread+0x3ad/0x760
[ 3711.593015]  ret_from_fork+0x54a/0x800
[ 3711.593021]  ret_from_fork_asm+0x11/0x20

[ 3711.593031] Second to last potentially related work creation:
[ 3711.593035]  kasan_save_stack+0x2c/0x50
[ 3711.593041]  kasan_record_aux_stack+0x88/0x90
[ 3711.593048]  __call_rcu_common.constprop.0+0xc9/0x1090
[ 3711.593054]  release_task+0xccc/0x1800
[ 3711.593061]  wait_consider_task+0x10e8/0x3680
[ 3711.593067]  __do_wait+0x603/0x740
[ 3711.593074]  do_wait+0x187/0x400
[ 3711.593080]  kernel_waitid+0xdc/0x110
[ 3711.593086]  __do_sys_waitid+0x18c/0x1b0
[ 3711.593093]  do_syscall_64+0x95/0x830
[ 3711.593099]  entry_SYSCALL_64_after_hwframe+0x4b/0x53

[ 3711.593109] The buggy address belongs to the object at ffff888133300000
                which belongs to the cache task_struct of size 9304
[ 3711.593116] The buggy address is located 52 bytes inside of
                freed 9304-byte region [ffff888133300000, ffff888133302458)

[ 3711.593127] The buggy address belongs to the physical page:
[ 3711.593132] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x133300
[ 3711.593139] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 3711.593145] memcg:ffff888181817701
[ 3711.593149] flags: 0x17ffffc0000040(head|node=0|zone=2|lastcpupid=0x1fffff)
[ 3711.593159] page_type: f5(slab)
[ 3711.593166] raw: 0017ffffc0000040 ffff8881008b6b40 dead000000000100 dead000000000122
[ 3711.593173] raw: 0000000000000000 0000000000030003 00000000f5000000 ffff888181817701
[ 3711.593179] head: 0017ffffc0000040 ffff8881008b6b40 dead000000000100 dead000000000122
[ 3711.593185] head: 0000000000000000 0000000000030003 00000000f5000000 ffff888181817701
[ 3711.593191] head: 0017ffffc0000003 ffffea0004ccc001 00000000ffffffff 00000000ffffffff
[ 3711.593196] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
[ 3711.593201] page dumped because: kasan: bad access detected

[ 3711.593209] Memory state around the buggy address:
[ 3711.593214]  ffff8881332fff00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 3711.593219]  ffff8881332fff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 3711.593224] >ffff888133300000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3711.593229]                                      ^
[ 3711.593234]  ffff888133300080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3711.593239]  ffff888133300100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3711.593243] ==================================================================

^ permalink raw reply

* Re: [PATCH] wifi: ath12k: Remove broken frequency range filtering
From: Saikiran B @ 2026-01-26  8:28 UTC (permalink / raw)
  To: Baochen Qiang; +Cc: ath12k, linux-wireless, kvalo
In-Reply-To: <CAAFDt1v-CBHPTMHQB2B9o3X547agCj77RF9tpp_sgUAPkUaYSw@mail.gmail.com>

Hi,

After further testing, I've found that the issue is simpler than I
initially thought.

The Real Problem:

The frequency range filtering was added in commit acc152f9be20 for
"split-phy devices" (devices with separate 2.4GHz and 5GHz radios).
However, WCN7850 is a single-phy device that handles both bands on one
radio.

When the filter runs on WCN7850, it incorrectly restricts channels
because the freq_range is set for only one band at a time, causing the
other bands to be filtered out entirely.

Testing Results:
I tested two approaches:

1. Adding a conditional check (skip filter if freq_range.end_freq ==
0) - This did NOT fix the issue
2. Removing the filter entirely - This DOES fix the issue, 5GHz works perfectly

Conclusion:
The frequency range filtering is fundamentally incompatible with
single-phy devices like WCN7850. The firmware already handles
frequency restrictions based on hardware capabilities, so this
driver-level filtering is unnecessary and breaks single-phy devices.

I'll send a V2 that removes the filtering entirely, with an updated
commit message explaining it's designed for split-phy devices and
breaks single-phy devices, If that's ok.

Thanks & Regards,
Saikiran

On Mon, Jan 26, 2026 at 12:33 PM Saikiran B <bjsaikiran@gmail.com> wrote:
>
> Hi Baochen,
>
> Sure.
>
> The Scenario:
> The ath12k_reg_update_chan_list() function filters channels based on ar->freq_range. However, this function can be triggered via a regulatory notifier while ar->freq_range is temporarily uninitialized (zeroed).
>
> The Execution Flow:
>
> - Reset: ath12k_regd_update() starts and resets ar->freq_range to 0 (to prepare for recalculation).
>
> - Trigger: ath12k_regd_update() calls regulatory_set_wiphy_regd(), which triggers the regulatory notifier to other subsystems.
>
> - Race: The notifier callback executes ath12k_reg_update_chan_list().
>
> - Failure: ath12k_reg_update_chan_list() sees ar->freq_range.end_freq == 0. The filter check (center_freq > end_freq) becomes true for all channels.
>
> - Result: All 5GHz channels are erroneously filtered out.
>
> - Observation: On the Lenovo Yoga Slim 7x, this hits consistently during boot and resume. The notifier fires before the driver has finished repopulating the frequency range in ath12k_mac_update_freq_range().
>
> - Proposed Fix: Since we cannot control the notifier timing, I proposed modifying the filter to skip the check if the range is invalid in my previous mail.
>
> Thanks & Regards,
> Saikiran
>
> On Mon, Jan 26, 2026 at 12:22 PM Baochen Qiang <baochen.qiang@oss.qualcomm.com> wrote:
>>
>>
>>
>> On 1/26/2026 2:35 PM, Saikiran B wrote:
>> > Hi Baochen,
>> >
>> > Thanks for the review.
>> >
>> > regarding ath12k_mac_update_freq_range(): You are correct that this
>> > function eventually updates the frequency range.
>> >
>> > However, on the WCN7850 (Lenovo Yoga Slim 7x), there is a race condition
>> > during boot/resume. ath12k_reg_update_chan_list() is being executed *before*
>> > ath12k_regd_update() has finished populating ar->freq_range.
>>
>> could you please elaborate on the race?
>>
>> >
>> > At that specific moment, ar->freq_range.end_freq is still 0. The check: if
>> > (center_freq > KHZ_TO_MHZ(ar->freq_range.end_freq)) evaluates to true for
>> > all channels, causing the driver to silently drop every 5GHz channel from
>> > the scan list.
>> >
>> > If I cannot remove this filter entirely, would you accept a V2 that skips
>> > the filtering if the range is uninitialized?
>> >
>> > Example:
>> >
>> > /* Skip check if regulatory range hasn't been populated yet */if
>> > (ar->freq_range.end_freq != 0 &&
>> >     (center_freq < KHZ_TO_MHZ(ar->freq_range.start_freq) ||
>> >      center_freq > KHZ_TO_MHZ(ar->freq_range.end_freq)))
>> >         continue;
>> >
>> > Without this change (or something similar), 5GHz is completely unusable on
>> > this platform.
>> >
>> > Thanks & Regards,
>> > Jaya saikiran
>> >
>> > On Mon, Jan 26, 2026 at 11:15 AM Baochen Qiang <
>> > baochen.qiang@oss.qualcomm.com> wrote:
>> >
>> >>
>> >>
>> >> On 1/23/2026 11:57 PM, Saikiran wrote:
>> >>> Between kernel 6.16 and 6.17, ath12k added frequency range filtering in
>> >>> ath12k_reg_update_chan_list() that filters channels based on
>> >>> ar->freq_range.start_freq and ar->freq_range.end_freq.
>> >>>
>> >>> However, these values are reset to 0 in ath12k_regd_update(), causing
>> >>
>> >> Yes, it is reset at the first, but it get re-calculated later. See
>> >> ath12k_mac_update_freq_range() called in ath12k_regd_update().
>> >>
>> >>> the filter to skip ALL channels:
>> >>>     if (channel_freq < 0 || channel_freq > 0)  // Always true when
>> >> end_freq=0
>> >>>         continue;  // All channels skipped
>> >>>
>> >>> This results in no channel list sent to firmware, causing 5 GHz Wi-Fi
>> >>> to stop working.
>> >>>
>> >>> Fix by removing the broken frequency range filtering. The firmware
>> >>> itself handles frequency range restrictions based on hardware
>> >> capabilities.
>> >>>
>> >>> 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 2dfcef013277..2d9adc74ac6e 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] Revert "wifi: iwlwifi: trans: remove STATUS_SUSPENDED"
From: Korenblit, Miriam Rachel @ 2026-01-26  7:15 UTC (permalink / raw)
  To: Chris Bainbridge, kvalo@kernel.org
  Cc: 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: <20260125233335.6875-1-chris.bainbridge@gmail.com>


> -----Original Message-----
> From: Chris Bainbridge <chris.bainbridge@gmail.com>
> Sent: Monday, January 26, 2026 1:34 AM
> To: Korenblit, Miriam Rachel <miriam.rachel.korenblit@intel.com>;
> kvalo@kernel.org
> Cc: 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; Chris Bainbridge <chris.bainbridge@gmail.com>;
> stable@vger.kernel.org
> Subject: [PATCH] Revert "wifi: iwlwifi: trans: remove STATUS_SUSPENDED"
> 
> This reverts commit e769f6f27ffe41331e00b69a33aa8a34db4dd830.
> 
> The removal of STATUS_SUSPENDED (which tracks suspend/resume state)
> resulted in an intermittent race condition on resume. The fault can be
> reproduced by carrying out repeated suspend/resume cycles while passing
> traffic through the NIC. A typical failure looks like:
> 
> [  141.093986] iwlwifi 0000:01:00.0: Error sending SCAN_CFG_CMD: time out
> after 2000ms.
> [  141.094057] iwlwifi 0000:01:00.0: Current CMD queue read_ptr 441
> write_ptr 442 [  141.094864] iwlwifi 0000:01:00.0: Start IWL Error Log Dump:
> [  141.094866] iwlwifi 0000:01:00.0: Transport status: 0x00000042, valid: 6 [
> 141.094870] iwlwifi 0000:01:00.0: Loaded firmware version: 89.7f71c7f4.0 ty-
> a0-gf-a0-89.ucode [  141.094873] iwlwifi 0000:01:00.0: 0x01000071 |
> ADVANCED_SYSASSERT ...
> [  141.098401] iwlwifi 0000:01:00.0: iwl_mvm_check_rt_status failed, device is
> gone during suspend
> 
> The kernel then oops due to a null pointer dereference in
> iwl_mvm_realloc_queues_after_restart().
> 
> Fixes: e769f6f27ffe ("wifi: iwlwifi: trans: remove STATUS_SUSPENDED")
> Closes: https://yhbt.net/lore/linux-
> wireless/aTDoDiD55qlUZ0pn@debian.local/
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Chris Bainbridge <chris.bainbridge@gmail.com>
> ---
>  .../net/wireless/intel/iwlwifi/iwl-trans.c    | 22 +++++++++++++++++--
>  .../net/wireless/intel/iwlwifi/iwl-trans.h    |  3 +++
>  2 files changed, 23 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
> b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
> index cc8a84018f70..f5c4aa165c5b 100644
> --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
> +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
> @@ -306,6 +306,9 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct
> iwl_host_cmd *cmd)
>  		     test_bit(STATUS_RFKILL_OPMODE, &trans->status)))
>  		return -ERFKILL;
> 
> +	if (unlikely(test_bit(STATUS_SUSPENDED, &trans->status)))
> +		return -EHOSTDOWN;
> +
>  	if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
>  		return -EIO;
> 
> @@ -406,6 +409,8 @@ int iwl_trans_start_hw(struct iwl_trans *trans)
>  	might_sleep();
> 
>  	clear_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status);
> +	/* opmode may not resume if it detects errors */
> +	clear_bit(STATUS_SUSPENDED, &trans->status);
> 
>  	return iwl_trans_pcie_start_hw(trans);  } @@ -505,17 +510,30 @@
> iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
> 
>  int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset)  {
> +	int err;
> +
>  	might_sleep();
> 
> -	return iwl_trans_pcie_d3_suspend(trans, reset);
> +	err = iwl_trans_pcie_d3_suspend(trans, reset);
> +
> +	if (!err)
> +		set_bit(STATUS_SUSPENDED, &trans->status);
> +
> +	return err;
>  }
>  IWL_EXPORT_SYMBOL(iwl_trans_d3_suspend);
> 
>  int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset)  {
> +	int err;
> +
>  	might_sleep();
> 
> -	return iwl_trans_pcie_d3_resume(trans, reset);
> +	err = iwl_trans_pcie_d3_resume(trans, reset);
> +
> +	clear_bit(STATUS_SUSPENDED, &trans->status);
> +
> +	return err;
>  }
>  IWL_EXPORT_SYMBOL(iwl_trans_d3_resume);
> 
> diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
> b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
> index a552669db6e2..c4d06a323f9b 100644
> --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
> +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
> @@ -290,6 +290,8 @@ static inline void iwl_free_rxb(struct
> iwl_rx_cmd_buffer *r)
>   *	the firmware state yet
>   * @STATUS_TRANS_RESET_IN_PROGRESS: reset is still in progress, don't
>   *	attempt another reset yet
> + * @STATUS_SUSPENDED: device is suspended, don't send commands that
> + *	aren't marked accordingly
>   */
>  enum iwl_trans_status {
>  	STATUS_SYNC_HCMD_ACTIVE,
> @@ -303,6 +305,7 @@ enum iwl_trans_status {
>  	STATUS_IN_SW_RESET,
>  	STATUS_RESET_PENDING,
>  	STATUS_TRANS_RESET_IN_PROGRESS,
> +	STATUS_SUSPENDED,
>  };
> 
>  static inline int
> --
> 2.47.3

Hi Chris, could you please provide the full log?

Miri

^ permalink raw reply

* Re: [PATCH] wifi: ath12k: Remove broken frequency range filtering
From: Baochen Qiang @ 2026-01-26  6:51 UTC (permalink / raw)
  To: Saikiran B; +Cc: ath12k, linux-wireless, kvalo
In-Reply-To: <CAAFDt1syi0jLvrho4mnvwsv8HtraT78wP8tCLFHRw3oiTq2E5w@mail.gmail.com>



On 1/26/2026 2:35 PM, Saikiran B wrote:
> Hi Baochen,
> 
> Thanks for the review.
> 
> regarding ath12k_mac_update_freq_range(): You are correct that this
> function eventually updates the frequency range.
> 
> However, on the WCN7850 (Lenovo Yoga Slim 7x), there is a race condition
> during boot/resume. ath12k_reg_update_chan_list() is being executed *before*
> ath12k_regd_update() has finished populating ar->freq_range.

could you please elaborate on the race?

> 
> At that specific moment, ar->freq_range.end_freq is still 0. The check: if
> (center_freq > KHZ_TO_MHZ(ar->freq_range.end_freq)) evaluates to true for
> all channels, causing the driver to silently drop every 5GHz channel from
> the scan list.
> 
> If I cannot remove this filter entirely, would you accept a V2 that skips
> the filtering if the range is uninitialized?
> 
> Example:
> 
> /* Skip check if regulatory range hasn't been populated yet */if
> (ar->freq_range.end_freq != 0 &&
>     (center_freq < KHZ_TO_MHZ(ar->freq_range.start_freq) ||
>      center_freq > KHZ_TO_MHZ(ar->freq_range.end_freq)))
>         continue;
> 
> Without this change (or something similar), 5GHz is completely unusable on
> this platform.
> 
> Thanks & Regards,
> Jaya saikiran
> 
> On Mon, Jan 26, 2026 at 11:15 AM Baochen Qiang <
> baochen.qiang@oss.qualcomm.com> wrote:
> 
>>
>>
>> On 1/23/2026 11:57 PM, Saikiran wrote:
>>> Between kernel 6.16 and 6.17, ath12k added frequency range filtering in
>>> ath12k_reg_update_chan_list() that filters channels based on
>>> ar->freq_range.start_freq and ar->freq_range.end_freq.
>>>
>>> However, these values are reset to 0 in ath12k_regd_update(), causing
>>
>> Yes, it is reset at the first, but it get re-calculated later. See
>> ath12k_mac_update_freq_range() called in ath12k_regd_update().
>>
>>> the filter to skip ALL channels:
>>>     if (channel_freq < 0 || channel_freq > 0)  // Always true when
>> end_freq=0
>>>         continue;  // All channels skipped
>>>
>>> This results in no channel list sent to firmware, causing 5 GHz Wi-Fi
>>> to stop working.
>>>
>>> Fix by removing the broken frequency range filtering. The firmware
>>> itself handles frequency range restrictions based on hardware
>> capabilities.
>>>
>>> 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 2dfcef013277..2d9adc74ac6e 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 ath-next 0/3] wifi: ath12k: Add support for RX pdev TX hardware queue stats via HTT debugfs
From: Baochen Qiang @ 2026-01-26  6:01 UTC (permalink / raw)
  To: Aaradhana Sahu, ath12k; +Cc: linux-wireless
In-Reply-To: <20260123071253.2202644-1-aaradhana.sahu@oss.qualcomm.com>



On 1/23/2026 3:12 PM, Aaradhana Sahu wrote:
> Add support for HTT stats type 2 to report RX pdev firmware and HTT stats
> type 3 to report TX hardware queue stats. Also fix invalid buffer access.
> 
> Aaradhana Sahu (3):
>   wifi: ath12k: Fix index decrement when array_len is zero
>   wifi: ath12k: Add support RX PDEV stats
>   wifi: ath12k: Add support TX hardware queue stats
> 
>  .../wireless/ath/ath12k/debugfs_htt_stats.c   | 197 +++++++++++++++++-
>  .../wireless/ath/ath12k/debugfs_htt_stats.h   |  81 +++++++
>  2 files changed, 275 insertions(+), 3 deletions(-)
> 
> 
> base-commit: 758064145fe77e06d07661b27dfa9c24fe0309a3

Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH] wifi: ath12k: Remove broken frequency range filtering
From: Baochen Qiang @ 2026-01-26  5:45 UTC (permalink / raw)
  To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
In-Reply-To: <20260123155750.6007-5-bjsaikiran@gmail.com>



On 1/23/2026 11:57 PM, Saikiran wrote:
> Between kernel 6.16 and 6.17, ath12k added frequency range filtering in
> ath12k_reg_update_chan_list() that filters channels based on
> ar->freq_range.start_freq and ar->freq_range.end_freq.
> 
> However, these values are reset to 0 in ath12k_regd_update(), causing

Yes, it is reset at the first, but it get re-calculated later. See
ath12k_mac_update_freq_range() called in ath12k_regd_update().

> the filter to skip ALL channels:
>     if (channel_freq < 0 || channel_freq > 0)  // Always true when end_freq=0
>         continue;  // All channels skipped
> 
> This results in no channel list sent to firmware, causing 5 GHz Wi-Fi
> to stop working.
> 
> Fix by removing the broken frequency range filtering. The firmware
> itself handles frequency range restrictions based on hardware capabilities.
> 
> 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 2dfcef013277..2d9adc74ac6e 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] wifi: ath12k: Initialize regulatory frequency ranges to avoid filtering all channels
From: Baochen Qiang @ 2026-01-26  5:26 UTC (permalink / raw)
  To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
In-Reply-To: <20260123155750.6007-3-bjsaikiran@gmail.com>



On 1/23/2026 11:57 PM, Saikiran wrote:
> Commit 657b0c72c4ad ("wifi: ath12k: Fix frequency range in driver")
> added reg_freq_2ghz/5ghz/6ghz structures to intersect regulatory
> frequency ranges with hardware capabilities. However, these structures
> are never initialized for devices with self-managed regulatory (like
> WCN7850).
> 
> The WCN7850 firmware manages its own regulatory domain and never calls
> ath12k_reg_build_regd() which updates these structures. This leaves
> them at {0, 0}, causing this logic in mac.c:

No. That function indeed would be called for WCN7850.

> 
>   freq_high = min(reg_cap->high_5ghz_chan, ab->reg_freq_5ghz.end_freq);
>   // freq_high = min(6000MHz, 0) = 0
> 
> Result: ALL 5GHz channels are filtered out and 5GHz WiFi is broken.
> 
> Fix: Initialize reg_freq_* structures to full frequency ranges in
> ath12k_core_alloc(). For devices with proper regulatory domain
> updates, these will be overwritten by ath12k_reg_build_regd().
> For WCN7850 with self-managed regulatory, these defaults allow
> channels to work.
> 
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302
> Fixes: 657b0c72c4ad ("wifi: ath12k: Fix frequency range in driver")
> 
> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> ---
>  drivers/net/wireless/ath/ath12k/core.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
> index 4121dd14bbcc..99c26ba01304 100644
> --- a/drivers/net/wireless/ath/ath12k/core.c
> +++ b/drivers/net/wireless/ath/ath12k/core.c
> @@ -2290,6 +2290,19 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
>  	ab->qmi.num_radios = U8_MAX;
>  	ab->single_chip_mlo_support = false;
>  
> +	/* Initialize regulatory frequency ranges to full range.
> +	 * These will be updated by ath12k_reg_build_regd() when
> +	 * regulatory domain is set. For WCN7850 with self-managed
> +	 * regulatory, firmware doesn't call reg_build_regd so we
> +	 * need sane defaults to avoid filtering out all channels.
> +	 */
> +	ab->reg_freq_2ghz.start_freq = 2312000; /* 2.312 GHz */
> +	ab->reg_freq_2ghz.end_freq = 2732000;   /* 2.732 GHz */
> +	ab->reg_freq_5ghz.start_freq = 5150000; /* 5.150 GHz */
> +	ab->reg_freq_5ghz.end_freq = 5945000;   /* 5.945 GHz */
> +	ab->reg_freq_6ghz.start_freq = 5945000; /* 5.945 GHz */
> +	ab->reg_freq_6ghz.end_freq = 7125000;   /* 7.125 GHz */
> +
>  	/* Device index used to identify the devices in a group.
>  	 *
>  	 * In Intra-device MLO, only one device present in a group,


^ permalink raw reply

* Re: [PATCH] wifi: ath12k: Fix firmware stats leak on get_txpower error paths
From: Baochen Qiang @ 2026-01-26  5:22 UTC (permalink / raw)
  To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
In-Reply-To: <20260123155750.6007-2-bjsaikiran@gmail.com>



On 1/23/2026 11:57 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().
> 
> However, in ath12k_mac_op_get_txpower(), when ath12k_mac_get_fw_stats()
> succeeds but the pdev stats list is empty, or when the stats request
> fails, the function exits via err_fallback without resetting the stats
> buffer.
> 
> This causes the stats buffer to accumulate data, eventually leading to
> firmware communication failures (error -71/EPROTO) during subsequent
> operations, particularly during 5GHz scanning which requires additional
> TX power queries.

IMO the description is bit generic - can you please describe it in detail? like the code
running path? At lease in
ath12k_wmi_tlv_fw_stats_data_parse()/ath12k_wmi_tlv_rssi_chain_parse() there are several
places returning such error code, and in which exact place is it returned?

> 
> Symptoms:
> - "failed to pull fw stats: -71" errors in dmesg  - 5GHz networks not detected despite hardware support
> - 2.4GHz networks work normally
> 
> Fix this by calling ath12k_fw_stats_reset() on all error paths after
> ath12k_mac_get_fw_stats() is called, ensuring the stats buffer is
> always freed regardless of the execution path.
> 
> 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 | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index f7a2a544bef2..4195364cb6e3 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -5161,6 +5161,7 @@ static int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,
>  	ret = ath12k_mac_get_fw_stats(ar, &params);
>  	if (ret) {
>  		ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
> +		ath12k_fw_stats_reset(ar);
>  		goto err_fallback;
>  	}
>  
> @@ -5169,6 +5170,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);

curious how could this help if the pdev stats list is empty?

>  		goto err_fallback;
>  	}
>  


^ permalink raw reply

* RE: [PATCH] wifi: rtw89: usb: fix TX flow control by tracking in-flight URBs
From: Ping-Ke Shih @ 2026-01-26  3:39 UTC (permalink / raw)
  To: Lucid Duck, linux-wireless@vger.kernel.org, Bitterblue Smith,
	Mh_chen
In-Reply-To: <20260125221943.36001-1-lucid_duck@justthetip.ca>

+ developers of WiFi USB adapters 

Lucid Duck <lucid_duck@justthetip.ca> 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.

Then URB becomes exhausted? 

> 
> 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>

[...]

> 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

Curiously. How did you decide this value? Have you tested USB2 and USB3 devices?
How about their throughput before/after this patch?

> +
>  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 */

I feel we don't need repeatedly adding this comment. If you like it, just
keep one.

> +       atomic_t tx_inflight[RTW89_TXCH_NUM];
>  };
> 
>  static inline struct rtw89_usb *rtw89_usb_priv(struct rtw89_dev *rtwdev)
> --
> 2.52.0
> 


^ permalink raw reply

* Re: [PATCH] wifi: ath12k: Fix invalid frequency error in freq_to_idx
From: Baochen Qiang @ 2026-01-26  3:38 UTC (permalink / raw)
  To: Saikiran, ath12k; +Cc: linux-wireless, kvalo
In-Reply-To: <20260123155750.6007-6-bjsaikiran@gmail.com>



On 1/23/2026 11:57 PM, Saikiran wrote:
> During suspend/resume, the following error is observed in dmesg:
>   ath12k_pci 0004:01:00.0: chan info: invalid frequency <freq> (idx 101 out of bounds)
> 
> This occurs because freq_to_idx() incorrectly filters channels based on
> ar->freq_range.start_freq and ar->freq_range.end_freq. These values can be
> temporarily zeroed out (e.g., during regulatory updates or suspend/resume
> sequences) while the hardware is still operational or reporting status.
> 
> When these values are zero, the filter skips all valid channels, causing
> the function to return the total channel count (e.g. 101) instead of the
> actual index, triggering the out-of-bounds warning.
> 
> Remove the broken frequency range filtering from freq_to_idx(). Channel
> mapping should depend only on the hardware band definition, not on the
> transient regulatory frequency range. This mirrors the fix recently applied
> to ath12k_reg_update_chan_list().
> 
> Tested-on: Lenovo Yoga Slim 7x
> 
> Signed-off-by: Saikiran <bjsaikiran@gmail.com>
> ---
>  drivers/net/wireless/ath/ath12k/wmi.c | 6 +-----
>  1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
> index be8b2943094f..bef1b324b62c 100644
> --- a/drivers/net/wireless/ath/ath12k/wmi.c
> +++ b/drivers/net/wireless/ath/ath12k/wmi.c
> @@ -6576,11 +6576,7 @@ static int freq_to_idx(struct ath12k *ar, int freq)
>  			continue;
>  
>  		for (ch = 0; ch < sband->n_channels; ch++, idx++) {
> -			if (sband->channels[ch].center_freq <
> -			    KHZ_TO_MHZ(ar->freq_range.start_freq) ||
> -			    sband->channels[ch].center_freq >
> -			    KHZ_TO_MHZ(ar->freq_range.end_freq))
> -				continue;
> +
>  
>  			if (sband->channels[ch].center_freq == freq)
>  				goto exit;


this has been fixed upstream, though for a different issue.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1fed08c5519d2f929457f354d3c06c6a8c33829c

^ permalink raw reply

* Re: [PATCH ath-next 0/2] wifi: ath12k: Add pdev-level OBSS PD configuration
From: Baochen Qiang @ 2026-01-26  3:19 UTC (permalink / raw)
  To: Wei Zhang, jeff.johnson; +Cc: ath12k, linux-wireless
In-Reply-To: <20260123064817.364047-1-wei.zhang@oss.qualcomm.com>



On 1/23/2026 2:48 PM, Wei Zhang wrote:
> This series introduces WMI support and AP-mode handling for HE Spatial
> Reuse in ath12k:
> 
> Patch 1 adds new WMI commands, TLV tags, and a service flag to configure
> SRG/non-SRG OBSS PD bitmaps (BSS color and partial BSSID) at the pdev
> level.
> Patch 2 switches AP mode to use the new pdev-level configuration path,
> programming OBSS PD thresholds, per-AC enablement, SR prohibit control,
> and SRG/non-SRG bitmaps based on mac80211 HE SPR parameters.
> 
> These changes enable firmware-managed OBSS PD behavior for HE Spatial
> Reuse.
> 
> Tested-on: WCN7850 hw2.0 PCI WLAN.IOE_HMT.1.1-00011-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1
> Tested-on: QCN9274 hw2.0 WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1
> 
> Wei Zhang (2):
>   wifi: ath12k: add WMI support for spatial reuse parameter
>     configuration
>   wifi: ath12k: support OBSS PD configuration for AP mode
> 
>  drivers/net/wireless/ath/ath12k/mac.c | 170 +++++++++++++++++++++++++-
>  drivers/net/wireless/ath/ath12k/mac.h |   3 +
>  drivers/net/wireless/ath/ath12k/wmi.c | 142 +++++++++++++++++++++
>  drivers/net/wireless/ath/ath12k/wmi.h |  47 +++++++
>  4 files changed, 359 insertions(+), 3 deletions(-)
> 
> 
> base-commit: 758064145fe77e06d07661b27dfa9c24fe0309a3

Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH] wifi: ath10k: sdio: add missing lock protection in ath10k_sdio_fw_crashed_dump()
From: Baochen Qiang @ 2026-01-26  2:16 UTC (permalink / raw)
  To: Ziyi Guo, Jeff Johnson; +Cc: linux-wireless, ath10k, linux-kernel
In-Reply-To: <20260123045822.2221549-1-n7l8m4@u.northwestern.edu>



On 1/23/2026 12:58 PM, Ziyi Guo wrote:
> ath10k_sdio_fw_crashed_dump() calls ath10k_coredump_new() which requires
> ar->dump_mutex to be held, as indicated by lockdep_assert_held() in that
> function. However, the SDIO implementation does not acquire this lock,
> unlike the PCI and SNOC implementations which properly hold the mutex.
> 
> Additionally, ar->stats.fw_crash_counter is documented as protected by
> ar->data_lock in core.h, but the SDIO implementation modifies it without
> holding this spinlock.
> 
> Add the missing mutex_lock()/mutex_unlock() around the coredump
> operations, and add spin_lock_bh()/spin_unlock_bh() around the
> fw_crash_counter increment, following the pattern used in
> ath10k_pci_fw_dump_work() and ath10k_snoc_fw_crashed_dump().
> 
> Fixes: 3c45f21af84e ("ath10k: sdio: add firmware coredump support")
> Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
> ---
>  drivers/net/wireless/ath/ath10k/sdio.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
> index c06d50db40b8..00d0556dafef 100644
> --- a/drivers/net/wireless/ath/ath10k/sdio.c
> +++ b/drivers/net/wireless/ath/ath10k/sdio.c
> @@ -2487,7 +2487,11 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar)
>  	if (fast_dump)
>  		ath10k_bmi_start(ar);
>  
> +	mutex_lock(&ar->dump_mutex);
> +
> +	spin_lock_bh(&ar->data_lock);
>  	ar->stats.fw_crash_counter++;
> +	spin_unlock_bh(&ar->data_lock);
>  
>  	ath10k_sdio_disable_intrs(ar);
>  
> @@ -2505,6 +2509,8 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar)
>  
>  	ath10k_sdio_enable_intrs(ar);
>  
> +	mutex_unlock(&ar->dump_mutex);
> +
>  	ath10k_core_start_recovery(ar);
>  }
>  

Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH v2] wifi: ath10k: fix lock protection in ath10k_wmi_event_peer_sta_ps_state_chg()
From: Baochen Qiang @ 2026-01-26  2:15 UTC (permalink / raw)
  To: Ziyi Guo, Jeff Johnson; +Cc: linux-wireless, ath10k, linux-kernel
In-Reply-To: <20260123175611.767731-1-n7l8m4@u.northwestern.edu>



On 1/24/2026 1:56 AM, Ziyi Guo wrote:
> ath10k_wmi_event_peer_sta_ps_state_chg() uses lockdep_assert_held() to
> assert that ar->data_lock should be held by the caller, but neither
> ath10k_wmi_10_2_op_rx() nor ath10k_wmi_10_4_op_rx() acquire this lock
> before calling this function.
> 
> The field arsta->peer_ps_state is documented as protected by
> ar->data_lock in core.h, and other accessors (ath10k_peer_ps_state_disable,
> ath10k_dbg_sta_read_peer_ps_state) properly acquire this lock.

there is another instance in ath10k_sta_state() where the lock is not acquired, but I
guess that is OK since during the NOTEXIST -> NONE transition no race is expected.

> 
> Add spin_lock_bh()/spin_unlock_bh() around the peer_ps_state update,
> and remove the lockdep_assert_held() to be aligned with new locking,
> following the pattern used by other WMI event handlers in the driver.
> 
> Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
> ---
> v2:
>  - Remove lockdep_assert_held() as suggested, since
>    we are now taking the lock internally.
> 
>  drivers/net/wireless/ath/ath10k/wmi.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
> index b4aad6604d6d..061a2fa8f00f 100644
> --- a/drivers/net/wireless/ath/ath10k/wmi.c
> +++ b/drivers/net/wireless/ath/ath10k/wmi.c
> @@ -5289,7 +5289,6 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb)
>  	struct ath10k_sta *arsta;
>  	u8 peer_addr[ETH_ALEN];
>  
> -	lockdep_assert_held(&ar->data_lock);
>  
>  	ev = (struct wmi_peer_sta_ps_state_chg_event *)skb->data;
>  	ether_addr_copy(peer_addr, ev->peer_macaddr.addr);
> @@ -5305,7 +5304,9 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb)
>  	}
>  
>  	arsta = (struct ath10k_sta *)sta->drv_priv;
> +	spin_lock_bh(&ar->data_lock);
>  	arsta->peer_ps_state = __le32_to_cpu(ev->peer_ps_state);
> +	spin_unlock_bh(&ar->data_lock);
>  
>  exit:
>  	rcu_read_unlock();

Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>


^ permalink raw reply

* [PATCH] Revert "wifi: iwlwifi: trans: remove STATUS_SUSPENDED"
From: Chris Bainbridge @ 2026-01-25 23:33 UTC (permalink / raw)
  To: miriam.rachel.korenblit, kvalo
  Cc: johannes.berg, benjamin, gustavoars, linux-intel-wifi,
	linux-wireless, netdev, linux-kernel, Chris Bainbridge, stable

This reverts commit e769f6f27ffe41331e00b69a33aa8a34db4dd830.

The removal of STATUS_SUSPENDED (which tracks suspend/resume state)
resulted in an intermittent race condition on resume. The fault can be
reproduced by carrying out repeated suspend/resume cycles while passing
traffic through the NIC. A typical failure looks like:

[  141.093986] iwlwifi 0000:01:00.0: Error sending SCAN_CFG_CMD: time out after 2000ms.
[  141.094057] iwlwifi 0000:01:00.0: Current CMD queue read_ptr 441 write_ptr 442
[  141.094864] iwlwifi 0000:01:00.0: Start IWL Error Log Dump:
[  141.094866] iwlwifi 0000:01:00.0: Transport status: 0x00000042, valid: 6
[  141.094870] iwlwifi 0000:01:00.0: Loaded firmware version: 89.7f71c7f4.0 ty-a0-gf-a0-89.ucode
[  141.094873] iwlwifi 0000:01:00.0: 0x01000071 | ADVANCED_SYSASSERT
...
[  141.098401] iwlwifi 0000:01:00.0: iwl_mvm_check_rt_status failed, device is gone during suspend

The kernel then oops due to a null pointer dereference in
iwl_mvm_realloc_queues_after_restart().

Fixes: e769f6f27ffe ("wifi: iwlwifi: trans: remove STATUS_SUSPENDED")
Closes: https://yhbt.net/lore/linux-wireless/aTDoDiD55qlUZ0pn@debian.local/
Cc: <stable@vger.kernel.org>
Signed-off-by: Chris Bainbridge <chris.bainbridge@gmail.com>
---
 .../net/wireless/intel/iwlwifi/iwl-trans.c    | 22 +++++++++++++++++--
 .../net/wireless/intel/iwlwifi/iwl-trans.h    |  3 +++
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index cc8a84018f70..f5c4aa165c5b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -306,6 +306,9 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 		     test_bit(STATUS_RFKILL_OPMODE, &trans->status)))
 		return -ERFKILL;
 
+	if (unlikely(test_bit(STATUS_SUSPENDED, &trans->status)))
+		return -EHOSTDOWN;
+
 	if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
 		return -EIO;
 
@@ -406,6 +409,8 @@ int iwl_trans_start_hw(struct iwl_trans *trans)
 	might_sleep();
 
 	clear_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status);
+	/* opmode may not resume if it detects errors */
+	clear_bit(STATUS_SUSPENDED, &trans->status);
 
 	return iwl_trans_pcie_start_hw(trans);
 }
@@ -505,17 +510,30 @@ iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
 
 int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset)
 {
+	int err;
+
 	might_sleep();
 
-	return iwl_trans_pcie_d3_suspend(trans, reset);
+	err = iwl_trans_pcie_d3_suspend(trans, reset);
+
+	if (!err)
+		set_bit(STATUS_SUSPENDED, &trans->status);
+
+	return err;
 }
 IWL_EXPORT_SYMBOL(iwl_trans_d3_suspend);
 
 int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset)
 {
+	int err;
+
 	might_sleep();
 
-	return iwl_trans_pcie_d3_resume(trans, reset);
+	err = iwl_trans_pcie_d3_resume(trans, reset);
+
+	clear_bit(STATUS_SUSPENDED, &trans->status);
+
+	return err;
 }
 IWL_EXPORT_SYMBOL(iwl_trans_d3_resume);
 
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index a552669db6e2..c4d06a323f9b 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -290,6 +290,8 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
  *	the firmware state yet
  * @STATUS_TRANS_RESET_IN_PROGRESS: reset is still in progress, don't
  *	attempt another reset yet
+ * @STATUS_SUSPENDED: device is suspended, don't send commands that
+ *	aren't marked accordingly
  */
 enum iwl_trans_status {
 	STATUS_SYNC_HCMD_ACTIVE,
@@ -303,6 +305,7 @@ enum iwl_trans_status {
 	STATUS_IN_SW_RESET,
 	STATUS_RESET_PENDING,
 	STATUS_TRANS_RESET_IN_PROGRESS,
+	STATUS_SUSPENDED,
 };
 
 static inline int
-- 
2.47.3


^ permalink raw reply related

* [PATCH] wifi: mt76: connac: fix txpower_cur not being updated
From: Lucid Duck @ 2026-01-25 22:22 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Lucid Duck

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


^ permalink raw reply related

* [PATCH] wifi: rtw89: usb: fix TX flow control by tracking in-flight URBs
From: Lucid Duck @ 2026-01-25 22:19 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ping-Ke Shih, Lucid Duck

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)
+		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];
 };
 
 static inline struct rtw89_usb *rtw89_usb_priv(struct rtw89_dev *rtwdev)
-- 
2.52.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