diff options
Diffstat (limited to 'net/wireless/sme.c')
| -rw-r--r-- | net/wireless/sme.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index dc0fc4989d54..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 | ||
| 37 | bool 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 | |||
| 66 | static void disconnect_work(struct work_struct *work) | ||
| 67 | { | ||
| 68 | if (!cfg80211_is_all_idle()) | ||
| 69 | return; | ||
| 70 | |||
| 71 | regulatory_hint_disconnect(); | ||
| 72 | } | ||
| 73 | |||
| 74 | static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); | ||
| 37 | 75 | ||
| 38 | static int cfg80211_conn_scan(struct wireless_dev *wdev) | 76 | static int cfg80211_conn_scan(struct wireless_dev *wdev) |
| 39 | { | 77 | { |
| @@ -454,6 +492,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
| 454 | * - and country_ie[1] which is the IE length | 492 | * - and country_ie[1] which is the IE length |
| 455 | */ | 493 | */ |
| 456 | regulatory_hint_11d(wdev->wiphy, | 494 | regulatory_hint_11d(wdev->wiphy, |
| 495 | bss->channel->band, | ||
| 457 | country_ie + 2, | 496 | country_ie + 2, |
| 458 | country_ie[1]); | 497 | country_ie[1]); |
| 459 | } | 498 | } |
| @@ -657,6 +696,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
| 657 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | 696 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); |
| 658 | wdev->wext.connect.ssid_len = 0; | 697 | wdev->wext.connect.ssid_len = 0; |
| 659 | #endif | 698 | #endif |
| 699 | |||
| 700 | schedule_work(&cfg80211_disconnect_work); | ||
| 660 | } | 701 | } |
| 661 | 702 | ||
| 662 | void cfg80211_disconnected(struct net_device *dev, u16 reason, | 703 | void cfg80211_disconnected(struct net_device *dev, u16 reason, |
