Linux wireless drivers development
 help / color / mirror / Atom feed
From: "Toke Høiland-Jørgensen" <toke@toke.dk>
To: Johannes Berg <johannes@sipsolutions.net>,
	linux-wireless@vger.kernel.org
Cc: Johannes Berg <johannes.berg@intel.com>
Subject: Re: [PATCH 13/30] wifi: mac80211: don't apply CoDel to PS-buffered frames
Date: Fri, 06 Nov 2026 13:22:42 +0100	[thread overview]
Message-ID: <87cxsip2st.fsf@toke.dk> (raw)
In-Reply-To: <20261102203831.1058362-45-johannes@sipsolutions.net>

Johannes Berg <johannes@sipsolutions.net> writes:

> From: Johannes Berg <johannes.berg@intel.com>
>
> Frames for sleeping stations remain on the TXQs now, applying
> CoDel to them would start dropping them due to a long wait on
> dequeue, but for PS STAs they will be on the queues for a while.
> Bypass CoDel while a STA is sleeping and for a while (10s) or
> when the queue drains after it wakes up, and for frames that
> were enqueued after the wakeup as well, which really is the
> common case.
>
> Assisted-by: LLM
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>  net/mac80211/ieee80211_i.h |  7 +++++
>  net/mac80211/sta_info.c    |  6 ++++-
>  net/mac80211/tx.c          | 52 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 64 insertions(+), 1 deletion(-)
>
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index 5045144641a4..cb947341fee6 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -978,6 +978,7 @@ enum txq_info_flags {
>  	IEEE80211_TXQ_AMPDU,
>  	IEEE80211_TXQ_NO_AMSDU,
>  	IEEE80211_TXQ_DIRTY,
> +	IEEE80211_TXQ_PS_BACKLOG,
>  };
>  
>  /**
> @@ -990,6 +991,9 @@ enum txq_info_flags {
>   * @schedule_order: used with ieee80211_local->active_txqs
>   * @schedule_round: counter to prevent infinite loops on TXQ scheduling
>   * @flags: TXQ flags from &enum txq_info_flags
> + * @ps_backlog_end: with %IEEE80211_TXQ_PS_BACKLOG, indicates when
> + *	the station woke up, i.e. frames before this were just queued
> + *	due to powersave
>   * @txq: the driver visible part
>   */
>  struct txq_info {
> @@ -1003,6 +1007,7 @@ struct txq_info {
>  	struct sk_buff_head frags;
>  
>  	unsigned long flags;
> +	codel_time_t ps_backlog_end;
>  
>  	/* keep last! */
>  	struct ieee80211_txq txq;
> @@ -2724,6 +2729,8 @@ void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
>  			struct txq_info *txq, int tid);
>  struct sk_buff *ieee80211_tx_dequeue_ps_release(struct ieee80211_local *local,
>  						struct txq_info *txqi);
> +void ieee80211_txq_ps_backlog_start(struct ieee80211_local *local,
> +				    struct txq_info *txqi);

The variable above is called ps_backlog_end, the function is called
ps_backlog_start. Seems a tad confusing? :)


