rt2x00: merge a fix for random tx stalls
authorFelix Fietkau <nbd@openwrt.org>
Sat, 10 Mar 2012 13:31:34 +0000 (13:31 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 10 Mar 2012 13:31:34 +0000 (13:31 +0000)
SVN-Revision: 30871

package/mac80211/patches/300-pending_work.patch
package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch

index 25d3b1744154fcee889a94db2e8c586a9e879763..30ce96e1703b96e278b85c3e0bc3918e16e86285 100644 (file)
  
                if (on)
                        REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -430,10 +430,14 @@ void rt2x00lib_txdone(struct queue_entry
+       /*
+        * If the data queue was below the threshold before the txdone
+        * handler we must make sure the packet queue in the mac80211 stack
+-       * is reenabled when the txdone handler has finished.
++       * is reenabled when the txdone handler has finished. This has to be
++       * serialized with rt2x00mac_tx(), otherwise we can wake up queue
++       * before it was stopped.
+        */
++      spin_lock_bh(&entry->queue->tx_lock);
+       if (!rt2x00queue_threshold(entry->queue))
+               rt2x00queue_unpause_queue(entry->queue);
++      spin_unlock_bh(&entry->queue->tx_lock);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
+--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
++++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
+@@ -152,13 +152,22 @@ void rt2x00mac_tx(struct ieee80211_hw *h
+       if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false)))
+               goto exit_fail;
++      /*
++       * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
++       * we should not use spin_lock_bh variant as bottom halve was already
++       * disabled before ieee80211_xmit() call.
++       */
++      spin_lock(&queue->tx_lock);
+       if (rt2x00queue_threshold(queue))
+               rt2x00queue_pause_queue(queue);
++      spin_unlock(&queue->tx_lock);
+       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);
+ }
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -619,6 +619,9 @@ int rt2x00queue_write_tx_frame(struct da
+       else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
+               rt2x00queue_align_frame(skb);
++      /*
++       * That function must be called with bh disabled.
++       */
+       spin_lock(&queue->tx_lock);
+       if (unlikely(rt2x00queue_full(queue))) {
index 31e33b7818da4ec6237130cd6dcb473da0d23dbc..e40d3a9342e5b0ba922a404383f9db9350325c6e 100644 (file)
        .get_entry_state        = rt2800pci_get_entry_state,
 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
 +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -1161,6 +1161,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+@@ -1165,6 +1165,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
                    BIT(NL80211_IFTYPE_MESH_POINT) |
                    BIT(NL80211_IFTYPE_WDS);
  
        /*
         * Initialize work.
         */
-@@ -1284,6 +1288,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
+@@ -1288,6 +1292,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
         */
        if (rt2x00dev->drv_data)
                kfree(rt2x00dev->drv_data);
index 9056076bd4bd1355a4ccf1df7dba03ed3da3bd80..476f730116b1ba7e52229c866f904cbc5c7cc385 100644 (file)
@@ -12,7 +12,7 @@
  #endif /* _RT2X00_PLATFORM_H */
 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
 +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -829,6 +829,22 @@ static int rt2x00lib_probe_hw_modes(stru
+@@ -833,6 +833,22 @@ static int rt2x00lib_probe_hw_modes(stru
        unsigned int num_rates;
        unsigned int i;