aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-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 aca22b00b6a3..07e7e41816be 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -721,7 +721,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
721{ 721{
722 struct ieee80211_local *local = (void *) data; 722 struct ieee80211_local *local = (void *) data;
723 723
724 if (local->quiescing) 724 if (local->quiescing || local->suspended)
725 return; 725 return;
726 726
727 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); 727 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 de5bba7f910a..0936fc24942d 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2453,6 +2453,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
2453 return; 2453 return;
2454 } 2454 }
2455 2455
2456 /*
2457 * If we're suspending, it is possible although not too likely
2458 * that we'd be receiving frames after having already partially
2459 * quiesced the stack. We can't process such frames then since
2460 * that might, for example, cause stations to be added or other
2461 * driver callbacks be invoked.
2462 */
2463 if (unlikely(local->quiescing || local->suspended)) {
2464 kfree_skb(skb);
2465 return;
2466 }
2467
2456 if (status->flag & RX_FLAG_HT) { 2468 if (status->flag & RX_FLAG_HT) {
2457 /* rate_idx is MCS index */ 2469 /* rate_idx is MCS index */
2458 if (WARN_ON(status->rate_idx < 0 || 2470 if (WARN_ON(status->rate_idx < 0 ||