aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/sysfs.c
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2013-02-28 04:55:25 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-06 10:35:55 -0500
commit8125696991194aacb1173b6e8196d19098b44e17 (patch)
tree870dacf2225b328a8393be930128b056dfee0539 /net/wireless/sysfs.c
parent30c97120c6c7893e5c6857a16229699b2b79dfbe (diff)
cfg80211/mac80211: disconnect on suspend
If possible that after suspend, cfg80211 will receive request to disconnect what require action on interface that was removed during suspend. Problem can manifest itself by various warnings similar to below one: WARNING: at net/mac80211/driver-ops.h:12 ieee80211_bss_info_change_notify+0x2f9/0x300 [mac80211]() wlan0: Failed check-sdata-in-driver check, flags: 0x4 Call Trace: [<c043e0b3>] warn_slowpath_fmt+0x33/0x40 [<f83707c9>] ieee80211_bss_info_change_notify+0x2f9/0x300 [mac80211] [<f83a660a>] ieee80211_recalc_ps_vif+0x2a/0x30 [mac80211] [<f83a6706>] ieee80211_set_disassoc+0xf6/0x500 [mac80211] [<f83a9441>] ieee80211_mgd_deauth+0x1f1/0x280 [mac80211] [<f8381b36>] ieee80211_deauth+0x16/0x20 [mac80211] [<f8261e70>] cfg80211_mlme_down+0x70/0xc0 [cfg80211] [<f8264de1>] __cfg80211_disconnect+0x1b1/0x1d0 [cfg80211] To fix the problem disconnect from any associated network before suspend. User space is responsible to establish connection again after resume. This basically need to be done by user space anyway, because associated stations can go away during suspend (for example NetworkManager disconnects on suspend and connect on resume by default). Patch also handle situation when driver refuse to suspend with wowlan configured and try to suspend again without it. Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/sysfs.c')
-rw-r--r--net/wireless/sysfs.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 238ee49b3868..8f28b9f798d8 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -83,6 +83,14 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
83 return 0; 83 return 0;
84} 84}
85 85
86static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
87{
88 struct wireless_dev *wdev;
89
90 list_for_each_entry(wdev, &rdev->wdev_list, list)
91 cfg80211_leave(rdev, wdev);
92}
93
86static int wiphy_suspend(struct device *dev, pm_message_t state) 94static int wiphy_suspend(struct device *dev, pm_message_t state)
87{ 95{
88 struct cfg80211_registered_device *rdev = dev_to_rdev(dev); 96 struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
@@ -90,12 +98,19 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
90 98
91 rdev->suspend_at = get_seconds(); 99 rdev->suspend_at = get_seconds();
92 100
93 if (rdev->ops->suspend) { 101 rtnl_lock();
94 rtnl_lock(); 102 if (rdev->wiphy.registered) {
95 if (rdev->wiphy.registered) 103 if (!rdev->wowlan)
96 ret = rdev_suspend(rdev); 104 cfg80211_leave_all(rdev);
97 rtnl_unlock(); 105 if (rdev->ops->suspend)
106 ret = rdev_suspend(rdev, rdev->wowlan);
107 if (ret == 1) {
108 /* Driver refuse to configure wowlan */
109 cfg80211_leave_all(rdev);
110 ret = rdev_suspend(rdev, NULL);
111 }
98 } 112 }
113 rtnl_unlock();
99 114
100 return ret; 115 return ret;
101} 116}