summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-07-14 16:48:54 +0200
committerJohn W. Linville <linville@tuxdriver.com>2011-07-15 13:39:42 -0400
commit94f9b97be5b3bf67392e43fb7f567721b09142c2 (patch)
tree4ffbf7480eeb60baf40f63070439f96e9a92c7e7 /net
parent3f29c522184ffb44fd475fdbe6083023ab1506f8 (diff)
downloadlinux-94f9b97be5b3bf67392e43fb7f567721b09142c2.tar.gz
linux-94f9b97be5b3bf67392e43fb7f567721b09142c2.tar.bz2
linux-94f9b97be5b3bf67392e43fb7f567721b09142c2.zip
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>
Diffstat (limited to 'net')
-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)
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
+ if (!local->open_count)
+ goto suspend;
+
ieee80211_scan_cancel(local);
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)
}
#endif
- /* restart hardware */
- if (local->open_count) {
- /*
- * Upon resume hardware can sometimes be goofy due to
- * various platform / driver / bus issues, so restarting
- * the device may at times not work immediately. Propagate
- * the error.
- */
- res = drv_start(local);
- if (res) {
- WARN(local->suspended, "Hardware became unavailable "
- "upon resume. This could be a software issue "
- "prior to suspend or a hardware issue.\n");
- return res;
- }
+ /* setup fragmentation threshold */
+ drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
+
+ /* setup RTS threshold */
+ drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
+
+ /* reset coverage class */
+ drv_set_coverage_class(local, hw->wiphy->coverage_class);
+
+ /* everything else happens only if HW was up & running */
+ if (!local->open_count)
+ goto wake_up;
- ieee80211_led_radio(local, true);
- ieee80211_mod_tpt_led_trig(local,
- IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
+ /*
+ * Upon resume hardware can sometimes be goofy due to
+ * various platform / driver / bus issues, so restarting
+ * the device may at times not work immediately. Propagate
+ * the error.
+ */
+ res = drv_start(local);
+ if (res) {
+ WARN(local->suspended, "Hardware became unavailable "
+ "upon resume. This could be a software issue "
+ "prior to suspend or a hardware issue.\n");
+ return res;
}
+ ieee80211_led_radio(local, true);
+ ieee80211_mod_tpt_led_trig(local,
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
+
/* add interfaces */
list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
@@ -1201,12 +1211,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
}
mutex_unlock(&local->sta_mtx);
- /* setup fragmentation threshold */
- drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
-
- /* setup RTS threshold */
- drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
-
/* reconfigure hardware */
ieee80211_hw_config(local, ~0);
@@ -1287,9 +1291,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (ieee80211_sdata_running(sdata))
ieee80211_enable_keys(sdata);
-#ifdef CONFIG_PM
wake_up:
-#endif
ieee80211_wake_queues_by_reason(hw,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);