diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-07-14 16:48:54 +0200 |
---|---|---|
committer | John Rigby <john.rigby@linaro.org> | 2011-10-17 09:53:22 -0600 |
commit | ce689c08b8fed720ce6f4cee3f3527e49dcc29a8 (patch) | |
tree | b123db9e49a3c3e6bd8f828df4a28cc00543525f | |
parent | c177f39edd6813c3200bdb1392899113aa9a0130 (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>
-rw-r--r-- | net/mac80211/pm.c | 3 | ||||
-rw-r--r-- | net/mac80211/util.c | 52 |
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); |