summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2016-01-13 16:52:52 +0300
committerKalle Valo <kvalo@qca.qualcomm.com>2016-01-21 14:50:29 +0300
commitd742c969b3ad9c83ac57579dfd56c90dd437db37 (patch)
treea95f38fa4a0eabdd72a40ab535008b1f32619757
parenta365e668e89d50230737ec20d43fe8fe18412730 (diff)
downloadlinux-d742c969b3ad9c83ac57579dfd56c90dd437db37.tar.xz
ath10k: prevent txrx running for too long
On multicore systems it was possible for the txrx tasklet to keep on running for long periods of time on a single CPU due to tx completion processing. Another CPU could feed the running tasklet for an indefinite amount of time. The tasklet is now guaranteed to run a finite amount of time and is limited by HTT CE Rx ring depth. This improves behavior when RPS is used on target system and might improve TCP handling as well. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 91afa3ae414c..3079434b5d9b 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2156,10 +2156,18 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
{
struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
struct ath10k *ar = htt->ar;
+ struct sk_buff_head tx_q;
struct htt_resp *resp;
struct sk_buff *skb;
+ unsigned long flags;
- while ((skb = skb_dequeue(&htt->tx_compl_q))) {
+ __skb_queue_head_init(&tx_q);
+
+ spin_lock_irqsave(&htt->tx_compl_q.lock, flags);
+ skb_queue_splice_init(&htt->tx_compl_q, &tx_q);
+ spin_unlock_irqrestore(&htt->tx_compl_q.lock, flags);
+
+ while ((skb = __skb_dequeue(&tx_q))) {
ath10k_htt_rx_frm_tx_compl(htt->ar, skb);
dev_kfree_skb_any(skb);
}