diff options
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r-- | net/wireless/reg.c | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 06d050da0d94..050d7948dd68 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -425,6 +425,11 @@ static bool is_user_regdom_saved(void) return true; } +static bool is_cfg80211_regdom_intersected(void) +{ + return is_intersected_alpha2(get_cfg80211_regdom()->alpha2); +} + static const struct ieee80211_regdomain * reg_copy_regd(const struct ieee80211_regdomain *src_regd) { @@ -1676,12 +1681,48 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy) { struct wireless_dev *wdev; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); - + struct net_device *dev; + struct cfg80211_sched_scan_request *sched_scan_req; ASSERT_RTNL(); - list_for_each_entry(wdev, &rdev->wdev_list, list) - if (!reg_wdev_chan_valid(wiphy, wdev)) - cfg80211_leave(rdev, wdev); + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) + if (!reg_wdev_chan_valid(wiphy, wdev)) { + dev = wdev->netdev; + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: + cfg80211_leave_ibss(rdev, dev, true); + break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + ASSERT_RTNL(); + sched_scan_req = rtnl_dereference(rdev->sched_scan_req); + if (sched_scan_req && dev == sched_scan_req->dev) + __cfg80211_stop_sched_scan(rdev, false); + + wdev_lock(wdev); +#ifdef CONFIG_CFG80211_WEXT + kfree(wdev->wext.ie); + wdev->wext.ie = NULL; + wdev->wext.ie_len = 0; + wdev->wext.connect.auth_type = + NL80211_AUTHTYPE_AUTOMATIC; +#endif + cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, true); + cfg80211_mlme_down(rdev, dev); + wdev_unlock(wdev); + break; + case NL80211_IFTYPE_MESH_POINT: + cfg80211_leave_mesh(rdev, dev); + break; + case NL80211_IFTYPE_AP: + cfg80211_stop_ap(rdev, dev, false); + break; + default: + break; + } + wdev->beacon_interval = 0; + } } static void reg_check_chans_work(struct work_struct *work) @@ -1941,9 +1982,14 @@ __reg_process_hint_user(struct regulatory_request *user_request) */ if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE || lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || - lr->initiator == NL80211_REGDOM_SET_BY_USER) && - regdom_changes(lr->alpha2)) - return REG_REQ_IGNORE; + lr->initiator == NL80211_REGDOM_SET_BY_USER)) { + if (lr->intersect) { + if (!is_cfg80211_regdom_intersected()) + return REG_REQ_IGNORE; + } else if (regdom_changes(lr->alpha2)) { + return REG_REQ_IGNORE; + } + } if (!regdom_changes(user_request->alpha2)) return REG_REQ_ALREADY_SET; @@ -2399,6 +2445,7 @@ int regulatory_hint_user(const char *alpha2, return 0; } +EXPORT_SYMBOL(regulatory_hint_user); int regulatory_hint_indoor(bool is_indoor, u32 portid) { |