aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-07-14 16:48:54 +0200
committerJohn Rigby <john.rigby@linaro.org>2011-09-23 08:55:29 -0600
commit2603de4dd8fccb7cb5e247140a6670e486ff2ddf (patch)
tree0b8a849d4ae74494c1533ccd9b5bd4609df75e59 /net
parentfb3ce4ef43a6a95da0f7f0d54546c3cdaa17fe4c (diff)
mac80211: be more careful in suspend/resume
BugLink: http://bugs.launchpad.net/bugs/811214 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> (cherry picked from commit 94f9b97be5b3bf67392e43fb7f567721b09142c2) Signed-off-by: Leann Ogasawara <leann.ogasawara@canonical.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/pm.c3
-rw-r--r--net/mac80211/util.c52
2 files changed, 31 insertions, 24 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 730778a2c90..850979bf62a 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -12,6 +12,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 d3fe2d23748..4a10c41a564 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1146,27 +1146,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);
- ieee80211_led_radio(local, true);
- ieee80211_mod_tpt_led_trig(local,
- IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
+ /* everything else happens only if HW was up & running */
+ if (!local->open_count)
+ goto wake_up;
+
+ /*
+ * 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 &&
@@ -1190,12 +1200,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);