aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c3
3 files changed, 17 insertions, 1 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index d2a1ea98d0f..fd356b7c047 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -426,10 +426,14 @@ void rt2x00lib_txdone(struct queue_entry *entry,
426 /* 426 /*
427 * If the data queue was below the threshold before the txdone 427 * If the data queue was below the threshold before the txdone
428 * handler we must make sure the packet queue in the mac80211 stack 428 * handler we must make sure the packet queue in the mac80211 stack
429 * is reenabled when the txdone handler has finished. 429 * is reenabled when the txdone handler has finished. This has to be
430 * serialized with rt2x00mac_tx(), otherwise we can wake up queue
431 * before it was stopped.
430 */ 432 */
433 spin_lock_bh(&entry->queue->tx_lock);
431 if (!rt2x00queue_threshold(entry->queue)) 434 if (!rt2x00queue_threshold(entry->queue))
432 rt2x00queue_unpause_queue(entry->queue); 435 rt2x00queue_unpause_queue(entry->queue);
436 spin_unlock_bh(&entry->queue->tx_lock);
433} 437}
434EXPORT_SYMBOL_GPL(rt2x00lib_txdone); 438EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
435 439
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index ede3c58e678..2df2eb6d3e0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -152,13 +152,22 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
152 if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false))) 152 if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false)))
153 goto exit_fail; 153 goto exit_fail;
154 154
155 /*
156 * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
157 * we should not use spin_lock_bh variant as bottom halve was already
158 * disabled before ieee80211_xmit() call.
159 */
160 spin_lock(&queue->tx_lock);
155 if (rt2x00queue_threshold(queue)) 161 if (rt2x00queue_threshold(queue))
156 rt2x00queue_pause_queue(queue); 162 rt2x00queue_pause_queue(queue);
163 spin_unlock(&queue->tx_lock);
157 164
158 return; 165 return;
159 166
160 exit_fail: 167 exit_fail:
168 spin_lock(&queue->tx_lock);
161 rt2x00queue_pause_queue(queue); 169 rt2x00queue_pause_queue(queue);
170 spin_unlock(&queue->tx_lock);
162 exit_free_skb: 171 exit_free_skb:
163 ieee80211_free_txskb(hw, skb); 172 ieee80211_free_txskb(hw, skb);
164} 173}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 5adfb3eab9c..9b1b2b7a780 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -619,6 +619,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
619 else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags)) 619 else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
620 rt2x00queue_align_frame(skb); 620 rt2x00queue_align_frame(skb);
621 621
622 /*
623 * That function must be called with bh disabled.
624 */
622 spin_lock(&queue->tx_lock); 625 spin_lock(&queue->tx_lock);
623 626
624 if (unlikely(rt2x00queue_full(queue))) { 627 if (unlikely(rt2x00queue_full(queue))) {