aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-07-14 10:48:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-15 13:39:42 -0400
commit94f9b97be5b3bf67392e43fb7f567721b09142c2 (patch)
tree4ffbf7480eeb60baf40f63070439f96e9a92c7e7
parent3f29c522184ffb44fd475fdbe6083023ab1506f8 (diff)
mac80211: be more careful in suspend/resume
When suspending with all netdevs down, the device is stopped but we still call a number of driver callbacks that the driver might not expect. The same happens during resume, we might call a few callbacks without starting the driver. Fix this by checking open_count around more things and exiting quickly if it is 0. Also, while at this I noticed that the coverage class isn't reprogrammed after resume, so add that. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/pm.c3
-rw-r--r--net/mac80211/util.c54
2 files changed, 31 insertions, 26 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index f87e993e713b..6326d3439861 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -34,6 +34,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
34 struct ieee80211_sub_if_data *sdata; 34 struct ieee80211_sub_if_data *sdata;
35 struct sta_info *sta; 35 struct sta_info *sta;
36 36
37 if (!local->open_count)
38 goto suspend;
39
37 ieee80211_scan_cancel(local); 40 ieee80211_scan_cancel(local);
38 41
39 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 42 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 5bfb80cba634..8c2df33fd7e8 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1157,27 +1157,37 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1157 } 1157 }
1158#endif 1158#endif
1159 1159
1160 /* restart hardware */ 1160 /* setup fragmentation threshold */
1161 if (local->open_count) { 1161 drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
1162 /* 1162
1163 * Upon resume hardware can sometimes be goofy due to 1163 /* setup RTS threshold */
1164 * various platform / driver / bus issues, so restarting 1164 drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
1165 * the device may at times not work immediately. Propagate 1165
1166 * the error. 1166 /* reset coverage class */
1167 */ 1167 drv_set_coverage_class(local, hw->wiphy->coverage_class);
1168 res = drv_start(local); 1168
1169 if (res) { 1169 /* everything else happens only if HW was up & running */
1170 WARN(local->suspended, "Hardware became unavailable " 1170 if (!local->open_count)
1171 "upon resume. This could be a software issue " 1171 goto wake_up;
1172 "prior to suspend or a hardware issue.\n");
1173 return res;
1174 }
1175 1172
1176 ieee80211_led_radio(local, true); 1173 /*
1177 ieee80211_mod_tpt_led_trig(local, 1174 * Upon resume hardware can sometimes be goofy due to
1178 IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); 1175 * various platform / driver / bus issues, so restarting
1176 * the device may at times not work immediately. Propagate
1177 * the error.
1178 */
1179 res = drv_start(local);
1180 if (res) {
1181 WARN(local->suspended, "Hardware became unavailable "
1182 "upon resume. This could be a software issue "
1183 "prior to suspend or a hardware issue.\n");
1184 return res;
1179 } 1185 }
1180 1186
1187 ieee80211_led_radio(local, true);
1188 ieee80211_mod_tpt_led_trig(local,
1189 IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
1190
1181 /* add interfaces */ 1191 /* add interfaces */
1182 list_for_each_entry(sdata, &local->interfaces, list) { 1192 list_for_each_entry(sdata, &local->interfaces, list) {
1183 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 1193 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
@@ -1201,12 +1211,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1201 } 1211 }
1202 mutex_unlock(&local->sta_mtx); 1212 mutex_unlock(&local->sta_mtx);
1203 1213
1204 /* setup fragmentation threshold */
1205 drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
1206
1207 /* setup RTS threshold */
1208 drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
1209
1210 /* reconfigure hardware */ 1214 /* reconfigure hardware */
1211 ieee80211_hw_config(local, ~0); 1215 ieee80211_hw_config(local, ~0);
1212 1216
@@ -1287,9 +1291,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1287 if (ieee80211_sdata_running(sdata)) 1291 if (ieee80211_sdata_running(sdata))
1288 ieee80211_enable_keys(sdata); 1292 ieee80211_enable_keys(sdata);
1289 1293
1290#ifdef CONFIG_PM
1291 wake_up: 1294 wake_up:
1292#endif
1293 ieee80211_wake_queues_by_reason(hw, 1295 ieee80211_wake_queues_by_reason(hw,
1294 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 1296 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
1295 1297