Merge commit 'c1e140bf79d817d4a7aa9932eb98b0359c87af33' from mac80211-next
[cascardo/linux.git] / net / wireless / core.c
index 53dda77..3af0ecf 100644 (file)
@@ -320,6 +320,20 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work)
        rtnl_unlock();
 }
 
+static void cfg80211_sched_scan_stop_wk(struct work_struct *work)
+{
+       struct cfg80211_registered_device *rdev;
+
+       rdev = container_of(work, struct cfg80211_registered_device,
+                          sched_scan_stop_wk);
+
+       rtnl_lock();
+
+       __cfg80211_stop_sched_scan(rdev, false);
+
+       rtnl_unlock();
+}
+
 /* exported functions */
 
 struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
@@ -406,6 +420,7 @@ use_default_name:
        INIT_LIST_HEAD(&rdev->destroy_list);
        spin_lock_init(&rdev->destroy_list_lock);
        INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
+       INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
 
 #ifdef CONFIG_CFG80211_DEFAULT_PS
        rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -560,6 +575,14 @@ int wiphy_register(struct wiphy *wiphy)
                                       BIT(NL80211_IFTYPE_MONITOR)))
                wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
 
+       if (WARN_ON((wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) &&
+                   (wiphy->regulatory_flags &
+                                       (REGULATORY_CUSTOM_REG |
+                                        REGULATORY_STRICT_REG |
+                                        REGULATORY_COUNTRY_IE_FOLLOW_POWER |
+                                        REGULATORY_COUNTRY_IE_IGNORE))))
+               return -EINVAL;
+
        if (WARN_ON(wiphy->coalesce &&
                    (!wiphy->coalesce->n_rules ||
                     !wiphy->coalesce->n_patterns) &&
@@ -778,6 +801,7 @@ void wiphy_unregister(struct wiphy *wiphy)
        flush_work(&rdev->event_work);
        cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
        flush_work(&rdev->destroy_work);
+       flush_work(&rdev->sched_scan_stop_wk);
 
 #ifdef CONFIG_PM
        if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
@@ -858,6 +882,7 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
                      struct wireless_dev *wdev)
 {
        struct net_device *dev = wdev->netdev;
+       struct cfg80211_sched_scan_request *sched_scan_req;
 
        ASSERT_RTNL();
        ASSERT_WDEV_LOCK(wdev);
@@ -868,7 +893,8 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
        case NL80211_IFTYPE_STATION:
-               if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev)
+               sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
+               if (sched_scan_req && dev == sched_scan_req->dev)
                        __cfg80211_stop_sched_scan(rdev, false);
 
 #ifdef CONFIG_CFG80211_WEXT
@@ -943,6 +969,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev;
+       struct cfg80211_sched_scan_request *sched_scan_req;
 
        if (!wdev)
                return NOTIFY_DONE;
@@ -1007,8 +1034,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                        ___cfg80211_scan_done(rdev, false);
                }
 
-               if (WARN_ON(rdev->sched_scan_req &&
-                           rdev->sched_scan_req->dev == wdev->netdev)) {
+               sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
+               if (WARN_ON(sched_scan_req &&
+                           sched_scan_req->dev == wdev->netdev)) {
                        __cfg80211_stop_sched_scan(rdev, false);
                }