diff options
Diffstat (limited to 'net/mac80211/pm.c')
-rw-r--r-- | net/mac80211/pm.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index ca405b6b686d..ac6ad6238e3a 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -59,9 +59,26 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
59 | cancel_work_sync(&local->dynamic_ps_enable_work); | 59 | cancel_work_sync(&local->dynamic_ps_enable_work); |
60 | del_timer_sync(&local->dynamic_ps_timer); | 60 | del_timer_sync(&local->dynamic_ps_timer); |
61 | 61 | ||
62 | local->wowlan = wowlan && local->open_count; | 62 | local->wowlan = wowlan; |
63 | if (local->wowlan) { | 63 | if (local->wowlan) { |
64 | int err = drv_suspend(local, wowlan); | 64 | int err; |
65 | |||
66 | /* Drivers don't expect to suspend while some operations like | ||
67 | * authenticating or associating are in progress. It doesn't | ||
68 | * make sense anyway to accept that, since the authentication | ||
69 | * or association would never finish since the driver can't do | ||
70 | * that on its own. | ||
71 | * Thus, clean up in-progress auth/assoc first. | ||
72 | */ | ||
73 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
74 | if (!ieee80211_sdata_running(sdata)) | ||
75 | continue; | ||
76 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
77 | continue; | ||
78 | ieee80211_mgd_quiesce(sdata); | ||
79 | } | ||
80 | |||
81 | err = drv_suspend(local, wowlan); | ||
65 | if (err < 0) { | 82 | if (err < 0) { |
66 | local->quiescing = false; | 83 | local->quiescing = false; |
67 | local->wowlan = false; | 84 | local->wowlan = false; |
@@ -80,6 +97,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
80 | return err; | 97 | return err; |
81 | } else if (err > 0) { | 98 | } else if (err > 0) { |
82 | WARN_ON(err != 1); | 99 | WARN_ON(err != 1); |
100 | /* cfg80211 will call back into mac80211 to disconnect | ||
101 | * all interfaces, allow that to proceed properly | ||
102 | */ | ||
103 | ieee80211_wake_queues_by_reason(hw, | ||
104 | IEEE80211_MAX_QUEUE_MAP, | ||
105 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | ||
106 | false); | ||
83 | return err; | 107 | return err; |
84 | } else { | 108 | } else { |
85 | goto suspend; | 109 | goto suspend; |