net: pass info struct via netdevice notifier
[firefly-linux-kernel-4.4.55.git] / net / wireless / core.c
index 6ddf74f0ae1e5ace4346f3c0cf6b4f1ce13fa580..01e41191f1bf7f59c502f4c2499ad71304e6e4e9 100644 (file)
@@ -638,17 +638,21 @@ int wiphy_register(struct wiphy *wiphy)
         * cfg80211_mutex lock
         */
        res = rfkill_register(rdev->rfkill);
-       if (res)
-               goto out_rm_dev;
+       if (res) {
+               device_del(&rdev->wiphy.dev);
+
+               mutex_lock(&cfg80211_mutex);
+               debugfs_remove_recursive(rdev->wiphy.debugfsdir);
+               list_del_rcu(&rdev->list);
+               wiphy_regulatory_deregister(wiphy);
+               mutex_unlock(&cfg80211_mutex);
+               return res;
+       }
 
        rtnl_lock();
        rdev->wiphy.registered = true;
        rtnl_unlock();
        return 0;
-
-out_rm_dev:
-       device_del(&rdev->wiphy.dev);
-       return res;
 }
 EXPORT_SYMBOL(wiphy_register);
 
@@ -842,11 +846,49 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
                rdev->num_running_monitor_ifaces += num;
 }
 
+void cfg80211_leave(struct cfg80211_registered_device *rdev,
+                  struct wireless_dev *wdev)
+{
+       struct net_device *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:
+               mutex_lock(&rdev->sched_scan_mtx);
+               __cfg80211_stop_sched_scan(rdev, false);
+               mutex_unlock(&rdev->sched_scan_mtx);
+
+               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);
+               wdev_unlock(wdev);
+               break;
+       case NL80211_IFTYPE_MESH_POINT:
+               cfg80211_leave_mesh(rdev, dev);
+               break;
+       case NL80211_IFTYPE_AP:
+               cfg80211_stop_ap(rdev, dev);
+               break;
+       default:
+               break;
+       }
+
+       wdev->beacon_interval = 0;
+}
+
 static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
-                                        unsigned long state,
-                                        void *ndev)
+                                        unsigned long state, void *ptr)
 {
-       struct net_device *dev = ndev;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev;
        int ret;
@@ -910,38 +952,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                        dev->priv_flags |= IFF_DONT_BRIDGE;
                break;
        case NETDEV_GOING_DOWN:
-               switch (wdev->iftype) {
-               case NL80211_IFTYPE_ADHOC:
-                       cfg80211_leave_ibss(rdev, dev, true);
-                       break;
-               case NL80211_IFTYPE_P2P_CLIENT:
-               case NL80211_IFTYPE_STATION:
-                       mutex_lock(&rdev->sched_scan_mtx);
-                       __cfg80211_stop_sched_scan(rdev, false);
-                       mutex_unlock(&rdev->sched_scan_mtx);
-
-                       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);
-                       break;
-               default:
-                       break;
-               }
-               wdev->beacon_interval = 0;
+               cfg80211_leave(rdev, wdev);
                break;
        case NETDEV_DOWN:
                cfg80211_update_iface_num(rdev, wdev->iftype, -1);
@@ -1117,8 +1128,10 @@ static int __init cfg80211_init(void)
                goto out_fail_reg;
 
        cfg80211_wq = create_singlethread_workqueue("cfg80211");
-       if (!cfg80211_wq)
+       if (!cfg80211_wq) {
+               err = -ENOMEM;
                goto out_fail_wq;
+       }
 
        return 0;