There were cases where we'd run out of msdu_ids. This can be fixed by telling mac80211 to stop sending us more frames if we run out of resources.
It was possible to trigger with massive TCP RX ~300mbps (e.g. using iperf). Signed-off-by: Michal Kazior <michal.kaz...@tieto.com> --- drivers/net/wireless/ath/ath10k/htt.h | 2 ++ drivers/net/wireless/ath/ath10k/htt_tx.c | 46 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/txrx.c | 1 + 3 files changed, 49 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 85de0b3..8ae1f03 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1262,6 +1262,7 @@ struct ath10k_htt { /* Protects access to %pending_tx, %used_msdu_ids */ spinlock_t tx_lock; + int num_pending_tx; struct sk_buff *pending_tx[HTT_MAX_NUM_PENDING_TX]; DECLARE_BITMAP(used_msdu_ids, HTT_MAX_NUM_PENDING_TX); wait_queue_head_t empty_tx_wq; @@ -1330,6 +1331,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); +void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt); void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 21add5d..7dd366f 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -18,9 +18,44 @@ #include <linux/etherdevice.h> #include "htt.h" #include "mac.h" +#include "hif.h" #include "txrx.h" #include "debug.h" +void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) +{ + htt->num_pending_tx--; + if (htt->num_pending_tx == HTT_MAX_NUM_PENDING_TX - 1) + ieee80211_wake_queues(htt->ar->hw); +} + +static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) +{ + spin_lock_bh(&htt->tx_lock); + __ath10k_htt_tx_dec_pending(htt); + spin_unlock_bh(&htt->tx_lock); +} + +static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) +{ + int ret = 0; + + spin_lock_bh(&htt->tx_lock); + + if (htt->num_pending_tx >= HTT_MAX_NUM_PENDING_TX) { + ret = -EBUSY; + goto exit; + } + + htt->num_pending_tx++; + if (htt->num_pending_tx == HTT_MAX_NUM_PENDING_TX) + ieee80211_stop_queues(htt->ar->hw); + +exit: + spin_unlock_bh(&htt->tx_lock); + return ret; +} + int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt) { int msdu_id; @@ -238,6 +273,11 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int msdu_id = -1; int res; + + res = ath10k_htt_tx_inc_pending(htt); + if (res) + return res; + len += sizeof(cmd->hdr); len += sizeof(cmd->mgmt_tx); @@ -295,6 +335,7 @@ err: ath10k_htt_tx_free_msdu_id(htt, msdu_id); spin_unlock_bh(&htt->tx_lock); } + ath10k_htt_tx_dec_pending(htt); return res; } @@ -316,6 +357,10 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) u8 flags0; u16 flags1; + res = ath10k_htt_tx_inc_pending(htt); + if (res) + return res; + prefetch_len = min(htt->prefetch_len, msdu->len); prefetch_len = roundup(prefetch_len, 4); @@ -431,6 +476,7 @@ err: ath10k_htt_tx_free_msdu_id(htt, msdu_id); spin_unlock_bh(&htt->tx_lock); } + ath10k_htt_tx_dec_pending(htt); ath10k_skb_unmap(dev, msdu); return res; } diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index a32448c..ce44ab1 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -95,6 +95,7 @@ exit: spin_lock_bh(&htt->tx_lock); htt->pending_tx[ATH10K_SKB_CB(txdesc)->htt.msdu_id] = NULL; ath10k_htt_tx_free_msdu_id(htt, ATH10K_SKB_CB(txdesc)->htt.msdu_id); + __ath10k_htt_tx_dec_pending(htt); if (bitmap_empty(htt->used_msdu_ids, HTT_MAX_NUM_PENDING_TX)) wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); -- 1.7.9.5 _______________________________________________ ath9k-devel mailing list ath9k-devel@lists.ath9k.org https://lists.ath9k.org/mailman/listinfo/ath9k-devel