aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/mlme.c2
-rw-r--r--net/mac80211/pm.c24
-rw-r--r--net/mac80211/rx.c12
3 files changed, 28 insertions, 10 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f60a83102ea2..ee83125ed179 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -760,7 +760,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
760{ 760{
761 struct ieee80211_local *local = (void *) data; 761 struct ieee80211_local *local = (void *) data;
762 762
763 if (local->quiescing) 763 if (local->quiescing || local->suspended)
764 return; 764 return;
765 765
766 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); 766 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 7a549f9deb96..5e3d476972f9 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -55,15 +55,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
55 55
56 rcu_read_unlock(); 56 rcu_read_unlock();
57 57
58 /* flush again, in case driver queued work */
59 flush_workqueue(local->hw.workqueue);
60
61 /* stop hardware - this must stop RX */
62 if (local->open_count) {
63 ieee80211_led_radio(local, false);
64 drv_stop(local);
65 }
66
67 /* remove STAs */ 58 /* remove STAs */
68 spin_lock_irqsave(&local->sta_lock, flags); 59 spin_lock_irqsave(&local->sta_lock, flags);
69 list_for_each_entry(sta, &local->sta_list, list) { 60 list_for_each_entry(sta, &local->sta_list, list) {
@@ -111,7 +102,22 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
111 drv_remove_interface(local, &conf); 102 drv_remove_interface(local, &conf);
112 } 103 }
113 104
105 /* stop hardware - this must stop RX */
106 if (local->open_count) {
107 ieee80211_led_radio(local, false);
108 drv_stop(local);
109 }
110
111 /*
112 * flush again, in case driver queued work -- it
113 * shouldn't be doing (or cancel everything in the
114 * stop callback) that but better safe than sorry.
115 */
116 flush_workqueue(local->hw.workqueue);
117
114 local->suspended = true; 118 local->suspended = true;
119 /* need suspended to be visible before quiescing is false */
120 barrier();
115 local->quiescing = false; 121 local->quiescing = false;
116 122
117 return 0; 123 return 0;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index f195705146bd..25a669c86e14 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2442,6 +2442,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
2442 return; 2442 return;
2443 } 2443 }
2444 2444
2445 /*
2446 * If we're suspending, it is possible although not too likely
2447 * that we'd be receiving frames after having already partially
2448 * quiesced the stack. We can't process such frames then since
2449 * that might, for example, cause stations to be added or other
2450 * driver callbacks be invoked.
2451 */
2452 if (unlikely(local->quiescing || local->suspended)) {
2453 kfree_skb(skb);
2454 return;
2455 }
2456
2445 if (status->flag & RX_FLAG_HT) { 2457 if (status->flag & RX_FLAG_HT) {
2446 /* rate_idx is MCS index */ 2458 /* rate_idx is MCS index */
2447 if (WARN_ON(status->rate_idx < 0 || 2459 if (WARN_ON(status->rate_idx < 0 ||