>  void ieee80211_txq_purge(struct ieee80211_local *local,
>  			 struct txq_info *txqi);
>  void ieee80211_purge_sta_txqs(struct sta_info *sta);
> diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
> index 51504f57128f..8d79e532b109 100644
> --- a/net/mac80211/sta_info.c
> +++ b/net/mac80211/sta_info.c
> @@ -1889,10 +1889,14 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
>  	/* this can be called in process context, e.g. for mesh */
>  	local_bh_disable();
>  	for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
> +		struct txq_info *txqi;
> +
>  		if (!sta->sta.txq[i] || !txq_has_queue(sta->sta.txq[i]))
>  			continue;
>  
> -		schedule_and_wake_txq(local, to_txq_info(sta->sta.txq[i]));
> +		txqi = to_txq_info(sta->sta.txq[i]);
> +		ieee80211_txq_ps_backlog_start(local, txqi);
> +		schedule_and_wake_txq(local, txqi);
>  	}
>  	local_bh_enable();
>  
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> index 0bd324a4d4cb..856018cdb617 100644
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
> @@ -1380,6 +1380,55 @@ static void codel_drop_func(struct sk_buff *skb,
>  	ieee80211_free_txskb(hw, skb);
>  }
>  
> +/* bypass codel since PS can last a long time */
> +static bool ieee80211_txq_codel_bypass(struct txq_info *txqi,
> +				       const struct fq_flow *flow)
> +{
> +	struct sta_info *sta;
> +	struct sk_buff *skb;
> +
> +	if (!txqi->txq.sta)
> +		return false;
> +
> +	sta = container_of(txqi->txq.sta, struct sta_info, sta);
> +	if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
> +	    test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
> +	    test_sta_flag(sta, WLAN_STA_PS_DELIVER))
> +		return true;
> +
> +	if (likely(!test_bit(IEEE80211_TXQ_PS_BACKLOG, &txqi->flags)))
> +		return false;
> +
> +	/*
> +	 * Stop treating as backlog after it cleared or after 1s
> +	 * (the latter to avoid time wrap and issues from that).
> +	 */
> +#define IEEE80211_TXQ_MAX_PS_BACKLOG	MS2TIME(MSEC_PER_SEC)
> +
> +	if (!txqi->tin.backlog_packets ||
> +	    codel_time_after(codel_get_time(),
> +			     (codel_time_t)(txqi->ps_backlog_end +
> +					    IEEE80211_TXQ_MAX_PS_BACKLOG))) {
> +		clear_bit(IEEE80211_TXQ_PS_BACKLOG, &txqi->flags);
> +		return false;
> +	}
> +
> +	skb = skb_peek(&flow->queue);
> +	return skb && codel_time_before(codel_skb_time_func(skb),
> +					txqi->ps_backlog_end);
> +}
> +
> +void ieee80211_txq_ps_backlog_start(struct ieee80211_local *local,
> +				    struct txq_info *txqi)
> +{
> +	spin_lock_bh(&local->fq.lock);
> +	if (txqi->tin.backlog_packets) {
> +		txqi->ps_backlog_end = codel_get_time();
> +		set_bit(IEEE80211_TXQ_PS_BACKLOG, &txqi->flags);

We should probably clear the codel variables here as well? Otherwise, if
CoDel was already in a dropping state when this happens, that can carry
over to after the bypass ends.

-Toke

  reply	other threads:[~2026-11-06 12:22 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02 20:22 [PATCH 00/30] wifi: mac80211: unify frame queueing Johannes Berg
2026-11-02 20:22 ` [PATCH 01/30] wifi: mac80211: mesh: clear PS_STA flag when peer wakes up Johannes Berg
2026-11-02 20:22 ` [PATCH 02/30] wifi: mac80211: disable BHs when waking TXQs on PS wakeup Johannes Berg
2026-11-02 20:22 ` [PATCH 03/30] wifi: mt76: correctly set more-data flag on PS release Johannes Berg
2026-11-02 20:22 ` [PATCH 04/30] wifi: mac80211: remove dead aggregation TX code Johannes Berg
2026-11-02 20:22 ` [PATCH 05/30] wifi: mac80211: remove tid_tx->pending Johannes Berg
2026-11-02 20:22 ` [PATCH 06/30] wifi: mac80211: remove aggregation queue stop reason Johannes Berg
2026-11-02 20:22 ` [PATCH 07/30] wifi: mac80211: rename vif->txq_mgmt to vif->txq_nan_dw Johannes Berg
2026-11-02 20:22 ` [PATCH 08/30] wifi: mac80211: use vlan-aware station lookup for pending TX Johannes Berg
2026-11-02 20:22 ` [PATCH 09/30] wifi: mac80211: stop tracking TXQ-buffered TIDs for PS STAs Johannes Berg
2026-11-02 20:23 ` [PATCH 10/30] wifi: mac80211: release frames from TXQs to PS stations Johannes Berg
2026-11-02 20:23 ` [PATCH 11/30] wifi: mac80211: mesh: release frames from TXQs sleeping peers Johannes Berg
2026-11-02 20:23 ` [PATCH 12/30] wifi: mac80211: don't TX from TXQs of sleeping STAs Johannes Berg
2026-11-02 20:23 ` [PATCH 13/30] wifi: mac80211: don't apply CoDel to PS-buffered frames Johannes Berg
2026-11-06 12:22   ` Toke Høiland-Jørgensen [this message]
2026-11-02 20:23 ` [PATCH 14/30] wifi: mac80211: put filtered data frames back on TXQs Johannes Berg
2026-11-06 12:23   ` Toke Høiland-Jørgensen
2026-11-02 20:23 ` [PATCH 15/30] wifi: mac80211: handle the mgmt TXQ of sleeping STAs Johannes Berg
2026-11-02 20:23 ` [PATCH 16/30] wifi: mac80211: hold frames for sleeping STAs on TXQs Johannes Berg
2026-11-02 20:23 ` [PATCH 17/30] wifi: mac80211: move ieee80211_txq_enqueue() up Johannes Berg
2026-11-02 20:23 ` [PATCH 18/30] wifi: mac80211: always use per-STA MMPDU TXQ Johannes Berg
2026-11-02 20:23 ` [PATCH 19/30] wifi: mac80211: use MMPDU TXQ for filtered mgmt frames Johannes Berg
2026-11-02 20:23 ` [PATCH 20/30] wifi: mac80211: avoid reordering PS-release MMPDUs Johannes Berg
2026-11-02 20:23 ` [PATCH 21/30] wifi: mac80211: buffer multicast frames on vif TXQ Johannes Berg
2026-11-02 20:23 ` [PATCH 22/30] wifi: mac80211: always use TXQ for mcast data frames Johannes Berg
2026-11-02 20:23 ` [PATCH 23/30] wifi: mac80211: refactor fast-xmit header encapsulation Johannes Berg
2026-11-02 20:23 ` [PATCH 24/30] wifi: mac80211: encapsulate fast-xmit frames at TXQ dequeue Johannes Berg
2026-11-02 20:23 ` [PATCH 25/30] net/fq_impl: allow pulling packets from the same flow Johannes Berg
2026-11-02 20:23 ` [PATCH 26/30] wifi: mac80211: build A-MSDUs at dequeue Johannes Berg
2026-11-02 20:23 ` [PATCH 27/30] wifi: mac80211: handle 802.11 encap at TXQ dequeue Johannes Berg
2026-11-02 20:23 ` [PATCH 28/30] wifi: mac80211: split some TX code into helpers Johannes Berg
2026-11-02 20:23 ` [PATCH 29/30] wifi: mac80211: queue unicast data frames as ethernet Johannes Berg
2026-11-02 20:23 ` [PATCH 30/30] wifi: mac80211: keep fast-xmit for sleeping STAs Johannes Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87cxsip2st.fsf@toke.dk \
    --to=toke@toke.dk \
    --cc=johannes.berg@intel.com \
    --cc=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox