aboutsummaryrefslogtreecommitdiffstats
path: root/net
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 /net
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>
Diffstat (limited to 'net')
-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
11 files changed, 92 insertions, 49 deletions
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