diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00')
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 9 | ||||
| -rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 3 |
3 files changed, 17 insertions, 1 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index d2a1ea98d0f2..fd356b7c0476 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 | } |
| 434 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); | 438 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); |
| 435 | 439 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index ede3c58e6783..2df2eb6d3e06 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 5adfb3eab9cd..9b1b2b7a7807 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))) { |
