[PATCH ath-next v3 6/9] wifi: ath11k: run the TXQ scheduler on tx completion
Julius Bairaktaris <[email protected]>
| Newsgroups | org.infradead.lists.ath11k,org.kernel.vger.linux-kernel,org.kernel.vger.linux-wireless |
|---|---|
| Message-ID | <[email protected]> |
A station whose airtime queue limit is reached stops being served by ieee80211_tx_dequeue(), and the airtime it is waiting on is only returned when the hardware completes the frames already charged to it. ath11k starts a scheduling round only where mac80211 calls the wake_tx_queue callback, so once the limit binds, the backlog moves again only when one of those events comes round: most often the next frame from the network stack. Under a saturated download the arrivals keep the round running; a flow that has just filled the intermediate queue, or one whose sender is waiting on the acknowledgements behind that queue, stalls for as long as it takes the next arrival to appear. Start a round for every radio whose completions were reaped, at the point where the airtime has been returned. The airtime queue limit then bounds a queue that is refilled as it drains, rather than one that is refilled when the network stack happens to push. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1 Assisted-by: Claude:claude-opus-5 Signed-off-by: Julius Bairaktaris <[email protected]> --- drivers/net/wireless/ath/ath11k/dp_tx.c | 12 +++++++++++- drivers/net/wireless/ath/ath11k/mac.c | 10 ++++++++++ drivers/net/wireless/ath/ath11k/mac.h | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index 52c4a9924a31..e706ba1077eb 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -694,9 +694,10 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id) struct sk_buff *msdu; struct hal_tx_status ts = {}; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; + unsigned long push = 0; u32 *desc; u32 msdu_id; - u8 mac_id; + u8 mac_id, i; spin_lock_bh(&status_ring->lock); @@ -756,12 +757,21 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id) spin_unlock(&tx_ring->tx_idr_lock); ar = ab->pdevs[mac_id].ar; + __set_bit(mac_id, &push); if (atomic_dec_and_test(&ar->dp.num_tx_pending)) wake_up(&ar->dp.tx_empty_waitq); ath11k_dp_tx_complete_msdu(ar, msdu, &ts); } + + /* A completion returns the airtime the frame was charged, which is + * what an airtime-limited station is waiting on. The arrivals that + * would otherwise start a round are themselves queued behind that + * limit. + */ + for_each_set_bit(i, &push, ab->num_radios) + ath11k_mac_tx_push_pending(ab->pdevs[i].ar); } int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid, diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 342b38308468..150b3a1a9c19 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -6583,6 +6583,16 @@ static void ath11k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, ath11k_mac_schedule_txq(hw->priv, txq->ac); } +void ath11k_mac_tx_push_pending(struct ath11k *ar) +{ + u8 ac; + + rcu_read_lock(); + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) + ath11k_mac_schedule_txq(ar, ac); + rcu_read_unlock(); +} + void ath11k_mac_drain_tx(struct ath11k *ar) { /* make sure rcu-protected mac80211 tx path itself is drained */ diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index 59f83c7175fd..4012155dddb6 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -161,6 +161,7 @@ struct ath11k *ath11k_mac_get_ar_by_vdev_id(struct ath11k_base *ab, u32 vdev_id) struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id); void ath11k_mac_drain_tx(struct ath11k *ar); +void ath11k_mac_tx_push_pending(struct ath11k *ar); void ath11k_mac_peer_cleanup_all(struct ath11k *ar); int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); u8 ath11k_mac_bw_to_mac80211_bw(u8 bw); -- 2.53.0