aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/pm.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-04-14 04:09:24 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:57:14 -0400
commitf2753ddbadb0873a98421415882318251bbd9eaa (patch)
treedaad40232be13d91835b30234e5743dfdd582f19 /net/mac80211/pm.c
parenta1c555802a62c845520d2486d783c9bb1d5e68a9 (diff)
mac80211: add hardware restart function
Some hardware defects may require the hardware to be re-initialised completely from scratch. Drivers would need much information (for instance the current MAC address, crypto keys, beaconing information, etc.) stored duplicated from mac80211 to be able to do this, so let mac80211 help them. The new ieee80211_restart_hw() function requires the same code as resuming, so move that code into a new ieee80211_reconfig() function in util.c and leave only the suspend code in pm.c. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/pm.c')
-rw-r--r--net/mac80211/pm.c110
1 files changed, 5 insertions, 105 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 2b4c95cd9daf..b38986c9deef 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -72,108 +72,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
72 return 0; 72 return 0;
73} 73}
74 74
75int __ieee80211_resume(struct ieee80211_hw *hw) 75/*
76{ 76 * __ieee80211_resume() is a static inline which just calls
77 struct ieee80211_local *local = hw_to_local(hw); 77 * ieee80211_reconfig(), which is also needed for hardware
78 struct ieee80211_sub_if_data *sdata; 78 * hang/firmware failure/etc. recovery.
79 struct ieee80211_if_init_conf conf; 79 */
80 struct sta_info *sta;
81 unsigned long flags;
82 int res;
83
84 /* restart hardware */
85 if (local->open_count) {
86 res = local->ops->start(hw);
87
88 ieee80211_led_radio(local, hw->conf.radio_enabled);
89 }
90
91 /* add interfaces */
92 list_for_each_entry(sdata, &local->interfaces, list) {
93 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
94 sdata->vif.type != NL80211_IFTYPE_MONITOR &&
95 netif_running(sdata->dev)) {
96 conf.vif = &sdata->vif;
97 conf.type = sdata->vif.type;
98 conf.mac_addr = sdata->dev->dev_addr;
99 res = local->ops->add_interface(hw, &conf);
100 }
101 }
102
103 /* add STAs back */
104 if (local->ops->sta_notify) {
105 spin_lock_irqsave(&local->sta_lock, flags);
106 list_for_each_entry(sta, &local->sta_list, list) {
107 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
108 sdata = container_of(sdata->bss,
109 struct ieee80211_sub_if_data,
110 u.ap);
111
112 local->ops->sta_notify(hw, &sdata->vif,
113 STA_NOTIFY_ADD, &sta->sta);
114 }
115 spin_unlock_irqrestore(&local->sta_lock, flags);
116 }
117
118 /* Clear Suspend state so that ADDBA requests can be processed */
119
120 rcu_read_lock();
121
122 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
123 list_for_each_entry_rcu(sta, &local->sta_list, list) {
124 clear_sta_flags(sta, WLAN_STA_SUSPEND);
125 }
126 }
127
128 rcu_read_unlock();
129
130 /* setup RTS threshold */
131 if (local->ops->set_rts_threshold)
132 local->ops->set_rts_threshold(hw, local->rts_threshold);
133
134 /* reconfigure hardware */
135 ieee80211_hw_config(local, ~0);
136
137 netif_addr_lock_bh(local->mdev);
138 ieee80211_configure_filter(local);
139 netif_addr_unlock_bh(local->mdev);
140
141 /* Finally also reconfigure all the BSS information */
142 list_for_each_entry(sdata, &local->interfaces, list) {
143 u32 changed = ~0;
144 if (!netif_running(sdata->dev))
145 continue;
146 switch (sdata->vif.type) {
147 case NL80211_IFTYPE_STATION:
148 /* disable beacon change bits */
149 changed &= ~IEEE80211_IFCC_BEACON;
150 /* fall through */
151 case NL80211_IFTYPE_ADHOC:
152 case NL80211_IFTYPE_AP:
153 case NL80211_IFTYPE_MESH_POINT:
154 WARN_ON(ieee80211_if_config(sdata, changed));
155 ieee80211_bss_info_change_notify(sdata, ~0);
156 break;
157 case NL80211_IFTYPE_WDS:
158 break;
159 case NL80211_IFTYPE_AP_VLAN:
160 case NL80211_IFTYPE_MONITOR:
161 /* ignore virtual */
162 break;
163 case NL80211_IFTYPE_UNSPECIFIED:
164 case __NL80211_IFTYPE_AFTER_LAST:
165 WARN_ON(1);
166 break;
167 }
168 }
169
170 /* add back keys */
171 list_for_each_entry(sdata, &local->interfaces, list)
172 if (netif_running(sdata->dev))
173 ieee80211_enable_keys(sdata);
174
175 ieee80211_wake_queues_by_reason(hw,
176 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
177
178 return 0;
179}