* [PATCH] wifi: mac80211: queue frames while off-channel
@ 2026-08-20 13:12 Stanislaw Gruszka
2026-09-04 6:56 ` Johannes Berg
0 siblings, 1 reply; 3+ messages in thread
From: Stanislaw Gruszka @ 2026-08-20 13:12 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
Drivers without FAST_XMIT and hardware scan support currently drop TX
frames during software scanning while being off-channel. This happens
in ieee80211_tx_h_check_assoc() before frames reach internal TX queue.
Move the off-channel check to invoke_tx_handlers_late(), after
ieee80211_queue_skb(). Frames can then remain queued and be transmitted
when the interface returns on-channel. This is how TX works currently when
code goes via ieee80211_xmit_fast() path.
Below is rt2x00 driver ping output example while scanning, before and
after the fix. After the fix, packets are no longer lost. Some have
increased latency, what is expected behavior.
BEFORE:
64 bytes from 192.168.0.1: icmp_seq=29 ttl=64 time=3.61 ms
64 bytes from 192.168.0.1: icmp_seq=31 ttl=64 time=3.33 ms # Missed 30
64 bytes from 192.168.0.1: icmp_seq=32 ttl=64 time=4.03 ms
64 bytes from 192.168.0.1: icmp_seq=34 ttl=64 time=3.10 ms # Missed 33
64 bytes from 192.168.0.1: icmp_seq=36 ttl=64 time=3.04 ms # Missed 35
64 bytes from 192.168.0.1: icmp_seq=38 ttl=64 time=3.05 ms # Missed 37
64 bytes from 192.168.0.1: icmp_seq=40 ttl=64 time=4.14 ms # Missed 39
64 bytes from 192.168.0.1: icmp_seq=41 ttl=64 time=4.50 ms
AFTER:
64 bytes from 192.168.0.1: icmp_seq=29 ttl=64 time=3.40 ms
64 bytes from 192.168.0.1: icmp_seq=30 ttl=64 time=6.10 ms
64 bytes from 192.168.0.1: icmp_seq=31 ttl=64 time=4.69 ms
64 bytes from 192.168.0.1: icmp_seq=32 ttl=64 time=4.49 ms
64 bytes from 192.168.0.1: icmp_seq=33 ttl=64 time=148 ms
64 bytes from 192.168.0.1: icmp_seq=34 ttl=64 time=6.83 ms
64 bytes from 192.168.0.1: icmp_seq=35 ttl=64 time=8.66 ms
64 bytes from 192.168.0.1: icmp_seq=36 ttl=64 time=13.0 ms
64 bytes from 192.168.0.1: icmp_seq=37 ttl=64 time=4.78 ms
64 bytes from 192.168.0.1: icmp_seq=38 ttl=64 time=3.85 ms
The change depends on the iTXQ resumption handling introduced by
commit 4444bc2116ae ("wifi: mac80211: Proper mark iTXQs for resumption")
and the wake_tx_queue support introduced by
commit a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to drivers"),
so use those in 'Fixes' tag.
Cc: <stable@vger.kernel.org> # v6.2
Fixes: a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to drivers")
Fixes: 4444bc2116ae ("wifi: mac80211: Proper mark iTXQs for resumption")
Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
---
net/mac80211/tx.c | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 91b14112e24f..842368cc45dc 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -267,20 +267,14 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
}
static ieee80211_tx_result debug_noinline
-ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
+ieee80211_tx_h_check_offchannel(struct ieee80211_tx_data *tx)
{
-
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
- bool assoc = false;
-
- if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
- return TX_CONTINUE;
if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
!ieee80211_is_probe_req(hdr->frame_control) &&
- !ieee80211_is_any_nullfunc(hdr->frame_control))
+ !ieee80211_is_any_nullfunc(hdr->frame_control)) {
/*
* When software scanning only nullfunc frames (to notify
* the sleep state to the AP) and probe requests (for the
@@ -290,6 +284,20 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
* off-channel. See __ieee80211_start_scan() for more.
*/
return TX_DROP;
+ }
+
+ return TX_CONTINUE;
+}
+
+static ieee80211_tx_result debug_noinline
+ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+ bool assoc = false;
+
+ if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
+ return TX_CONTINUE;
if (tx->sdata->vif.type == NL80211_IFTYPE_OCB)
return TX_CONTINUE;
@@ -1864,6 +1872,7 @@ static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx)
goto txh_done;
}
+ CALL_TXH(ieee80211_tx_h_check_offchannel);
CALL_TXH(ieee80211_tx_h_michael_mic_add);
CALL_TXH(ieee80211_tx_h_sequence);
CALL_TXH(ieee80211_tx_h_fragment);
@@ -4686,10 +4695,6 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
queue = ieee80211_select_queue(sdata, sta, skb);
skb_set_queue_mapping(skb, queue);
- if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
- test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
- goto out_free;
-
skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb))
return;
@@ -4756,11 +4761,6 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
ieee80211_tpt_led_trig_tx(local, len);
ieee80211_tx_8023(sdata, skb, sta, false);
-
- return;
-
-out_free:
- kfree_skb(skb);
}
static bool ieee80211_check_mcast_offload(struct ieee80211_sub_if_data *sdata,
--
2.50.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] wifi: mac80211: queue frames while off-channel
2026-08-20 13:12 [PATCH] wifi: mac80211: queue frames while off-channel Stanislaw Gruszka
@ 2026-09-04 6:56 ` Johannes Berg
2026-09-04 7:29 ` Stanislaw Gruszka
0 siblings, 1 reply; 3+ messages in thread
From: Johannes Berg @ 2026-09-04 6:56 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: linux-wireless
On Thu, 2026-08-20 at 15:12 +0200, Stanislaw Gruszka wrote:
>
> The change depends on the iTXQ resumption handling introduced by
> commit 4444bc2116ae ("wifi: mac80211: Proper mark iTXQs for resumption")
> and the wake_tx_queue support introduced by
> commit a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to drivers"),
> so use those in 'Fixes' tag.
That doesn't really make any sense, IMHO.
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -267,20 +267,14 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
> }
>
> static ieee80211_tx_result debug_noinline
> -ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
> +ieee80211_tx_h_check_offchannel(struct ieee80211_tx_data *tx)
I (vaguely?) had these ordered by execution order, might make sense to
move around and try to keep that.
> {
> -
> struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
> - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
> - bool assoc = false;
> -
> - if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
> - return TX_CONTINUE;
Not sure you should remove that, still you want injection to go out?
Not sure injection should even be queued - maybe you do want to send
while scanning on a random channel? Or maybe not? Maybe someone depends
on that behaviour? Or maybe not? Kinda hard to say...
johannes
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] wifi: mac80211: queue frames while off-channel
2026-09-04 6:56 ` Johannes Berg
@ 2026-09-04 7:29 ` Stanislaw Gruszka
0 siblings, 0 replies; 3+ messages in thread
From: Stanislaw Gruszka @ 2026-09-04 7:29 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On Fri, Sep 04, 2026 at 08:56:13AM +0200, Johannes Berg wrote:
> On Thu, 2026-08-20 at 15:12 +0200, Stanislaw Gruszka wrote:
> >
> > The change depends on the iTXQ resumption handling introduced by
> > commit 4444bc2116ae ("wifi: mac80211: Proper mark iTXQs for resumption")
> > and the wake_tx_queue support introduced by
> > commit a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to drivers"),
> > so use those in 'Fixes' tag.
>
> That doesn't really make any sense, IMHO.
Going to drop those 'Fixes:' tags and comment. but I don't know
what the tag should be then.
I saw in docs that 'Fixes:' is required for -stable submissions
for net tree, but maybe I could just skip it for mac80211?
> > --- a/net/mac80211/tx.c
> > +++ b/net/mac80211/tx.c
> > @@ -267,20 +267,14 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
> > }
> >
> > static ieee80211_tx_result debug_noinline
> > -ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
> > +ieee80211_tx_h_check_offchannel(struct ieee80211_tx_data *tx)
>
> I (vaguely?) had these ordered by execution order, might make sense to
> move around and try to keep that.
Ok, will move.
> > {
> > -
> > struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
> > - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
> > - bool assoc = false;
> > -
> > - if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
> > - return TX_CONTINUE;
>
>
> Not sure you should remove that, still you want injection to go out?
>
> Not sure injection should even be queued - maybe you do want to send
> while scanning on a random channel? Or maybe not? Maybe someone depends
> on that behaviour? Or maybe not? Kinda hard to say...
I will keep it v2, change indeed could cause regression for someone.
Regards
Stanislaw
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-04 7:35 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 13:12 [PATCH] wifi: mac80211: queue frames while off-channel Stanislaw Gruszka
2026-09-04 6:56 ` Johannes Berg
2026-09-04 7:29 ` Stanislaw Gruszka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox