[PATCH ath-next v3 9/9] wifi: ath11k: budget the tx completion handler
Julius Bairaktaris <[email protected]>
| Newsgroups | org.kernel.vger.linux-wireless,org.infradead.lists.ath11k,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
ath11k_dp_service_srng() calls ath11k_dp_tx_completion_handler() without a budget and discards its result, while every receive block below it takes the NAPI budget as a bound and reports what it consumed. The handler drains the whole software status FIFO, which holds one entry short of the 32768-entry release ring, and each entry costs a DMA unmap, an idr removal, a peer lookup under the base lock and a call into ieee80211_tx_status_ext(). One poll can therefore run for as long as the hardware has completions to report, with the receive rings behind it waiting, and the scheduling round the handler now ends with adds to that. Bound the drain by the budget it is given and account for it the way the receive blocks do. No new constant is introduced: the bound is the NAPI weight the poll already carries, so a poll that spends it on completions returns and is rescheduled rather than running on. 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.c | 10 ++++++++-- drivers/net/wireless/ath/ath11k/dp_tx.c | 11 +++++++++-- drivers/net/wireless/ath/ath11k/dp_tx.h | 3 ++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c index f389b97acbdd..676440ee742a 100644 --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c @@ -781,8 +781,14 @@ int ath11k_dp_service_srng(struct ath11k_base *ab, for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) { if (BIT(ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num) & - ab->hw_params.ring_mask->tx[grp_id]) - ath11k_dp_tx_completion_handler(ab, i); + ab->hw_params.ring_mask->tx[grp_id]) { + work_done = + ath11k_dp_tx_completion_handler(ab, i, budget); + budget -= work_done; + tot_work_done += work_done; + if (budget <= 0) + goto done; + } } if (ab->hw_params.ring_mask->rx_err[grp_id]) { diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index e706ba1077eb..b309a97d6ad2 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -685,7 +685,8 @@ static inline void ath11k_dp_tx_status_parse(struct ath11k_base *ab, ts->rate_stats = 0; } -void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id) +int ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id, + int budget) { struct ath11k *ar; struct ath11k_dp *dp = &ab->dp; @@ -695,6 +696,7 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id) struct hal_tx_status ts = {}; struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; unsigned long push = 0; + int done = 0; u32 *desc; u32 msdu_id; u8 mac_id, i; @@ -723,10 +725,13 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id) spin_unlock_bh(&status_ring->lock); - while (ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_tail) != tx_ring->tx_status_head) { + while (done < budget && + ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_tail) != + tx_ring->tx_status_head) { struct hal_wbm_release_ring *tx_status; u32 desc_id; + done++; tx_ring->tx_status_tail = ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_tail); tx_status = &tx_ring->tx_status[tx_ring->tx_status_tail]; @@ -772,6 +777,8 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id) */ for_each_set_bit(i, &push, ab->num_radios) ath11k_mac_tx_push_pending(ab->pdevs[i].ar); + + return done; } 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/dp_tx.h b/drivers/net/wireless/ath/ath11k/dp_tx.h index 9303b5ba6e01..b5296cda73e3 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.h +++ b/drivers/net/wireless/ath/ath11k/dp_tx.h @@ -21,7 +21,8 @@ void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts); int ath11k_dp_tx_htt_h2t_ver_req_msg(struct ath11k_base *ab); int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, struct ath11k_sta *arsta, struct sk_buff *skb); -void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id); +int ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id, + int budget); int ath11k_dp_tx_send_reo_cmd(struct ath11k_base *ab, struct dp_rx_tid *rx_tid, enum hal_reo_cmd_type type, struct ath11k_hal_reo_cmd *cmd, -- 2.53.0