aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/pm.c')
-rw-r--r--net/mac80211/pm.c36
1 files changed, 12 insertions, 24 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index e535f1c988fe..d287fde0431d 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -10,9 +10,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
10{ 10{
11 struct ieee80211_local *local = hw_to_local(hw); 11 struct ieee80211_local *local = hw_to_local(hw);
12 struct ieee80211_sub_if_data *sdata; 12 struct ieee80211_sub_if_data *sdata;
13 struct ieee80211_if_init_conf conf;
14 struct sta_info *sta; 13 struct sta_info *sta;
15 unsigned long flags;
16 14
17 ieee80211_scan_cancel(local); 15 ieee80211_scan_cancel(local);
18 16
@@ -42,39 +40,32 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
42 list_for_each_entry(sdata, &local->interfaces, list) 40 list_for_each_entry(sdata, &local->interfaces, list)
43 ieee80211_disable_keys(sdata); 41 ieee80211_disable_keys(sdata);
44 42
45 /* Tear down aggregation sessions */ 43 /* tear down aggregation sessions and remove STAs */
46 44 mutex_lock(&local->sta_mtx);
47 rcu_read_lock(); 45 list_for_each_entry(sta, &local->sta_list, list) {
48 46 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
49 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 47 set_sta_flags(sta, WLAN_STA_BLOCK_BA);
50 list_for_each_entry_rcu(sta, &local->sta_list, list) {
51 set_sta_flags(sta, WLAN_STA_SUSPEND);
52 ieee80211_sta_tear_down_BA_sessions(sta); 48 ieee80211_sta_tear_down_BA_sessions(sta);
53 } 49 }
54 }
55 50
56 rcu_read_unlock(); 51 if (sta->uploaded) {
57
58 /* remove STAs */
59 spin_lock_irqsave(&local->sta_lock, flags);
60 list_for_each_entry(sta, &local->sta_list, list) {
61 if (local->ops->sta_notify) {
62 sdata = sta->sdata; 52 sdata = sta->sdata;
63 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 53 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
64 sdata = container_of(sdata->bss, 54 sdata = container_of(sdata->bss,
65 struct ieee80211_sub_if_data, 55 struct ieee80211_sub_if_data,
66 u.ap); 56 u.ap);
67 57
68 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, 58 drv_sta_remove(local, sdata, &sta->sta);
69 &sta->sta);
70 } 59 }
71 60
72 mesh_plink_quiesce(sta); 61 mesh_plink_quiesce(sta);
73 } 62 }
74 spin_unlock_irqrestore(&local->sta_lock, flags); 63 mutex_unlock(&local->sta_mtx);
75 64
76 /* remove all interfaces */ 65 /* remove all interfaces */
77 list_for_each_entry(sdata, &local->interfaces, list) { 66 list_for_each_entry(sdata, &local->interfaces, list) {
67 cancel_work_sync(&sdata->work);
68
78 switch(sdata->vif.type) { 69 switch(sdata->vif.type) {
79 case NL80211_IFTYPE_STATION: 70 case NL80211_IFTYPE_STATION:
80 ieee80211_sta_quiesce(sdata); 71 ieee80211_sta_quiesce(sdata);
@@ -93,17 +84,14 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
93 break; 84 break;
94 } 85 }
95 86
96 if (!netif_running(sdata->dev)) 87 if (!ieee80211_sdata_running(sdata))
97 continue; 88 continue;
98 89
99 /* disable beaconing */ 90 /* disable beaconing */
100 ieee80211_bss_info_change_notify(sdata, 91 ieee80211_bss_info_change_notify(sdata,
101 BSS_CHANGED_BEACON_ENABLED); 92 BSS_CHANGED_BEACON_ENABLED);
102 93
103 conf.vif = &sdata->vif; 94 drv_remove_interface(local, &sdata->vif);
104 conf.type = sdata->vif.type;
105 conf.mac_addr = sdata->dev->dev_addr;
106 drv_remove_interface(local, &conf);
107 } 95 }
108 96
109 /* stop hardware - this must stop RX */ 97 /* stop hardware - this must stop RX */