|
@@ -142,22 +142,28 @@ void rt2x00mac_tx(struct ieee80211_hw *hw,
|
|
|
if (!rt2x00dev->ops->hw->set_rts_threshold &&
|
|
|
(tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
|
|
|
IEEE80211_TX_RC_USE_CTS_PROTECT))) {
|
|
|
- if (rt2x00queue_available(queue) <= 1)
|
|
|
- goto exit_fail;
|
|
|
+ if (rt2x00queue_available(queue) <= 1) {
|
|
|
+ /*
|
|
|
+ * Recheck for full queue under lock to avoid race
|
|
|
+ * conditions with rt2x00lib_txdone().
|
|
|
+ */
|
|
|
+ spin_lock(&queue->tx_lock);
|
|
|
+ if (rt2x00queue_threshold(queue))
|
|
|
+ rt2x00queue_pause_queue(queue);
|
|
|
+ spin_unlock(&queue->tx_lock);
|
|
|
+
|
|
|
+ goto exit_free_skb;
|
|
|
+ }
|
|
|
|
|
|
if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb))
|
|
|
- goto exit_fail;
|
|
|
+ goto exit_free_skb;
|
|
|
}
|
|
|
|
|
|
if (unlikely(rt2x00queue_write_tx_frame(queue, skb, control->sta, false)))
|
|
|
- goto exit_fail;
|
|
|
+ goto exit_free_skb;
|
|
|
|
|
|
return;
|
|
|
|
|
|
- exit_fail:
|
|
|
- spin_lock(&queue->tx_lock);
|
|
|
- rt2x00queue_pause_queue(queue);
|
|
|
- spin_unlock(&queue->tx_lock);
|
|
|
exit_free_skb:
|
|
|
ieee80211_free_txskb(hw, skb);
|
|
|
}
|