aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2009-07-29 20:08:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-04 16:44:14 -0400
commit42935ecaf4e784d0815afa9a7e5fe7e141157ca3 (patch)
treedc0a0dcfff761e98d8a2a23a7edc8f9182c2774c
parent64344d78228f6346a0462ba2d5fc03494aef4e6b (diff)
mac80211: redefine usage of the mac80211 workqueue
The mac80211 workqueue exists to enable mac80211 and drivers to queue their own work on a single threaded workqueue. mac80211 takes care to flush the workqueue during suspend but we never really had requirements on drivers for how they should use the workqueue in consideration for suspend. We extend mac80211 to document how the mac80211 workqueue should be used, how it should not be used and finally move raw access to the workqueue to mac80211 only. Drivers and mac80211 use helpers to queue work onto the mac80211 workqueue: * ieee80211_queue_work() * ieee80211_queue_delayed_work() These helpers will now warn if mac80211 already completed its suspend cycle and someone is trying to queue work. mac80211 flushes the mac80211 workqueue prior to suspend a few times, but we haven't taken the care to ensure drivers won't add more work after suspend. To help with this we add a warning when someone tries to add work and mac80211 already completed the suspend cycle. Drivers should ensure they cancel any work or delayed work in the mac80211 stop() callback. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/at76c50x-usb.c10
-rw-r--r--drivers/net/wireless/ath/ar9170/led.c11
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c26
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c2
-rw-r--r--drivers/net/wireless/b43/main.c8
-rw-r--r--drivers/net/wireless/b43/phy_common.c2
-rw-r--r--drivers/net/wireless/b43/pio.c2
-rw-r--r--drivers/net/wireless/b43legacy/main.c8
-rw-r--r--drivers/net/wireless/p54/led.c5
-rw-r--r--drivers/net/wireless/p54/main.c2
-rw-r--r--drivers/net/wireless/p54/p54spi.c4
-rw-r--r--drivers/net/wireless/p54/txrx.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_leds.c10
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c2
-rw-r--r--include/net/mac80211.h50
-rw-r--r--net/mac80211/ibss.c6
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/iface.c4
-rw-r--r--net/mac80211/main.c8
-rw-r--r--net/mac80211/mesh.c10
-rw-r--r--net/mac80211/mesh_hwmp.c4
-rw-r--r--net/mac80211/mlme.c48
-rw-r--r--net/mac80211/pm.c4
-rw-r--r--net/mac80211/scan.c8
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/mac80211/util.c41
32 files changed, 208 insertions, 123 deletions
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index aff09a1cf64f..7218dbabad3e 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1875,8 +1875,8 @@ static void at76_dwork_hw_scan(struct work_struct *work)
1875 /* FIXME: add maximum time for scan to complete */ 1875 /* FIXME: add maximum time for scan to complete */
1876 1876
1877 if (ret != CMD_STATUS_COMPLETE) { 1877 if (ret != CMD_STATUS_COMPLETE) {
1878 queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan, 1878 ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
1879 SCAN_POLL_INTERVAL); 1879 SCAN_POLL_INTERVAL);
1880 mutex_unlock(&priv->mtx); 1880 mutex_unlock(&priv->mtx);
1881 return; 1881 return;
1882 } 1882 }
@@ -1937,8 +1937,8 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
1937 goto exit; 1937 goto exit;
1938 } 1938 }
1939 1939
1940 queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan, 1940 ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
1941 SCAN_POLL_INTERVAL); 1941 SCAN_POLL_INTERVAL);
1942 1942
1943exit: 1943exit:
1944 mutex_unlock(&priv->mtx); 1944 mutex_unlock(&priv->mtx);
@@ -2027,7 +2027,7 @@ static void at76_configure_filter(struct ieee80211_hw *hw,
2027 } else 2027 } else
2028 return; 2028 return;
2029 2029
2030 queue_work(hw->workqueue, &priv->work_set_promisc); 2030 ieee80211_queue_work(hw, &priv->work_set_promisc);
2031} 2031}
2032 2032
2033static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 2033static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c
index 63fda6cd2101..86c4e79f6bc8 100644
--- a/drivers/net/wireless/ath/ar9170/led.c
+++ b/drivers/net/wireless/ath/ar9170/led.c
@@ -90,9 +90,12 @@ static void ar9170_update_leds(struct work_struct *work)
90 ar9170_set_leds_state(ar, led_val); 90 ar9170_set_leds_state(ar, led_val);
91 mutex_unlock(&ar->mutex); 91 mutex_unlock(&ar->mutex);
92 92
93 if (rerun) 93 if (!rerun)
94 queue_delayed_work(ar->hw->workqueue, &ar->led_work, 94 return;
95 msecs_to_jiffies(blink_delay)); 95
96 ieee80211_queue_delayed_work(ar->hw,
97 &ar->led_work,
98 msecs_to_jiffies(blink_delay));
96} 99}
97 100
98static void ar9170_led_brightness_set(struct led_classdev *led, 101static void ar9170_led_brightness_set(struct led_classdev *led,
@@ -110,7 +113,7 @@ static void ar9170_led_brightness_set(struct led_classdev *led,
110 } 113 }
111 114
112 if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) 115 if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
113 queue_delayed_work(ar->hw->workqueue, &ar->led_work, HZ/10); 116 ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10);
114} 117}
115 118
116static int ar9170_register_led(struct ar9170 *ar, int i, char *name, 119static int ar9170_register_led(struct ar9170 *ar, int i, char *name,
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 099ed3c3ba28..4fc389ae74b4 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -595,10 +595,12 @@ static void ar9170_tx_janitor(struct work_struct *work)
595 595
596 ar9170_tx_fake_ampdu_status(ar); 596 ar9170_tx_fake_ampdu_status(ar);
597 597
598 if (resched) 598 if (!resched)
599 queue_delayed_work(ar->hw->workqueue, 599 return;
600 &ar->tx_janitor, 600
601 msecs_to_jiffies(AR9170_JANITOR_DELAY)); 601 ieee80211_queue_delayed_work(ar->hw,
602 &ar->tx_janitor,
603 msecs_to_jiffies(AR9170_JANITOR_DELAY));
602} 604}
603 605
604void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) 606void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
@@ -648,7 +650,7 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
648 * pre-TBTT event 650 * pre-TBTT event
649 */ 651 */
650 if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) 652 if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
651 queue_work(ar->hw->workqueue, &ar->beacon_work); 653 ieee80211_queue_work(ar->hw, &ar->beacon_work);
652 break; 654 break;
653 655
654 case 0xc2: 656 case 0xc2:
@@ -1825,10 +1827,12 @@ static void ar9170_tx(struct ar9170 *ar)
1825 } 1827 }
1826 } 1828 }
1827 1829
1828 if (schedule_garbagecollector) 1830 if (!schedule_garbagecollector)
1829 queue_delayed_work(ar->hw->workqueue, 1831 return;
1830 &ar->tx_janitor, 1832
1831 msecs_to_jiffies(AR9170_JANITOR_DELAY)); 1833 ieee80211_queue_delayed_work(ar->hw,
1834 &ar->tx_janitor,
1835 msecs_to_jiffies(AR9170_JANITOR_DELAY));
1832} 1836}
1833 1837
1834static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb) 1838static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb)
@@ -2157,7 +2161,7 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
2157 } 2161 }
2158 2162
2159 if (likely(IS_STARTED(ar))) 2163 if (likely(IS_STARTED(ar)))
2160 queue_work(ar->hw->workqueue, &ar->filter_config_work); 2164 ieee80211_queue_work(ar->hw, &ar->filter_config_work);
2161} 2165}
2162 2166
2163static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, 2167static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
@@ -2415,7 +2419,7 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw,
2415 } 2419 }
2416 2420
2417 if (IS_STARTED(ar) && ar->filter_changed) 2421 if (IS_STARTED(ar) && ar->filter_changed)
2418 queue_work(ar->hw->workqueue, &ar->filter_config_work); 2422 ieee80211_queue_work(ar->hw, &ar->filter_config_work);
2419} 2423}
2420 2424
2421static int ar9170_get_stats(struct ieee80211_hw *hw, 2425static int ar9170_get_stats(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index cf44623b5cd2..292ac2b41891 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -973,10 +973,11 @@ static void ath_led_blink_work(struct work_struct *work)
973 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 973 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN,
974 (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); 974 (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
975 975
976 queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work, 976 ieee80211_queue_delayed_work(sc->hw,
977 (sc->sc_flags & SC_OP_LED_ON) ? 977 &sc->ath_led_blink_work,
978 msecs_to_jiffies(sc->led_off_duration) : 978 (sc->sc_flags & SC_OP_LED_ON) ?
979 msecs_to_jiffies(sc->led_on_duration)); 979 msecs_to_jiffies(sc->led_off_duration) :
980 msecs_to_jiffies(sc->led_on_duration));
980 981
981 sc->led_on_duration = sc->led_on_cnt ? 982 sc->led_on_duration = sc->led_on_cnt ?
982 max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : 983 max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
@@ -1013,8 +1014,8 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
1013 case LED_FULL: 1014 case LED_FULL:
1014 if (led->led_type == ATH_LED_ASSOC) { 1015 if (led->led_type == ATH_LED_ASSOC) {
1015 sc->sc_flags |= SC_OP_LED_ASSOCIATED; 1016 sc->sc_flags |= SC_OP_LED_ASSOCIATED;
1016 queue_delayed_work(sc->hw->workqueue, 1017 ieee80211_queue_delayed_work(sc->hw,
1017 &sc->ath_led_blink_work, 0); 1018 &sc->ath_led_blink_work, 0);
1018 } else if (led->led_type == ATH_LED_RADIO) { 1019 } else if (led->led_type == ATH_LED_RADIO) {
1019 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); 1020 ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0);
1020 sc->sc_flags |= SC_OP_LED_ON; 1021 sc->sc_flags |= SC_OP_LED_ON;
@@ -1972,7 +1973,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
1972 1973
1973 ieee80211_wake_queues(hw); 1974 ieee80211_wake_queues(hw);
1974 1975
1975 queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, 0); 1976 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
1976 1977
1977mutex_unlock: 1978mutex_unlock:
1978 mutex_unlock(&sc->mutex); 1979 mutex_unlock(&sc->mutex);
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index e1d419e02b4a..19b88f8177fd 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -351,7 +351,7 @@ void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
351 * Drop from tasklet to work to allow mutex for channel 351 * Drop from tasklet to work to allow mutex for channel
352 * change. 352 * change.
353 */ 353 */
354 queue_work(aphy->sc->hw->workqueue, 354 ieee80211_queue_work(aphy->sc->hw,
355 &aphy->sc->chan_work); 355 &aphy->sc->chan_work);
356 } 356 }
357 } 357 }
@@ -367,7 +367,7 @@ static void ath9k_mark_paused(struct ath_wiphy *aphy)
367 struct ath_softc *sc = aphy->sc; 367 struct ath_softc *sc = aphy->sc;
368 aphy->state = ATH_WIPHY_PAUSED; 368 aphy->state = ATH_WIPHY_PAUSED;
369 if (!__ath9k_wiphy_pausing(sc)) 369 if (!__ath9k_wiphy_pausing(sc))
370 queue_work(sc->hw->workqueue, &sc->chan_work); 370 ieee80211_queue_work(sc->hw, &sc->chan_work);
371} 371}
372 372
373static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) 373static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
@@ -521,7 +521,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
521 spin_unlock_bh(&sc->wiphy_lock); 521 spin_unlock_bh(&sc->wiphy_lock);
522 ath_radio_disable(sc); 522 ath_radio_disable(sc);
523 ath_radio_enable(sc); 523 ath_radio_enable(sc);
524 queue_work(aphy->sc->hw->workqueue, 524 ieee80211_queue_work(aphy->sc->hw,
525 &aphy->sc->chan_work); 525 &aphy->sc->chan_work);
526 return -EBUSY; /* previous select still in progress */ 526 return -EBUSY; /* previous select still in progress */
527 } 527 }
@@ -541,7 +541,7 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
541 541
542 if (now) { 542 if (now) {
543 /* Ready to request channel change immediately */ 543 /* Ready to request channel change immediately */
544 queue_work(aphy->sc->hw->workqueue, &aphy->sc->chan_work); 544 ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work);
545 } 545 }
546 546
547 /* 547 /*
@@ -648,8 +648,9 @@ try_again:
648 "change\n"); 648 "change\n");
649 } 649 }
650 650
651 queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, 651 ieee80211_queue_delayed_work(sc->hw,
652 sc->wiphy_scheduler_int); 652 &sc->wiphy_work,
653 sc->wiphy_scheduler_int);
653} 654}
654 655
655void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) 656void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
@@ -657,8 +658,8 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
657 cancel_delayed_work_sync(&sc->wiphy_work); 658 cancel_delayed_work_sync(&sc->wiphy_work);
658 sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); 659 sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int);
659 if (sc->wiphy_scheduler_int) 660 if (sc->wiphy_scheduler_int)
660 queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, 661 ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work,
661 sc->wiphy_scheduler_int); 662 sc->wiphy_scheduler_int);
662} 663}
663 664
664/* caller must hold wiphy_lock */ 665/* caller must hold wiphy_lock */
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index b7806e2ca0e1..87762da0383b 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2063,7 +2063,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
2063 ath_reset(sc, false); 2063 ath_reset(sc, false);
2064 } 2064 }
2065 2065
2066 queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, 2066 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
2067 msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); 2067 msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
2068} 2068}
2069 2069
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 3f4360ad0e4e..f985938962e3 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1654,7 +1654,7 @@ static void b43_update_templates(struct b43_wl *wl)
1654 wl->current_beacon = beacon; 1654 wl->current_beacon = beacon;
1655 wl->beacon0_uploaded = 0; 1655 wl->beacon0_uploaded = 0;
1656 wl->beacon1_uploaded = 0; 1656 wl->beacon1_uploaded = 0;
1657 queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); 1657 ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
1658} 1658}
1659 1659
1660static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) 1660static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
@@ -2914,7 +2914,7 @@ out_requeue:
2914 delay = msecs_to_jiffies(50); 2914 delay = msecs_to_jiffies(50);
2915 else 2915 else
2916 delay = round_jiffies_relative(HZ * 15); 2916 delay = round_jiffies_relative(HZ * 15);
2917 queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay); 2917 ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
2918out: 2918out:
2919 mutex_unlock(&wl->mutex); 2919 mutex_unlock(&wl->mutex);
2920} 2920}
@@ -2925,7 +2925,7 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev)
2925 2925
2926 dev->periodic_state = 0; 2926 dev->periodic_state = 0;
2927 INIT_DELAYED_WORK(work, b43_periodic_work_handler); 2927 INIT_DELAYED_WORK(work, b43_periodic_work_handler);
2928 queue_delayed_work(dev->wl->hw->workqueue, work, 0); 2928 ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
2929} 2929}
2930 2930
2931/* Check if communication with the device works correctly. */ 2931/* Check if communication with the device works correctly. */
@@ -4871,7 +4871,7 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
4871 if (b43_status(dev) < B43_STAT_INITIALIZED) 4871 if (b43_status(dev) < B43_STAT_INITIALIZED)
4872 return; 4872 return;
4873 b43info(dev->wl, "Controller RESET (%s) ...\n", reason); 4873 b43info(dev->wl, "Controller RESET (%s) ...\n", reason);
4874 queue_work(dev->wl->hw->workqueue, &dev->restart_work); 4874 ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
4875} 4875}
4876 4876
4877#ifdef CONFIG_PM 4877#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 6d241622210e..f537bfef690a 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -352,7 +352,7 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
352 352
353 /* We must adjust the transmission power in hardware. 353 /* We must adjust the transmission power in hardware.
354 * Schedule b43_phy_txpower_adjust_work(). */ 354 * Schedule b43_phy_txpower_adjust_work(). */
355 queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work); 355 ieee80211_queue_work(dev->wl->hw, &dev->wl->txpower_adjust_work);
356} 356}
357 357
358int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset) 358int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 69138e8c1db6..73c047d8de40 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -783,7 +783,7 @@ void b43_pio_rx(struct b43_pio_rxqueue *q)
783{ 783{
784 /* Due to latency issues we must run the RX path in 784 /* Due to latency issues we must run the RX path in
785 * a workqueue to be able to schedule between packets. */ 785 * a workqueue to be able to schedule between packets. */
786 queue_work(q->dev->wl->hw->workqueue, &q->rx_work); 786 ieee80211_queue_work(q->dev->wl->hw, &q->rx_work);
787} 787}
788 788
789static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q) 789static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index c4973c1942bf..b1435594921a 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1252,7 +1252,7 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl)
1252 wl->current_beacon = beacon; 1252 wl->current_beacon = beacon;
1253 wl->beacon0_uploaded = 0; 1253 wl->beacon0_uploaded = 0;
1254 wl->beacon1_uploaded = 0; 1254 wl->beacon1_uploaded = 0;
1255 queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); 1255 ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
1256} 1256}
1257 1257
1258static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev, 1258static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
@@ -2300,7 +2300,7 @@ out_requeue:
2300 delay = msecs_to_jiffies(50); 2300 delay = msecs_to_jiffies(50);
2301 else 2301 else
2302 delay = round_jiffies_relative(HZ * 15); 2302 delay = round_jiffies_relative(HZ * 15);
2303 queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay); 2303 ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
2304out: 2304out:
2305 mutex_unlock(&wl->mutex); 2305 mutex_unlock(&wl->mutex);
2306} 2306}
@@ -2311,7 +2311,7 @@ static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev)
2311 2311
2312 dev->periodic_state = 0; 2312 dev->periodic_state = 0;
2313 INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler); 2313 INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler);
2314 queue_delayed_work(dev->wl->hw->workqueue, work, 0); 2314 ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
2315} 2315}
2316 2316
2317/* Validate access to the chip (SHM) */ 2317/* Validate access to the chip (SHM) */
@@ -3885,7 +3885,7 @@ void b43legacy_controller_restart(struct b43legacy_wldev *dev,
3885 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) 3885 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
3886 return; 3886 return;
3887 b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason); 3887 b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason);
3888 queue_work(dev->wl->hw->workqueue, &dev->restart_work); 3888 ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
3889} 3889}
3890 3890
3891#ifdef CONFIG_PM 3891#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c
index c00115b206d4..9575ac033630 100644
--- a/drivers/net/wireless/p54/led.c
+++ b/drivers/net/wireless/p54/led.c
@@ -61,7 +61,7 @@ static void p54_update_leds(struct work_struct *work)
61 wiphy_name(priv->hw->wiphy), err); 61 wiphy_name(priv->hw->wiphy), err);
62 62
63 if (rerun) 63 if (rerun)
64 queue_delayed_work(priv->hw->workqueue, &priv->led_work, 64 ieee80211_queue_delayed_work(priv->hw, &priv->led_work,
65 msecs_to_jiffies(blink_delay)); 65 msecs_to_jiffies(blink_delay));
66} 66}
67 67
@@ -78,8 +78,7 @@ static void p54_led_brightness_set(struct led_classdev *led_dev,
78 78
79 if ((brightness) && (led->registered)) { 79 if ((brightness) && (led->registered)) {
80 led->toggled++; 80 led->toggled++;
81 queue_delayed_work(priv->hw->workqueue, &priv->led_work, 81 ieee80211_queue_delayed_work(priv->hw, &priv->led_work, HZ/10);
82 HZ/10);
83 } 82 }
84} 83}
85 84
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 955f6d7ec16a..a0d0e726bc4e 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -180,7 +180,7 @@ static int p54_start(struct ieee80211_hw *dev)
180 goto out; 180 goto out;
181 } 181 }
182 182
183 queue_delayed_work(dev->workqueue, &priv->work, 0); 183 ieee80211_queue_delayed_work(dev, &priv->work, 0);
184 184
185 priv->softled_state = 0; 185 priv->softled_state = 0;
186 err = p54_set_leds(priv); 186 err = p54_set_leds(priv);
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index eef532987d05..05458d9249ce 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -391,7 +391,7 @@ static irqreturn_t p54spi_interrupt(int irq, void *config)
391 struct spi_device *spi = config; 391 struct spi_device *spi = config;
392 struct p54s_priv *priv = dev_get_drvdata(&spi->dev); 392 struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
393 393
394 queue_work(priv->hw->workqueue, &priv->work); 394 ieee80211_queue_work(priv->hw, &priv->work);
395 395
396 return IRQ_HANDLED; 396 return IRQ_HANDLED;
397} 397}
@@ -479,7 +479,7 @@ static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
479 list_add_tail(&di->tx_list, &priv->tx_pending); 479 list_add_tail(&di->tx_list, &priv->tx_pending);
480 spin_unlock_irqrestore(&priv->tx_lock, flags); 480 spin_unlock_irqrestore(&priv->tx_lock, flags);
481 481
482 queue_work(priv->hw->workqueue, &priv->work); 482 ieee80211_queue_work(priv->hw, &priv->work);
483} 483}
484 484
485static void p54spi_work(struct work_struct *work) 485static void p54spi_work(struct work_struct *work)
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index c32a0d2fa1f7..704685fab177 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -380,7 +380,7 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
380 380
381 ieee80211_rx_irqsafe(priv->hw, skb); 381 ieee80211_rx_irqsafe(priv->hw, skb);
382 382
383 queue_delayed_work(priv->hw->workqueue, &priv->work, 383 ieee80211_queue_delayed_work(priv->hw, &priv->work,
384 msecs_to_jiffies(P54_STATISTICS_UPDATE)); 384 msecs_to_jiffies(P54_STATISTICS_UPDATE));
385 385
386 return -1; 386 return -1;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 658a63bfb761..b717afbf3f38 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -215,7 +215,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
215 rt2x00lib_beacondone_iter, 215 rt2x00lib_beacondone_iter,
216 rt2x00dev); 216 rt2x00dev);
217 217
218 queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); 218 ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
219} 219}
220EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); 220EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
221 221
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 79915687e744..917831689ccd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -351,8 +351,8 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
351 351
352 rt2x00link_reset_tuner(rt2x00dev, false); 352 rt2x00link_reset_tuner(rt2x00dev, false);
353 353
354 queue_delayed_work(rt2x00dev->hw->workqueue, 354 ieee80211_queue_delayed_work(rt2x00dev->hw,
355 &link->work, LINK_TUNE_INTERVAL); 355 &link->work, LINK_TUNE_INTERVAL);
356} 356}
357 357
358void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) 358void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
@@ -461,8 +461,8 @@ static void rt2x00link_tuner(struct work_struct *work)
461 * Increase tuner counter, and reschedule the next link tuner run. 461 * Increase tuner counter, and reschedule the next link tuner run.
462 */ 462 */
463 link->count++; 463 link->count++;
464 queue_delayed_work(rt2x00dev->hw->workqueue, 464 ieee80211_queue_delayed_work(rt2x00dev->hw,
465 &link->work, LINK_TUNE_INTERVAL); 465 &link->work, LINK_TUNE_INTERVAL);
466} 466}
467 467
468void rt2x00link_register(struct rt2x00_dev *rt2x00dev) 468void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index e92c8f99d695..81febdfd6639 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -431,7 +431,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
431 if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) 431 if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
432 rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); 432 rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
433 else 433 else
434 queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); 434 ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->filter_work);
435} 435}
436EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); 436EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
437 437
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index c9b9dbe584c6..53f57dc52226 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -220,7 +220,7 @@ static void rtl8187_tx_cb(struct urb *urb)
220 * reading a register in the device. We are in interrupt mode 220 * reading a register in the device. We are in interrupt mode
221 * here, thus queue the skb and finish on a work queue. */ 221 * here, thus queue the skb and finish on a work queue. */
222 skb_queue_tail(&priv->b_tx_status.queue, skb); 222 skb_queue_tail(&priv->b_tx_status.queue, skb);
223 queue_delayed_work(hw->workqueue, &priv->work, 0); 223 ieee80211_queue_delayed_work(hw, &priv->work, 0);
224 } 224 }
225} 225}
226 226
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c
index cf9f899fe0e6..a6cfb7e77994 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_leds.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c
@@ -108,11 +108,11 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
108 struct rtl8187_priv *priv = hw->priv; 108 struct rtl8187_priv *priv = hw->priv;
109 109
110 if (brightness == LED_OFF) { 110 if (brightness == LED_OFF) {
111 queue_delayed_work(hw->workqueue, &priv->led_off, 0); 111 ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
112 /* The LED is off for 1/20 sec so that it just blinks. */ 112 /* The LED is off for 1/20 sec so that it just blinks. */
113 queue_delayed_work(hw->workqueue, &priv->led_on, HZ / 20); 113 ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20);
114 } else 114 } else
115 queue_delayed_work(hw->workqueue, &priv->led_on, 0); 115 ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
116} 116}
117 117
118static int rtl8187_register_led(struct ieee80211_hw *dev, 118static int rtl8187_register_led(struct ieee80211_hw *dev,
@@ -193,7 +193,7 @@ void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
193 err = rtl8187_register_led(dev, &priv->led_rx, name, 193 err = rtl8187_register_led(dev, &priv->led_rx, name,
194 ieee80211_get_rx_led_name(dev), ledpin); 194 ieee80211_get_rx_led_name(dev), ledpin);
195 if (!err) { 195 if (!err) {
196 queue_delayed_work(dev->workqueue, &priv->led_on, 0); 196 ieee80211_queue_delayed_work(dev, &priv->led_on, 0);
197 return; 197 return;
198 } 198 }
199 /* registration of RX LED failed - unregister TX */ 199 /* registration of RX LED failed - unregister TX */
@@ -209,7 +209,7 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev)
209 struct rtl8187_priv *priv = dev->priv; 209 struct rtl8187_priv *priv = dev->priv;
210 210
211 /* turn the LED off before exiting */ 211 /* turn the LED off before exiting */
212 queue_delayed_work(dev->workqueue, &priv->led_off, 0); 212 ieee80211_queue_delayed_work(dev, &priv->led_off, 0);
213 cancel_delayed_work_sync(&priv->led_off); 213 cancel_delayed_work_sync(&priv->led_off);
214 cancel_delayed_work_sync(&priv->led_on); 214 cancel_delayed_work_sync(&priv->led_on);
215 rtl8187_unregister_led(&priv->led_rx); 215 rtl8187_unregister_led(&priv->led_rx);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 9600b72495da..54abdd0c0045 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -698,7 +698,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
698 && !mac->pass_ctrl) 698 && !mac->pass_ctrl)
699 return 0; 699 return 0;
700 700
701 fc = *(__le16 *)buffer; 701 fc = get_unaligned((__le16*)buffer);
702 need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc); 702 need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
703 703
704 skb = dev_alloc_skb(length + (need_padding ? 2 : 0)); 704 skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d4e09a06b4a2..5ed93f4406a8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -73,6 +73,21 @@
73 */ 73 */
74 74
75/** 75/**
76 * DOC: mac80211 workqueue
77 *
78 * mac80211 provides its own workqueue for drivers and internal mac80211 use.
79 * The workqueue is a single threaded workqueue and can only be accessed by
80 * helpers for sanity checking. Drivers must ensure all work added onto the
81 * mac80211 workqueue should be cancelled on the driver stop() callback.
82 *
83 * mac80211 will flushed the workqueue upon interface removal and during
84 * suspend.
85 *
86 * All work performed on the mac80211 workqueue must not acquire the RTNL lock.
87 *
88 */
89
90/**
76 * enum ieee80211_max_queues - maximum number of queues 91 * enum ieee80211_max_queues - maximum number of queues
77 * 92 *
78 * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. 93 * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues.
@@ -913,12 +928,6 @@ enum ieee80211_hw_flags {
913 * 928 *
914 * @conf: &struct ieee80211_conf, device configuration, don't use. 929 * @conf: &struct ieee80211_conf, device configuration, don't use.
915 * 930 *
916 * @workqueue: single threaded workqueue available for driver use,
917 * allocated by mac80211 on registration and flushed when an
918 * interface is removed.
919 * NOTICE: All work performed on this workqueue must not
920 * acquire the RTNL lock.
921 *
922 * @priv: pointer to private area that was allocated for driver use 931 * @priv: pointer to private area that was allocated for driver use
923 * along with this structure. 932 * along with this structure.
924 * 933 *
@@ -954,7 +963,6 @@ enum ieee80211_hw_flags {
954struct ieee80211_hw { 963struct ieee80211_hw {
955 struct ieee80211_conf conf; 964 struct ieee80211_conf conf;
956 struct wiphy *wiphy; 965 struct wiphy *wiphy;
957 struct workqueue_struct *workqueue;
958 const char *rate_control_algorithm; 966 const char *rate_control_algorithm;
959 void *priv; 967 void *priv;
960 u32 flags; 968 u32 flags;
@@ -1301,7 +1309,8 @@ enum ieee80211_ampdu_mlme_action {
1301 * is disabled. This should turn off the hardware (at least 1309 * is disabled. This should turn off the hardware (at least
1302 * it must turn off frame reception.) 1310 * it must turn off frame reception.)
1303 * May be called right after add_interface if that rejects 1311 * May be called right after add_interface if that rejects
1304 * an interface. 1312 * an interface. If you added any work onto the mac80211 workqueue
1313 * you should ensure to cancel it on this callback.
1305 * Must be implemented. 1314 * Must be implemented.
1306 * 1315 *
1307 * @add_interface: Called when a netdevice attached to the hardware is 1316 * @add_interface: Called when a netdevice attached to the hardware is
@@ -1928,6 +1937,31 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
1928 void *data); 1937 void *data);
1929 1938
1930/** 1939/**
1940 * ieee80211_queue_work - add work onto the mac80211 workqueue
1941 *
1942 * Drivers and mac80211 use this to add work onto the mac80211 workqueue.
1943 * This helper ensures drivers are not queueing work when they should not be.
1944 *
1945 * @hw: the hardware struct for the interface we are adding work for
1946 * @work: the work we want to add onto the mac80211 workqueue
1947 */
1948void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work);
1949
1950/**
1951 * ieee80211_queue_delayed_work - add work onto the mac80211 workqueue
1952 *
1953 * Drivers and mac80211 use this to queue delayed work onto the mac80211
1954 * workqueue.
1955 *
1956 * @hw: the hardware struct for the interface we are adding work for
1957 * @dwork: delayable work to queue onto the mac80211 workqueue
1958 * @delay: number of jiffies to wait before queueing
1959 */
1960void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
1961 struct delayed_work *dwork,
1962 unsigned long delay);
1963
1964/**
1931 * ieee80211_start_tx_ba_session - Start a tx Block Ack session. 1965 * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
1932 * @hw: pointer as obtained from ieee80211_alloc_hw(). 1966 * @hw: pointer as obtained from ieee80211_alloc_hw().
1933 * @ra: receiver address of the BA session recipient 1967 * @ra: receiver address of the BA session recipient
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 6e3cca65c460..920ec8792f4b 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -781,7 +781,7 @@ static void ieee80211_ibss_timer(unsigned long data)
781 } 781 }
782 782
783 set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); 783 set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
784 queue_work(local->hw.workqueue, &ifibss->work); 784 ieee80211_queue_work(&local->hw, &ifibss->work);
785} 785}
786 786
787#ifdef CONFIG_PM 787#ifdef CONFIG_PM
@@ -853,7 +853,7 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
853 case IEEE80211_STYPE_PROBE_REQ: 853 case IEEE80211_STYPE_PROBE_REQ:
854 case IEEE80211_STYPE_AUTH: 854 case IEEE80211_STYPE_AUTH:
855 skb_queue_tail(&sdata->u.ibss.skb_queue, skb); 855 skb_queue_tail(&sdata->u.ibss.skb_queue, skb);
856 queue_work(local->hw.workqueue, &sdata->u.ibss.work); 856 ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
857 return RX_QUEUED; 857 return RX_QUEUED;
858 } 858 }
859 859
@@ -912,7 +912,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
912 ieee80211_recalc_idle(sdata->local); 912 ieee80211_recalc_idle(sdata->local);
913 913
914 set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); 914 set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
915 queue_work(sdata->local->hw.workqueue, &sdata->u.ibss.work); 915 ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work);
916 916
917 return 0; 917 return 0;
918} 918}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index aec6853cb435..316825be2019 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -614,6 +614,12 @@ struct ieee80211_local {
614 614
615 const struct ieee80211_ops *ops; 615 const struct ieee80211_ops *ops;
616 616
617 /*
618 * private workqueue to mac80211. mac80211 makes this accessible
619 * via ieee80211_queue_work()
620 */
621 struct workqueue_struct *workqueue;
622
617 unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; 623 unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
618 /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ 624 /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */
619 spinlock_t queue_stop_reason_lock; 625 spinlock_t queue_stop_reason_lock;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index a83087f4237d..8c1284d45e69 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -312,7 +312,7 @@ static int ieee80211_open(struct net_device *dev)
312 * to fix this. 312 * to fix this.
313 */ 313 */
314 if (sdata->vif.type == NL80211_IFTYPE_STATION) 314 if (sdata->vif.type == NL80211_IFTYPE_STATION)
315 queue_work(local->hw.workqueue, &sdata->u.mgd.work); 315 ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
316 316
317 netif_tx_start_all_queues(dev); 317 netif_tx_start_all_queues(dev);
318 318
@@ -551,7 +551,7 @@ static int ieee80211_stop(struct net_device *dev)
551 551
552 ieee80211_led_radio(local, false); 552 ieee80211_led_radio(local, false);
553 553
554 flush_workqueue(local->hw.workqueue); 554 flush_workqueue(local->workqueue);
555 555
556 tasklet_disable(&local->tx_pending_tasklet); 556 tasklet_disable(&local->tx_pending_tasklet);
557 tasklet_disable(&local->tasklet); 557 tasklet_disable(&local->tasklet);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 5e76dd1daf71..22e07385ff60 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -821,9 +821,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
821 if (hw->queues > IEEE80211_MAX_QUEUES) 821 if (hw->queues > IEEE80211_MAX_QUEUES)
822 hw->queues = IEEE80211_MAX_QUEUES; 822 hw->queues = IEEE80211_MAX_QUEUES;
823 823
824 local->hw.workqueue = 824 local->workqueue =
825 create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); 825 create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
826 if (!local->hw.workqueue) { 826 if (!local->workqueue) {
827 result = -ENOMEM; 827 result = -ENOMEM;
828 goto fail_workqueue; 828 goto fail_workqueue;
829 } 829 }
@@ -913,7 +913,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
913 sta_info_stop(local); 913 sta_info_stop(local);
914 fail_sta_info: 914 fail_sta_info:
915 debugfs_hw_del(local); 915 debugfs_hw_del(local);
916 destroy_workqueue(local->hw.workqueue); 916 destroy_workqueue(local->workqueue);
917 fail_workqueue: 917 fail_workqueue:
918 wiphy_unregister(local->hw.wiphy); 918 wiphy_unregister(local->hw.wiphy);
919 fail_wiphy_register: 919 fail_wiphy_register:
@@ -955,7 +955,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
955 skb_queue_purge(&local->skb_queue); 955 skb_queue_purge(&local->skb_queue);
956 skb_queue_purge(&local->skb_queue_unreliable); 956 skb_queue_purge(&local->skb_queue_unreliable);
957 957
958 destroy_workqueue(local->hw.workqueue); 958 destroy_workqueue(local->workqueue);
959 wiphy_unregister(local->hw.wiphy); 959 wiphy_unregister(local->hw.wiphy);
960 ieee80211_wep_free(local); 960 ieee80211_wep_free(local);
961 ieee80211_led_exit(local); 961 ieee80211_led_exit(local);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 9a3826978b1c..2f4f518ab45c 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -54,7 +54,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
54 return; 54 return;
55 } 55 }
56 56
57 queue_work(local->hw.workqueue, &ifmsh->work); 57 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
58} 58}
59 59
60/** 60/**
@@ -357,7 +357,7 @@ static void ieee80211_mesh_path_timer(unsigned long data)
357 return; 357 return;
358 } 358 }
359 359
360 queue_work(local->hw.workqueue, &ifmsh->work); 360 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
361} 361}
362 362
363struct mesh_table *mesh_table_grow(struct mesh_table *tbl) 363struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
@@ -471,7 +471,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
471 struct ieee80211_local *local = sdata->local; 471 struct ieee80211_local *local = sdata->local;
472 472
473 ifmsh->housekeeping = true; 473 ifmsh->housekeeping = true;
474 queue_work(local->hw.workqueue, &ifmsh->work); 474 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
475 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | 475 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
476 BSS_CHANGED_BEACON_ENABLED); 476 BSS_CHANGED_BEACON_ENABLED);
477} 477}
@@ -619,7 +619,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
619 rcu_read_lock(); 619 rcu_read_lock();
620 list_for_each_entry_rcu(sdata, &local->interfaces, list) 620 list_for_each_entry_rcu(sdata, &local->interfaces, list)
621 if (ieee80211_vif_is_mesh(&sdata->vif)) 621 if (ieee80211_vif_is_mesh(&sdata->vif))
622 queue_work(local->hw.workqueue, &sdata->u.mesh.work); 622 ieee80211_queue_work(local->hw.workqueue, &sdata->u.mesh.work);
623 rcu_read_unlock(); 623 rcu_read_unlock();
624} 624}
625 625
@@ -692,7 +692,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
692 case IEEE80211_STYPE_PROBE_RESP: 692 case IEEE80211_STYPE_PROBE_RESP:
693 case IEEE80211_STYPE_BEACON: 693 case IEEE80211_STYPE_BEACON:
694 skb_queue_tail(&ifmsh->skb_queue, skb); 694 skb_queue_tail(&ifmsh->skb_queue, skb);
695 queue_work(local->hw.workqueue, &ifmsh->work); 695 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work);
696 return RX_QUEUED; 696 return RX_QUEUED;
697 } 697 }
698 698
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index e93c37ef6a48..11ab71a68ff9 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -660,14 +660,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
660 spin_unlock(&ifmsh->mesh_preq_queue_lock); 660 spin_unlock(&ifmsh->mesh_preq_queue_lock);
661 661
662 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) 662 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
663 queue_work(sdata->local->hw.workqueue, &ifmsh->work); 663 ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work);
664 664
665 else if (time_before(jiffies, ifmsh->last_preq)) { 665 else if (time_before(jiffies, ifmsh->last_preq)) {
666 /* avoid long wait if did not send preqs for a long time 666 /* avoid long wait if did not send preqs for a long time
667 * and jiffies wrapped around 667 * and jiffies wrapped around
668 */ 668 */
669 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; 669 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
670 queue_work(sdata->local->hw.workqueue, &ifmsh->work); 670 ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work);
671 } else 671 } else
672 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + 672 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
673 min_preq_int_jiff(sdata)); 673 min_preq_int_jiff(sdata));
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ee83125ed179..0779ba150b26 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -565,7 +565,7 @@ static void ieee80211_chswitch_timer(unsigned long data)
565 return; 565 return;
566 } 566 }
567 567
568 queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work); 568 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
569} 569}
570 570
571void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, 571void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
@@ -597,7 +597,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
597 sdata->local->csa_channel = new_ch; 597 sdata->local->csa_channel = new_ch;
598 598
599 if (sw_elem->count <= 1) { 599 if (sw_elem->count <= 1) {
600 queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work); 600 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
601 } else { 601 } else {
602 ieee80211_stop_queues_by_reason(&sdata->local->hw, 602 ieee80211_stop_queues_by_reason(&sdata->local->hw,
603 IEEE80211_QUEUE_STOP_REASON_CSA); 603 IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -763,7 +763,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
763 if (local->quiescing || local->suspended) 763 if (local->quiescing || local->suspended)
764 return; 764 return;
765 765
766 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); 766 ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
767} 767}
768 768
769/* MLME */ 769/* MLME */
@@ -950,7 +950,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
950 * due to work needing to be done. Hence, queue the STAs work 950 * due to work needing to be done. Hence, queue the STAs work
951 * again for that. 951 * again for that.
952 */ 952 */
953 queue_work(local->hw.workqueue, &ifmgd->work); 953 ieee80211_queue_work(&local->hw, &ifmgd->work);
954 return RX_MGMT_CFG80211_AUTH_TO; 954 return RX_MGMT_CFG80211_AUTH_TO;
955 } 955 }
956 956
@@ -995,7 +995,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
995 * due to work needing to be done. Hence, queue the STAs work 995 * due to work needing to be done. Hence, queue the STAs work
996 * again for that. 996 * again for that.
997 */ 997 */
998 queue_work(local->hw.workqueue, &ifmgd->work); 998 ieee80211_queue_work(&local->hw, &ifmgd->work);
999 return RX_MGMT_CFG80211_AUTH_TO; 999 return RX_MGMT_CFG80211_AUTH_TO;
1000 } 1000 }
1001 1001
@@ -1124,7 +1124,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata,
1124 * due to work needing to be done. Hence, queue the STAs work 1124 * due to work needing to be done. Hence, queue the STAs work
1125 * again for that. 1125 * again for that.
1126 */ 1126 */
1127 queue_work(local->hw.workqueue, &ifmgd->work); 1127 ieee80211_queue_work(&local->hw, &ifmgd->work);
1128 return RX_MGMT_CFG80211_ASSOC_TO; 1128 return RX_MGMT_CFG80211_ASSOC_TO;
1129 } 1129 }
1130 1130
@@ -1232,8 +1232,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
1232{ 1232{
1233 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 1233 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1234 1234
1235 queue_work(sdata->local->hw.workqueue, 1235 ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
1236 &sdata->u.mgd.beacon_loss_work);
1237} 1236}
1238EXPORT_SYMBOL(ieee80211_beacon_loss); 1237EXPORT_SYMBOL(ieee80211_beacon_loss);
1239 1238
@@ -1888,7 +1887,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
1888 case IEEE80211_STYPE_DISASSOC: 1887 case IEEE80211_STYPE_DISASSOC:
1889 case IEEE80211_STYPE_ACTION: 1888 case IEEE80211_STYPE_ACTION:
1890 skb_queue_tail(&sdata->u.mgd.skb_queue, skb); 1889 skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
1891 queue_work(local->hw.workqueue, &sdata->u.mgd.work); 1890 ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
1892 return RX_QUEUED; 1891 return RX_QUEUED;
1893 } 1892 }
1894 1893
@@ -2026,7 +2025,7 @@ static void ieee80211_sta_timer(unsigned long data)
2026 return; 2025 return;
2027 } 2026 }
2028 2027
2029 queue_work(local->hw.workqueue, &ifmgd->work); 2028 ieee80211_queue_work(&local->hw, &ifmgd->work);
2030} 2029}
2031 2030
2032static void ieee80211_sta_work(struct work_struct *work) 2031static void ieee80211_sta_work(struct work_struct *work)
@@ -2051,13 +2050,11 @@ static void ieee80211_sta_work(struct work_struct *work)
2051 return; 2050 return;
2052 2051
2053 /* 2052 /*
2054 * Nothing should have been stuffed into the workqueue during 2053 * ieee80211_queue_work() should have picked up most cases,
2055 * the suspend->resume cycle. If this WARN is seen then there 2054 * here we'll pick the the rest.
2056 * is a bug with either the driver suspend or something in
2057 * mac80211 stuffing into the workqueue which we haven't yet
2058 * cleared during mac80211's suspend cycle.
2059 */ 2055 */
2060 if (WARN_ON(local->suspended)) 2056 if (WARN(local->suspended, "STA MLME work scheduled while "
2057 "going to suspend\n"))
2061 return; 2058 return;
2062 2059
2063 ifmgd = &sdata->u.mgd; 2060 ifmgd = &sdata->u.mgd;
@@ -2113,9 +2110,9 @@ static void ieee80211_sta_work(struct work_struct *work)
2113 mutex_unlock(&ifmgd->mtx); 2110 mutex_unlock(&ifmgd->mtx);
2114 2111
2115 if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) 2112 if (test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request))
2116 queue_delayed_work(local->hw.workqueue, 2113 ieee80211_queue_delayed_work(&local->hw,
2117 &local->scan_work, 2114 &local->scan_work,
2118 round_jiffies_relative(0)); 2115 round_jiffies_relative(0));
2119 return; 2116 return;
2120 } 2117 }
2121 2118
@@ -2196,8 +2193,7 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
2196 if (local->quiescing) 2193 if (local->quiescing)
2197 return; 2194 return;
2198 2195
2199 queue_work(sdata->local->hw.workqueue, 2196 ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
2200 &sdata->u.mgd.beacon_loss_work);
2201} 2197}
2202 2198
2203static void ieee80211_sta_conn_mon_timer(unsigned long data) 2199static void ieee80211_sta_conn_mon_timer(unsigned long data)
@@ -2210,7 +2206,7 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data)
2210 if (local->quiescing) 2206 if (local->quiescing)
2211 return; 2207 return;
2212 2208
2213 queue_work(local->hw.workqueue, &ifmgd->monitor_work); 2209 ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
2214} 2210}
2215 2211
2216static void ieee80211_sta_monitor_work(struct work_struct *work) 2212static void ieee80211_sta_monitor_work(struct work_struct *work)
@@ -2229,10 +2225,10 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
2229 IEEE80211_STA_CONNECTION_POLL); 2225 IEEE80211_STA_CONNECTION_POLL);
2230 2226
2231 /* let's probe the connection once */ 2227 /* let's probe the connection once */
2232 queue_work(sdata->local->hw.workqueue, 2228 ieee80211_queue_work(&sdata->local->hw,
2233 &sdata->u.mgd.monitor_work); 2229 &sdata->u.mgd.monitor_work);
2234 /* and do all the other regular work too */ 2230 /* and do all the other regular work too */
2235 queue_work(sdata->local->hw.workqueue, 2231 ieee80211_queue_work(&sdata->local->hw,
2236 &sdata->u.mgd.work); 2232 &sdata->u.mgd.work);
2237 } 2233 }
2238} 2234}
@@ -2393,7 +2389,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2393 list_add(&wk->list, &sdata->u.mgd.work_list); 2389 list_add(&wk->list, &sdata->u.mgd.work_list);
2394 mutex_unlock(&ifmgd->mtx); 2390 mutex_unlock(&ifmgd->mtx);
2395 2391
2396 queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work); 2392 ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
2397 return 0; 2393 return 0;
2398} 2394}
2399 2395
@@ -2467,7 +2463,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2467 else 2463 else
2468 ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; 2464 ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
2469 2465
2470 queue_work(sdata->local->hw.workqueue, &sdata->u.mgd.work); 2466 ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work);
2471 2467
2472 err = 0; 2468 err = 0;
2473 2469
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 3320f7daaf25..a5d2f1fb4417 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -26,7 +26,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
26 /* make quiescing visible to timers everywhere */ 26 /* make quiescing visible to timers everywhere */
27 mb(); 27 mb();
28 28
29 flush_workqueue(local->hw.workqueue); 29 flush_workqueue(local->workqueue);
30 30
31 /* Don't try to run timers while suspended. */ 31 /* Don't try to run timers while suspended. */
32 del_timer_sync(&local->sta_cleanup); 32 del_timer_sync(&local->sta_cleanup);
@@ -117,7 +117,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
117 * shouldn't be doing (or cancel everything in the 117 * shouldn't be doing (or cancel everything in the
118 * stop callback) that but better safe than sorry. 118 * stop callback) that but better safe than sorry.
119 */ 119 */
120 flush_workqueue(local->hw.workqueue); 120 flush_workqueue(local->workqueue);
121 121
122 local->suspended = true; 122 local->suspended = true;
123 /* need suspended to be visible before quiescing is false */ 123 /* need suspended to be visible before quiescing is false */
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 45731000eb8d..244f53f3c8b4 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -385,8 +385,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
385 spin_unlock_bh(&local->filter_lock); 385 spin_unlock_bh(&local->filter_lock);
386 386
387 /* TODO: start scan as soon as all nullfunc frames are ACKed */ 387 /* TODO: start scan as soon as all nullfunc frames are ACKed */
388 queue_delayed_work(local->hw.workqueue, &local->scan_work, 388 ieee80211_queue_delayed_work(&local->hw,
389 IEEE80211_CHANNEL_TIME); 389 &local->scan_work,
390 IEEE80211_CHANNEL_TIME);
390 391
391 return 0; 392 return 0;
392} 393}
@@ -715,8 +716,7 @@ void ieee80211_scan_work(struct work_struct *work)
715 } 716 }
716 } while (next_delay == 0); 717 } while (next_delay == 0);
717 718
718 queue_delayed_work(local->hw.workqueue, &local->scan_work, 719 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
719 next_delay);
720} 720}
721 721
722int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, 722int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 4e1b2ba122cd..7cffaa046b33 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1400,7 +1400,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1400 if (local->hw.conf.flags & IEEE80211_CONF_PS) { 1400 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
1401 ieee80211_stop_queues_by_reason(&local->hw, 1401 ieee80211_stop_queues_by_reason(&local->hw,
1402 IEEE80211_QUEUE_STOP_REASON_PS); 1402 IEEE80211_QUEUE_STOP_REASON_PS);
1403 queue_work(local->hw.workqueue, 1403 ieee80211_queue_work(&local->hw,
1404 &local->dynamic_ps_disable_work); 1404 &local->dynamic_ps_disable_work);
1405 } 1405 }
1406 1406
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 8502936e5314..e55d57f559ec 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -511,6 +511,46 @@ void ieee80211_iterate_active_interfaces_atomic(
511} 511}
512EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); 512EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
513 513
514/*
515 * Nothing should have been stuffed into the workqueue during
516 * the suspend->resume cycle. If this WARN is seen then there
517 * is a bug with either the driver suspend or something in
518 * mac80211 stuffing into the workqueue which we haven't yet
519 * cleared during mac80211's suspend cycle.
520 */
521static bool ieee80211_can_queue_work(struct ieee80211_local *local)
522{
523 if (WARN(local->suspended, "queueing ieee80211 work while "
524 "going to suspend\n"))
525 return false;
526
527 return true;
528}
529
530void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work)
531{
532 struct ieee80211_local *local = hw_to_local(hw);
533
534 if (!ieee80211_can_queue_work(local))
535 return;
536
537 queue_work(local->workqueue, work);
538}
539EXPORT_SYMBOL(ieee80211_queue_work);
540
541void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
542 struct delayed_work *dwork,
543 unsigned long delay)
544{
545 struct ieee80211_local *local = hw_to_local(hw);
546
547 if (!ieee80211_can_queue_work(local))
548 return;
549
550 queue_delayed_work(local->workqueue, dwork, delay);
551}
552EXPORT_SYMBOL(ieee80211_queue_delayed_work);
553
514void ieee802_11_parse_elems(u8 *start, size_t len, 554void ieee802_11_parse_elems(u8 *start, size_t len,
515 struct ieee802_11_elems *elems) 555 struct ieee802_11_elems *elems)
516{ 556{
@@ -1114,3 +1154,4 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1114#endif 1154#endif
1115 return 0; 1155 return 0;
1116} 1156}
1157