aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/sme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/sme.c')
-rw-r--r--net/wireless/sme.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 745c37e7992e..17fde0da1b08 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -34,6 +34,44 @@ struct cfg80211_conn {
34 bool auto_auth, prev_bssid_valid; 34 bool auto_auth, prev_bssid_valid;
35}; 35};
36 36
37bool cfg80211_is_all_idle(void)
38{
39 struct cfg80211_registered_device *rdev;
40 struct wireless_dev *wdev;
41 bool is_all_idle = true;
42
43 mutex_lock(&cfg80211_mutex);
44
45 /*
46 * All devices must be idle as otherwise if you are actively
47 * scanning some new beacon hints could be learned and would
48 * count as new regulatory hints.
49 */
50 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
51 cfg80211_lock_rdev(rdev);
52 list_for_each_entry(wdev, &rdev->netdev_list, list) {
53 wdev_lock(wdev);
54 if (wdev->sme_state != CFG80211_SME_IDLE)
55 is_all_idle = false;
56 wdev_unlock(wdev);
57 }
58 cfg80211_unlock_rdev(rdev);
59 }
60
61 mutex_unlock(&cfg80211_mutex);
62
63 return is_all_idle;
64}
65
66static void disconnect_work(struct work_struct *work)
67{
68 if (!cfg80211_is_all_idle())
69 return;
70
71 regulatory_hint_disconnect();
72}
73
74static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
37 75
38static int cfg80211_conn_scan(struct wireless_dev *wdev) 76static int cfg80211_conn_scan(struct wireless_dev *wdev)
39{ 77{
@@ -658,6 +696,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
658 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 696 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
659 wdev->wext.connect.ssid_len = 0; 697 wdev->wext.connect.ssid_len = 0;
660#endif 698#endif
699
700 schedule_work(&cfg80211_disconnect_work);
661} 701}
662 702
663void cfg80211_disconnected(struct net_device *dev, u16 reason, 703void cfg80211_disconnected(struct net_device *dev, u16 reason,