All of lore.kernel.org
 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: 35+ 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-07  4:45   ` Zhi-Jun You
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-09 13:40     ` Johannes Berg
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.