mac80211/rt2x00: add ieee80211_tx_status_ni()
authorJohannes Stezenbach <js@sig21.net>
Tue, 30 Nov 2010 15:49:23 +0000 (16:49 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 30 Nov 2010 18:53:46 +0000 (13:53 -0500)
All rt2x00 drivers except rt2800pci call ieee80211_tx_status() from
a workqueue, which causes "NOHZ: local_softirq_pending 08" messages.

To fix it, add ieee80211_tx_status_ni() similar to ieee80211_rx_ni()
which can be called from process context, and call it from
rt2x00lib_txdone().  For the rt2800pci special case a driver
flag is introduced.

Signed-off-by: Johannes Stezenbach <js@sig21.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00dev.c
include/net/mac80211.h

index 433c7f3ef837c901ec149905e3443fffd8a16b1f..b989b0d3ed499e9f7667f40094134d47ee87e6aa 100644 (file)
@@ -911,6 +911,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
        __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
        __set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags);
+       __set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags);
        if (!modparam_nohwcrypt)
                __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
        __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
index 0a55eeff871e80126c07616eac938087393f184e..e72117f3fdf59d2d6c9f134bc182854c9d2456db 100644 (file)
@@ -664,6 +664,7 @@ enum rt2x00_flags {
        DRIVER_REQUIRE_COPY_IV,
        DRIVER_REQUIRE_L2PAD,
        DRIVER_REQUIRE_TXSTATUS_FIFO,
+       DRIVER_REQUIRE_TASKLET_CONTEXT,
 
        /*
         * Driver features
index c879f9a7037c39a76a2d709e6de3f3aa901417f3..bd3afc92f4343af8b006bf5597136ceafb6312fb 100644 (file)
@@ -379,9 +379,12 @@ void rt2x00lib_txdone(struct queue_entry *entry,
         * through a mac80211 library call (RTS/CTS) then we should not
         * send the status report back.
         */
-       if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
-               ieee80211_tx_status(rt2x00dev->hw, entry->skb);
-       else
+       if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
+               if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags))
+                       ieee80211_tx_status(rt2x00dev->hw, entry->skb);
+               else
+                       ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
+       } else
                dev_kfree_skb_any(entry->skb);
 
        /*
index eaa4affd40cd79bf62b69e88ee49690bdb51f07e..e411cf87fb4152af0fe79bc7616eee34ca29dc38 100644 (file)
@@ -2055,8 +2055,8 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,
  *
  * This function may not be called in IRQ context. Calls to this function
  * for a single hardware must be synchronized against each other. Calls
- * to this function and ieee80211_tx_status_irqsafe() may not be mixed
- * for a single hardware.
+ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
+ * may not be mixed for a single hardware.
  *
  * @hw: the hardware the frame was transmitted by
  * @skb: the frame that was transmitted, owned by mac80211 after this call
@@ -2064,14 +2064,34 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,
 void ieee80211_tx_status(struct ieee80211_hw *hw,
                         struct sk_buff *skb);
 
+/**
+ * ieee80211_tx_status_ni - transmit status callback (in process context)
+ *
+ * Like ieee80211_tx_status() but can be called in process context.
+ *
+ * Calls to this function, ieee80211_tx_status() and
+ * ieee80211_tx_status_irqsafe() may not be mixed
+ * for a single hardware.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ */
+static inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw,
+                                         struct sk_buff *skb)
+{
+       local_bh_disable();
+       ieee80211_tx_status(hw, skb);
+       local_bh_enable();
+}
+
 /**
  * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback
  *
  * Like ieee80211_tx_status() but can be called in IRQ context
  * (internally defers to a tasklet.)
  *
- * Calls to this function and ieee80211_tx_status() may not be mixed for a
- * single hardware.
+ * Calls to this function, ieee80211_tx_status() and
+ * ieee80211_tx_status_ni() may not be mixed for a single hardware.
  *
  * @hw: the hardware the frame was transmitted by
  * @skb: the frame that was transmitted, owned by mac80211 after this call