* @scan_start: time (in jiffies) when the scan started
  * @wdev: the wireless device to scan for
  * @aborted: (internal) scan request was notified as aborted
+ * @notified: (internal) scan request was notified as done or aborted
  * @no_cck: used to send probe requests at non CCK rate in 2GHz band
  */
 struct cfg80211_scan_request {
        /* internal */
        struct wiphy *wiphy;
        unsigned long scan_start;
-       bool aborted;
+       bool aborted, notified;
        bool no_cck;
 
        /* keep last */
 
        struct mutex mtx;
 
-       struct work_struct cleanup_work;
-
        bool use_4addr, p2p_started;
 
        u8 address[ETH_ALEN] __aligned(sizeof(u16));
 
 MODULE_DESCRIPTION("wireless configuration support");
 MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
 
-/* RCU-protected (and cfg80211_mutex for writers) */
+/* RCU-protected (and RTNL for writers) */
 LIST_HEAD(cfg80211_rdev_list);
 int cfg80211_rdev_list_generation;
 
-DEFINE_MUTEX(cfg80211_mutex);
-
 /* for debugfs */
 static struct dentry *ieee80211_debugfs_dir;
 
 MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
                 "Disable 40MHz support in the 2.4GHz band");
 
-/* requires cfg80211_mutex to be held! */
 struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
 {
        struct cfg80211_registered_device *result = NULL, *rdev;
 
-       assert_cfg80211_lock();
+       ASSERT_RTNL();
 
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
                if (rdev->wiphy_idx == wiphy_idx) {
        return rdev->wiphy_idx;
 }
 
-/* requires cfg80211_rdev_mutex to be held! */
 struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
 {
        struct cfg80211_registered_device *rdev;
 
-       assert_cfg80211_lock();
+       ASSERT_RTNL();
 
        rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
        if (!rdev)
        return &rdev->wiphy;
 }
 
-/* requires cfg80211_mutex to be held */
 int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
                        char *newname)
 {
        struct cfg80211_registered_device *rdev2;
        int wiphy_idx, taken = -1, result, digits;
 
-       assert_cfg80211_lock();
+       ASSERT_RTNL();
 
        /* prohibit calling the thing phy%d when %d is not its number */
        sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
 void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
                              struct wireless_dev *wdev)
 {
-       lockdep_assert_held(&rdev->devlist_mtx);
-       lockdep_assert_held(&rdev->sched_scan_mtx);
+       ASSERT_RTNL();
 
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
                return;
 
        rtnl_lock();
 
-       /* read-only iteration need not hold the devlist_mtx */
-
        list_for_each_entry(wdev, &rdev->wdev_list, list) {
                if (wdev->netdev) {
                        dev_close(wdev->netdev);
                /* otherwise, check iftype */
                switch (wdev->iftype) {
                case NL80211_IFTYPE_P2P_DEVICE:
-                       /* but this requires it */
-                       mutex_lock(&rdev->devlist_mtx);
-                       mutex_lock(&rdev->sched_scan_mtx);
                        cfg80211_stop_p2p_device(rdev, wdev);
-                       mutex_unlock(&rdev->sched_scan_mtx);
-                       mutex_unlock(&rdev->devlist_mtx);
                        break;
                default:
                        break;
                            event_work);
 
        rtnl_lock();
-       cfg80211_lock_rdev(rdev);
-
        cfg80211_process_rdev_events(rdev);
-       cfg80211_unlock_rdev(rdev);
        rtnl_unlock();
 }
 
        /* give it a proper name */
        dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
 
-       mutex_init(&rdev->mtx);
-       mutex_init(&rdev->devlist_mtx);
-       mutex_init(&rdev->sched_scan_mtx);
        INIT_LIST_HEAD(&rdev->wdev_list);
        INIT_LIST_HEAD(&rdev->beacon_registrations);
        spin_lock_init(&rdev->beacon_registrations_lock);
        /* check and set up bitrates */
        ieee80211_set_bitrate_flags(wiphy);
 
-       mutex_lock(&cfg80211_mutex);
+       rtnl_lock();
 
        res = device_add(&rdev->wiphy.dev);
        if (res) {
-               mutex_unlock(&cfg80211_mutex);
+               rtnl_unlock();
                return res;
        }
 
        }
 
        cfg80211_debugfs_rdev_add(rdev);
-       mutex_unlock(&cfg80211_mutex);
 
-       /*
-        * due to a locking dependency this has to be outside of the
-        * cfg80211_mutex lock
-        */
        res = rfkill_register(rdev->rfkill);
        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);
+               rtnl_unlock();
                return res;
        }
 
-       rtnl_lock();
        rdev->wiphy.registered = true;
        rtnl_unlock();
        return 0;
 {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
-       rtnl_lock();
-       rdev->wiphy.registered = false;
-       rtnl_unlock();
-
-       rfkill_unregister(rdev->rfkill);
-
-       /* protect the device list */
-       mutex_lock(&cfg80211_mutex);
-
        wait_event(rdev->dev_wait, ({
                int __count;
-               mutex_lock(&rdev->devlist_mtx);
+               rtnl_lock();
                __count = rdev->opencount;
-               mutex_unlock(&rdev->devlist_mtx);
+               rtnl_unlock();
                __count == 0; }));
 
-       mutex_lock(&rdev->devlist_mtx);
+       rtnl_lock();
+       rdev->wiphy.registered = false;
+
+       rfkill_unregister(rdev->rfkill);
+
        BUG_ON(!list_empty(&rdev->wdev_list));
-       mutex_unlock(&rdev->devlist_mtx);
 
        /*
         * First remove the hardware from everywhere, this makes
        list_del_rcu(&rdev->list);
        synchronize_rcu();
 
-       /*
-        * Try to grab rdev->mtx. If a command is still in progress,
-        * hopefully the driver will refuse it since it's tearing
-        * down the device already. We wait for this command to complete
-        * before unlinking the item from the list.
-        * Note: as codified by the BUG_ON above we cannot get here if
-        * a virtual interface is still present. Hence, we can only get
-        * to lock contention here if userspace issues a command that
-        * identified the hardware by wiphy index.
-        */
-       cfg80211_lock_rdev(rdev);
-       /* nothing */
-       cfg80211_unlock_rdev(rdev);
-
        /*
         * If this device got a regulatory hint tell core its
         * free to listen now to a new shiny device regulatory hint
        cfg80211_rdev_list_generation++;
        device_del(&rdev->wiphy.dev);
 
-       mutex_unlock(&cfg80211_mutex);
+       rtnl_unlock();
 
        flush_work(&rdev->scan_done_wk);
        cancel_work_sync(&rdev->conn_work);
        struct cfg80211_internal_bss *scan, *tmp;
        struct cfg80211_beacon_registration *reg, *treg;
        rfkill_destroy(rdev->rfkill);
-       mutex_destroy(&rdev->mtx);
-       mutex_destroy(&rdev->devlist_mtx);
-       mutex_destroy(&rdev->sched_scan_mtx);
        list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
                list_del(®->list);
                kfree(reg);
 }
 EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
 
-static void wdev_cleanup_work(struct work_struct *work)
-{
-       struct wireless_dev *wdev;
-       struct cfg80211_registered_device *rdev;
-
-       wdev = container_of(work, struct wireless_dev, cleanup_work);
-       rdev = wiphy_to_dev(wdev->wiphy);
-
-       mutex_lock(&rdev->sched_scan_mtx);
-
-       if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
-               rdev->scan_req->aborted = true;
-               ___cfg80211_scan_done(rdev, true);
-       }
-
-       if (WARN_ON(rdev->sched_scan_req &&
-                   rdev->sched_scan_req->dev == wdev->netdev)) {
-               __cfg80211_stop_sched_scan(rdev, false);
-       }
-
-       mutex_unlock(&rdev->sched_scan_mtx);
-
-       mutex_lock(&rdev->devlist_mtx);
-       rdev->opencount--;
-       mutex_unlock(&rdev->devlist_mtx);
-       wake_up(&rdev->dev_wait);
-
-       dev_put(wdev->netdev);
-}
-
 void cfg80211_unregister_wdev(struct wireless_dev *wdev)
 {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
        if (WARN_ON(wdev->netdev))
                return;
 
-       mutex_lock(&rdev->devlist_mtx);
-       mutex_lock(&rdev->sched_scan_mtx);
        list_del_rcu(&wdev->list);
        rdev->devlist_generation++;
 
                WARN_ON_ONCE(1);
                break;
        }
-       mutex_unlock(&rdev->sched_scan_mtx);
-       mutex_unlock(&rdev->devlist_mtx);
 }
 EXPORT_SYMBOL(cfg80211_unregister_wdev);
 
 }
 
 void cfg80211_leave(struct cfg80211_registered_device *rdev,
-                  struct wireless_dev *wdev)
+                   struct wireless_dev *wdev)
 {
        struct net_device *dev = wdev->netdev;
 
                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
                 * are added with nl80211.
                 */
                mutex_init(&wdev->mtx);
-               INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
                INIT_LIST_HEAD(&wdev->event_list);
                spin_lock_init(&wdev->event_lock);
                INIT_LIST_HEAD(&wdev->mgmt_registrations);
                spin_lock_init(&wdev->mgmt_registrations_lock);
 
-               mutex_lock(&rdev->devlist_mtx);
                wdev->identifier = ++rdev->wdev_id;
                list_add_rcu(&wdev->list, &rdev->wdev_list);
                rdev->devlist_generation++;
                }
                wdev->netdev = dev;
                wdev->sme_state = CFG80211_SME_IDLE;
-               mutex_unlock(&rdev->devlist_mtx);
 #ifdef CONFIG_CFG80211_WEXT
                wdev->wext.default_key = -1;
                wdev->wext.default_mgmt_key = -1;
                break;
        case NETDEV_DOWN:
                cfg80211_update_iface_num(rdev, wdev->iftype, -1);
-               dev_hold(dev);
-               queue_work(cfg80211_wq, &wdev->cleanup_work);
+               if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+                       if (WARN_ON(!rdev->scan_req->notified))
+                               rdev->scan_req->aborted = true;
+                       ___cfg80211_scan_done(rdev, true);
+               }
+
+               if (WARN_ON(rdev->sched_scan_req &&
+                           rdev->sched_scan_req->dev == wdev->netdev)) {
+                       __cfg80211_stop_sched_scan(rdev, false);
+               }
+
+               rdev->opencount--;
+               wake_up(&rdev->dev_wait);
                break;
        case NETDEV_UP:
-               /*
-                * If we have a really quick DOWN/UP succession we may
-                * have this work still pending ... cancel it and see
-                * if it was pending, in which case we need to account
-                * for some of the work it would have done.
-                */
-               if (cancel_work_sync(&wdev->cleanup_work)) {
-                       mutex_lock(&rdev->devlist_mtx);
-                       rdev->opencount--;
-                       mutex_unlock(&rdev->devlist_mtx);
-                       dev_put(dev);
-               }
                cfg80211_update_iface_num(rdev, wdev->iftype, 1);
-               cfg80211_lock_rdev(rdev);
-               mutex_lock(&rdev->devlist_mtx);
-               mutex_lock(&rdev->sched_scan_mtx);
                wdev_lock(wdev);
                switch (wdev->iftype) {
 #ifdef CONFIG_CFG80211_WEXT
                        break;
                }
                wdev_unlock(wdev);
-               mutex_unlock(&rdev->sched_scan_mtx);
                rdev->opencount++;
-               mutex_unlock(&rdev->devlist_mtx);
-               cfg80211_unlock_rdev(rdev);
 
                /*
                 * Configure power management to the driver here so that its
                        }
                break;
        case NETDEV_UNREGISTER:
-               /*
-                * NB: cannot take rdev->mtx here because this may be
-                * called within code protected by it when interfaces
-                * are removed with nl80211.
-                */
-               mutex_lock(&rdev->devlist_mtx);
                /*
                 * It is possible to get NETDEV_UNREGISTER
                 * multiple times. To detect that, check
                        kfree(wdev->wext.keys);
 #endif
                }
-               mutex_unlock(&rdev->devlist_mtx);
                /*
                 * synchronise (so that we won't find this netdev
                 * from other code any more) and then clear the list
                        return notifier_from_errno(-EOPNOTSUPP);
                if (rfkill_blocked(rdev->rfkill))
                        return notifier_from_errno(-ERFKILL);
-               mutex_lock(&rdev->devlist_mtx);
                ret = cfg80211_can_add_interface(rdev, wdev->iftype);
-               mutex_unlock(&rdev->devlist_mtx);
                if (ret)
                        return notifier_from_errno(ret);
                break;
        struct cfg80211_registered_device *rdev;
 
        rtnl_lock();
-       mutex_lock(&cfg80211_mutex);
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
                if (net_eq(wiphy_net(&rdev->wiphy), net))
                        WARN_ON(cfg80211_switch_netns(rdev, &init_net));
        }
-       mutex_unlock(&cfg80211_mutex);
        rtnl_unlock();
 }
 
 
  */
 #ifndef __NET_WIRELESS_CORE_H
 #define __NET_WIRELESS_CORE_H
-#include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
 #include <linux/rbtree.h>
 struct cfg80211_registered_device {
        const struct cfg80211_ops *ops;
        struct list_head list;
-       /* we hold this mutex during any call so that
-        * we cannot do multiple calls at once, and also
-        * to avoid the deregister call to proceed while
-        * any call is in progress */
-       struct mutex mtx;
 
        /* rfkill support */
        struct rfkill_ops rfkill_ops;
        /* wiphy index, internal only */
        int wiphy_idx;
 
-       /* associated wireless interfaces */
-       struct mutex devlist_mtx;
-       /* protected by devlist_mtx or RCU */
+       /* associated wireless interfaces, protected by rtnl or RCU */
        struct list_head wdev_list;
        int devlist_generation, wdev_id;
        int opencount; /* also protected by devlist_mtx */
        struct work_struct scan_done_wk;
        struct work_struct sched_scan_results_wk;
 
-       struct mutex sched_scan_mtx;
-
 #ifdef CONFIG_NL80211_TESTMODE
        struct genl_info *testmode_info;
 #endif
 }
 
 extern struct workqueue_struct *cfg80211_wq;
-extern struct mutex cfg80211_mutex;
 extern struct list_head cfg80211_rdev_list;
 extern int cfg80211_rdev_list_generation;
 
-static inline void assert_cfg80211_lock(void)
-{
-       lockdep_assert_held(&cfg80211_mutex);
-}
-
 struct cfg80211_internal_bss {
        struct list_head list;
        struct list_head hidden_list;
 struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
 int get_wiphy_idx(struct wiphy *wiphy);
 
-/* requires cfg80211_rdev_mutex to be held! */
 struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
 
 int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
                          struct net *net);
 
-static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev)
-{
-       mutex_lock(&rdev->mtx);
-}
-
-static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev)
-{
-       BUG_ON(IS_ERR(rdev) || !rdev);
-       mutex_unlock(&rdev->mtx);
-}
-
 static inline void wdev_lock(struct wireless_dev *wdev)
        __acquires(wdev)
 {
        mutex_unlock(&wdev->mtx);
 }
 
-#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
+#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
 #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
 
 static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
 
        if (!buf)
                return -ENOMEM;
 
-       mutex_lock(&cfg80211_mutex);
+       rtnl_lock();
 
        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                sband = wiphy->bands[band];
                                                buf, buf_size, offset);
        }
 
-       mutex_unlock(&cfg80211_mutex);
+       rtnl_unlock();
 
        r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
 
 
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        int err;
 
-       mutex_lock(&rdev->devlist_mtx);
+       ASSERT_RTNL();
+
        wdev_lock(wdev);
        err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
        wdev_unlock(wdev);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
                wdev->wext.ibss.channel_fixed = false;
        }
 
-       mutex_lock(&rdev->devlist_mtx);
        wdev_lock(wdev);
        err = cfg80211_ibss_wext_join(rdev, wdev);
        wdev_unlock(wdev);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
        memcpy(wdev->wext.ibss.ssid, ssid, len);
        wdev->wext.ibss.ssid_len = len;
 
-       mutex_lock(&rdev->devlist_mtx);
        wdev_lock(wdev);
        err = cfg80211_ibss_wext_join(rdev, wdev);
        wdev_unlock(wdev);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
        } else
                wdev->wext.ibss.bssid = NULL;
 
-       mutex_lock(&rdev->devlist_mtx);
        wdev_lock(wdev);
        err = cfg80211_ibss_wext_join(rdev, wdev);
        wdev_unlock(wdev);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
 
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        int err;
 
-       mutex_lock(&rdev->devlist_mtx);
        wdev_lock(wdev);
        err = __cfg80211_join_mesh(rdev, dev, setup, conf);
        wdev_unlock(wdev);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
 
 {
        int err;
 
-       mutex_lock(&rdev->devlist_mtx);
+       ASSERT_RTNL();
+
        wdev_lock(dev->ieee80211_ptr);
        err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
                                   ssid, ssid_len, ie, ie_len,
                                   key, key_len, key_idx,
                                   sae_data, sae_data_len);
        wdev_unlock(dev->ieee80211_ptr);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        int err;
 
-       mutex_lock(&rdev->devlist_mtx);
+       ASSERT_RTNL();
+
        wdev_lock(wdev);
        err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid,
                                    ssid, ssid_len, req);
        wdev_unlock(wdev);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
                            dfs_update_channels_wk);
        wiphy = &rdev->wiphy;
 
-       mutex_lock(&cfg80211_mutex);
+       rtnl_lock();
        for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
                sband = wiphy->bands[bandid];
                if (!sband)
                        check_again = true;
                }
        }
-       mutex_unlock(&cfg80211_mutex);
+       rtnl_unlock();
 
        /* reschedule if there are other channels waiting to be cleared again */
        if (check_again)
 
        int wiphy_idx = -1;
        int ifidx = -1;
 
-       assert_cfg80211_lock();
+       ASSERT_RTNL();
 
        if (!have_ifidx && !have_wdev_id)
                return ERR_PTR(-EINVAL);
                if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
                        continue;
 
-               mutex_lock(&rdev->devlist_mtx);
                list_for_each_entry(wdev, &rdev->wdev_list, list) {
                        if (have_ifidx && wdev->netdev &&
                            wdev->netdev->ifindex == ifidx) {
                                break;
                        }
                }
-               mutex_unlock(&rdev->devlist_mtx);
 
                if (result)
                        break;
        struct cfg80211_registered_device *rdev = NULL, *tmp;
        struct net_device *netdev;
 
-       assert_cfg80211_lock();
+       ASSERT_RTNL();
 
        if (!attrs[NL80211_ATTR_WIPHY] &&
            !attrs[NL80211_ATTR_IFINDEX] &&
                tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
                if (tmp) {
                        /* make sure wdev exists */
-                       mutex_lock(&tmp->devlist_mtx);
                        list_for_each_entry(wdev, &tmp->wdev_list, list) {
                                if (wdev->identifier != (u32)wdev_id)
                                        continue;
                                found = true;
                                break;
                        }
-                       mutex_unlock(&tmp->devlist_mtx);
 
                        if (!found)
                                tmp = NULL;
 /*
  * This function returns a pointer to the driver
  * that the genl_info item that is passed refers to.
- * If successful, it returns non-NULL and also locks
- * the driver's mutex!
- *
- * This means that you need to call cfg80211_unlock_rdev()
- * before being allowed to acquire &cfg80211_mutex!
- *
- * This is necessary because we need to lock the global
- * mutex to get an item off the list safely, and then
- * we lock the rdev mutex so it doesn't go away under us.
- *
- * We don't want to keep cfg80211_mutex locked
- * for all the time in order to allow requests on
- * other interfaces to go through at the same time.
  *
  * The result of this can be a PTR_ERR and hence must
  * be checked with IS_ERR() for errors.
 static struct cfg80211_registered_device *
 cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
 {
-       struct cfg80211_registered_device *rdev;
-
-       mutex_lock(&cfg80211_mutex);
-       rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);
-
-       /* if it is not an error we grab the lock on
-        * it to assure it won't be going away while
-        * we operate on it */
-       if (!IS_ERR(rdev))
-               mutex_lock(&rdev->mtx);
-
-       mutex_unlock(&cfg80211_mutex);
-
-       return rdev;
+       return __cfg80211_rdev_from_attrs(netns, info->attrs);
 }
 
 /* policy for the attributes */
        int err;
 
        rtnl_lock();
-       mutex_lock(&cfg80211_mutex);
 
        if (!cb->args[0]) {
                err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
                *rdev = wiphy_to_dev(wiphy);
                *wdev = NULL;
 
-               mutex_lock(&(*rdev)->devlist_mtx);
                list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
                        if (tmp->identifier == cb->args[1]) {
                                *wdev = tmp;
                                break;
                        }
                }
-               mutex_unlock(&(*rdev)->devlist_mtx);
 
                if (!*wdev) {
                        err = -ENODEV;
                }
        }
 
-       cfg80211_lock_rdev(*rdev);
-
-       mutex_unlock(&cfg80211_mutex);
        return 0;
  out_unlock:
-       mutex_unlock(&cfg80211_mutex);
        rtnl_unlock();
        return err;
 }
 
 static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
 {
-       cfg80211_unlock_rdev(rdev);
        rtnl_unlock();
 }
 
        struct nlattr **tb = nl80211_fam.attrbuf;
        int res;
 
-       mutex_lock(&cfg80211_mutex);
+       rtnl_lock();
        res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
                          tb, nl80211_fam.maxattr, nl80211_policy);
        if (res == 0) {
                        int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
 
                        netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
-                       if (!netdev) {
-                               mutex_unlock(&cfg80211_mutex);
+                       if (!netdev)
                                return -ENODEV;
-                       }
                        if (netdev->ieee80211_ptr) {
                                dev = wiphy_to_dev(
                                        netdev->ieee80211_ptr->wiphy);
                                    !skb->len &&
                                    cb->min_dump_alloc < 4096) {
                                        cb->min_dump_alloc = 4096;
-                                       mutex_unlock(&cfg80211_mutex);
                                        return 1;
                                }
                                idx--;
                } while (cb->args[1] > 0);
                break;
        }
-       mutex_unlock(&cfg80211_mutex);
+       rtnl_unlock();
 
        cb->args[0] = idx;
 
        if (result)
                return result;
 
-       mutex_lock(&rdev->devlist_mtx);
        switch (iftype) {
        case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_P2P_GO:
        default:
                result = -EINVAL;
        }
-       mutex_unlock(&rdev->devlist_mtx);
 
        return result;
 }
        u32 frag_threshold = 0, rts_threshold = 0;
        u8 coverage_class = 0;
 
+       ASSERT_RTNL();
+
        /*
         * Try to find the wiphy and netdev. Normally this
         * function shouldn't need the netdev, but this is
         * also passed a netdev to set_wiphy, so that it is
         * possible to let that go to the right netdev!
         */
-       mutex_lock(&cfg80211_mutex);
 
        if (info->attrs[NL80211_ATTR_IFINDEX]) {
                int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
 
                netdev = dev_get_by_index(genl_info_net(info), ifindex);
-               if (netdev && netdev->ieee80211_ptr) {
+               if (netdev && netdev->ieee80211_ptr)
                        rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
-                       mutex_lock(&rdev->mtx);
-               } else
+               else
                        netdev = NULL;
        }
 
        if (!netdev) {
                rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
                                                  info->attrs);
-               if (IS_ERR(rdev)) {
-                       mutex_unlock(&cfg80211_mutex);
+               if (IS_ERR(rdev))
                        return PTR_ERR(rdev);
-               }
                wdev = NULL;
                netdev = NULL;
                result = 0;
-
-               mutex_lock(&rdev->mtx);
        } else
                wdev = netdev->ieee80211_ptr;
 
                result = cfg80211_dev_rename(
                        rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
 
-       mutex_unlock(&cfg80211_mutex);
-
        if (result)
                goto bad_res;
 
        }
 
  bad_res:
-       mutex_unlock(&rdev->mtx);
        if (netdev)
                dev_put(netdev);
        return result;
        struct cfg80211_registered_device *rdev;
        struct wireless_dev *wdev;
 
-       mutex_lock(&cfg80211_mutex);
+       rtnl_lock();
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
                if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
                        continue;
                }
                if_idx = 0;
 
-               mutex_lock(&rdev->devlist_mtx);
                list_for_each_entry(wdev, &rdev->wdev_list, list) {
                        if (if_idx < if_start) {
                                if_idx++;
                        if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
                                               cb->nlh->nlmsg_seq, NLM_F_MULTI,
                                               rdev, wdev) < 0) {
-                               mutex_unlock(&rdev->devlist_mtx);
                                goto out;
                        }
                        if_idx++;
                }
-               mutex_unlock(&rdev->devlist_mtx);
 
                wp_idx++;
        }
  out:
-       mutex_unlock(&cfg80211_mutex);
+       rtnl_unlock();
 
        cb->args[0] = wp_idx;
        cb->args[1] = if_idx;
                INIT_LIST_HEAD(&wdev->mgmt_registrations);
                spin_lock_init(&wdev->mgmt_registrations_lock);
 
-               mutex_lock(&rdev->devlist_mtx);
                wdev->identifier = ++rdev->wdev_id;
                list_add_rcu(&wdev->list, &rdev->wdev_list);
                rdev->devlist_generation++;
-               mutex_unlock(&rdev->devlist_mtx);
                break;
        default:
                break;
        struct wireless_dev *wdev;
        bool ret = false;
 
-       mutex_lock(&rdev->devlist_mtx);
-
        list_for_each_entry(wdev, &rdev->wdev_list, list) {
                if (wdev->iftype != NL80211_IFTYPE_AP &&
                    wdev->iftype != NL80211_IFTYPE_P2P_GO)
                break;
        }
 
-       mutex_unlock(&rdev->devlist_mtx);
-
        return ret;
 }
 
                params.radar_required = true;
        }
 
-       mutex_lock(&rdev->devlist_mtx);
        err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
                                           params.chandef.chan,
                                           CHAN_MODE_SHARED,
                                           radar_detect_width);
-       mutex_unlock(&rdev->devlist_mtx);
-
        if (err)
                return err;
 
        void *hdr = NULL;
        struct nlattr *nl_reg_rules;
        unsigned int i;
-       int err = -EINVAL;
-
-       mutex_lock(&cfg80211_mutex);
 
        if (!cfg80211_regdomain)
-               goto out;
+               return -EINVAL;
 
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (!msg) {
-               err = -ENOBUFS;
-               goto out;
-       }
+       if (!msg)
+               return -ENOBUFS;
 
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_GET_REG);
        nla_nest_end(msg, nl_reg_rules);
 
        genlmsg_end(msg, hdr);
-       err = genlmsg_reply(msg, info);
-       goto out;
+       return genlmsg_reply(msg, info);
 
 nla_put_failure_rcu:
        rcu_read_unlock();
        genlmsg_cancel(msg, hdr);
 put_failure:
        nlmsg_free(msg);
-       err = -EMSGSIZE;
-out:
-       mutex_unlock(&cfg80211_mutex);
-       return err;
+       return -EMSGSIZE;
 }
 
 static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
                }
        }
 
-       mutex_lock(&cfg80211_mutex);
-
        r = set_regdom(rd);
        /* set_regdom took ownership */
        rd = NULL;
-       mutex_unlock(&cfg80211_mutex);
 
  bad_reg:
        kfree(rd);
        if (!rdev->ops->scan)
                return -EOPNOTSUPP;
 
-       mutex_lock(&rdev->sched_scan_mtx);
        if (rdev->scan_req) {
                err = -EBUSY;
                goto unlock;
        }
 
  unlock:
-       mutex_unlock(&rdev->sched_scan_mtx);
        return err;
 }
 
        if (ie_len > wiphy->max_sched_scan_ie_len)
                return -EINVAL;
 
-       mutex_lock(&rdev->sched_scan_mtx);
-
        if (rdev->sched_scan_req) {
                err = -EINPROGRESS;
                goto out;
 out_free:
        kfree(request);
 out:
-       mutex_unlock(&rdev->sched_scan_mtx);
        return err;
 }
 
                                   struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       int err;
 
        if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
            !rdev->ops->sched_scan_stop)
                return -EOPNOTSUPP;
 
-       mutex_lock(&rdev->sched_scan_mtx);
-       err = __cfg80211_stop_sched_scan(rdev, false);
-       mutex_unlock(&rdev->sched_scan_mtx);
-
-       return err;
+       return __cfg80211_stop_sched_scan(rdev, false);
 }
 
 static int nl80211_start_radar_detection(struct sk_buff *skb,
        if (!rdev->ops->start_radar_detection)
                return -EOPNOTSUPP;
 
-       mutex_lock(&rdev->devlist_mtx);
        err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
                                           chandef.chan, CHAN_MODE_SHARED,
                                           BIT(chandef.width));
        if (err)
-               goto err_locked;
+               return err;
 
        err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
        if (!err) {
                wdev->cac_started = true;
                wdev->cac_start_time = jiffies;
        }
-err_locked:
-       mutex_unlock(&rdev->devlist_mtx);
-
        return err;
 }
 
        void *data = NULL;
        int data_len = 0;
 
+       rtnl_lock();
+
        if (cb->args[0]) {
                /*
                 * 0 is a valid index, but not valid for args[0],
                                  nl80211_fam.attrbuf, nl80211_fam.maxattr,
                                  nl80211_policy);
                if (err)
-                       return err;
+                       goto out_err;
 
-               mutex_lock(&cfg80211_mutex);
                rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
                                                  nl80211_fam.attrbuf);
                if (IS_ERR(rdev)) {
-                       mutex_unlock(&cfg80211_mutex);
-                       return PTR_ERR(rdev);
+                       err = PTR_ERR(rdev);
+                       goto out_err;
                }
                phy_idx = rdev->wiphy_idx;
                rdev = NULL;
-               mutex_unlock(&cfg80211_mutex);
 
                if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
                        cb->args[1] =
                data_len = nla_len((void *)cb->args[1]);
        }
 
-       mutex_lock(&cfg80211_mutex);
        rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
        if (!rdev) {
-               mutex_unlock(&cfg80211_mutex);
-               return -ENOENT;
+               err = -ENOENT;
+               goto out_err;
        }
-       cfg80211_lock_rdev(rdev);
-       mutex_unlock(&cfg80211_mutex);
 
        if (!rdev->ops->testmode_dump) {
                err = -EOPNOTSUPP;
        /* see above */
        cb->args[0] = phy_idx + 1;
  out_err:
-       cfg80211_unlock_rdev(rdev);
+       rtnl_unlock();
        return err;
 }
 
        if (wdev->p2p_started)
                return 0;
 
-       mutex_lock(&rdev->devlist_mtx);
        err = cfg80211_can_add_interface(rdev, wdev->iftype);
-       mutex_unlock(&rdev->devlist_mtx);
        if (err)
                return err;
 
                return err;
 
        wdev->p2p_started = true;
-       mutex_lock(&rdev->devlist_mtx);
        rdev->opencount++;
-       mutex_unlock(&rdev->devlist_mtx);
 
        return 0;
 }
        if (!rdev->ops->stop_p2p_device)
                return -EOPNOTSUPP;
 
-       mutex_lock(&rdev->devlist_mtx);
-       mutex_lock(&rdev->sched_scan_mtx);
        cfg80211_stop_p2p_device(rdev, wdev);
-       mutex_unlock(&rdev->sched_scan_mtx);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return 0;
 }
                info->user_ptr[0] = rdev;
        } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
                   ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
-               mutex_lock(&cfg80211_mutex);
+               ASSERT_RTNL();
+
                wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
                                                  info->attrs);
                if (IS_ERR(wdev)) {
-                       mutex_unlock(&cfg80211_mutex);
                        if (rtnl)
                                rtnl_unlock();
                        return PTR_ERR(wdev);
 
                if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
                        if (!dev) {
-                               mutex_unlock(&cfg80211_mutex);
                                if (rtnl)
                                        rtnl_unlock();
                                return -EINVAL;
                if (dev) {
                        if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
                            !netif_running(dev)) {
-                               mutex_unlock(&cfg80211_mutex);
                                if (rtnl)
                                        rtnl_unlock();
                                return -ENETDOWN;
                        dev_hold(dev);
                } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
                        if (!wdev->p2p_started) {
-                               mutex_unlock(&cfg80211_mutex);
                                if (rtnl)
                                        rtnl_unlock();
                                return -ENETDOWN;
                        }
                }
 
-               cfg80211_lock_rdev(rdev);
-
-               mutex_unlock(&cfg80211_mutex);
-
                info->user_ptr[0] = rdev;
        }
 
 static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
                              struct genl_info *info)
 {
-       if (info->user_ptr[0])
-               cfg80211_unlock_rdev(info->user_ptr[0]);
        if (info->user_ptr[1]) {
                if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
                        struct wireless_dev *wdev = info->user_ptr[1];
                .dumpit = nl80211_dump_wiphy,
                .policy = nl80211_policy,
                /* can be retrieved by unprivileged users */
-               .internal_flags = NL80211_FLAG_NEED_WIPHY,
+               .internal_flags = NL80211_FLAG_NEED_WIPHY |
+                                 NL80211_FLAG_NEED_RTNL,
        },
        {
                .cmd = NL80211_CMD_SET_WIPHY,
                .dumpit = nl80211_dump_interface,
                .policy = nl80211_policy,
                /* can be retrieved by unprivileged users */
-               .internal_flags = NL80211_FLAG_NEED_WDEV,
+               .internal_flags = NL80211_FLAG_NEED_WDEV |
+                                 NL80211_FLAG_NEED_RTNL,
        },
        {
                .cmd = NL80211_CMD_SET_INTERFACE,
                .cmd = NL80211_CMD_GET_REG,
                .doit = nl80211_get_reg,
                .policy = nl80211_policy,
+               .internal_flags = NL80211_FLAG_NEED_RTNL,
                /* can be retrieved by unprivileged users */
        },
        {
                .doit = nl80211_set_reg,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
+               .internal_flags = NL80211_FLAG_NEED_RTNL,
        },
        {
                .cmd = NL80211_CMD_REQ_SET_REG,
        struct nlattr *nest;
        int i;
 
-       lockdep_assert_held(&rdev->sched_scan_mtx);
-
        if (WARN_ON(!req))
                return 0;
 
 
        const struct ieee80211_regdomain *curdom, *regdom = NULL;
        int i;
 
-       mutex_lock(&cfg80211_mutex);
+       rtnl_lock();
 
        mutex_lock(®_regdb_search_mutex);
        while (!list_empty(®_regdb_search_list)) {
        if (!IS_ERR_OR_NULL(regdom))
                set_regdom(regdom);
 
-       mutex_unlock(&cfg80211_mutex);
+       rtnl_unlock();
 }
 
 static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
        struct cfg80211_registered_device *rdev;
        struct wiphy *wiphy;
 
-       assert_cfg80211_lock();
+       ASSERT_RTNL();
 
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
                wiphy = &rdev->wiphy;
 {
        struct regulatory_request *reg_request, *lr;
 
-       mutex_lock(&cfg80211_mutex);
-       mutex_lock(®_mutex);
        lr = get_last_request();
 
        /* When last_request->processed becomes true this will be rescheduled */
        if (lr && !lr->processed) {
                REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n");
-               goto out;
+               return;
        }
 
        spin_lock(®_requests_lock);
 
        if (list_empty(®_requests_list)) {
                spin_unlock(®_requests_lock);
-               goto out;
+               return;
        }
 
        reg_request = list_first_entry(®_requests_list,
        spin_unlock(®_requests_lock);
 
        reg_process_hint(reg_request, reg_request->initiator);
-
-out:
-       mutex_unlock(®_mutex);
-       mutex_unlock(&cfg80211_mutex);
 }
 
 /* Processes beacon hints -- this has nothing to do with country IEs */
        struct cfg80211_registered_device *rdev;
        struct reg_beacon *pending_beacon, *tmp;
 
-       mutex_lock(&cfg80211_mutex);
-       mutex_lock(®_mutex);
-
        /* This goes through the _pending_ beacon list */
        spin_lock_bh(®_pending_beacons_lock);
 
        }
 
        spin_unlock_bh(®_pending_beacons_lock);
-       mutex_unlock(®_mutex);
-       mutex_unlock(&cfg80211_mutex);
 }
 
 static void reg_todo(struct work_struct *work)
 {
+       rtnl_lock();
+       mutex_lock(®_mutex);
        reg_process_pending_hints();
        reg_process_pending_beacon_hints();
+       mutex_unlock(®_mutex);
+       rtnl_unlock();
 }
 
 static void queue_regulatory_request(struct regulatory_request *request)
 }
 EXPORT_SYMBOL(regulatory_hint);
 
-/*
- * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
- * therefore cannot iterate over the rdev list here.
- */
 void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
                         const u8 *country_ie, u8 country_ie_len)
 {
        /*
         * We will run this only upon a successful connection on cfg80211.
         * We leave conflict resolution to the workqueue, where can hold
-        * cfg80211_mutex.
+        * the RTNL.
         */
        if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
            lr->wiphy_idx != WIPHY_IDX_INVALID)
        LIST_HEAD(tmp_reg_req_list);
        struct cfg80211_registered_device *rdev;
 
-       mutex_lock(&cfg80211_mutex);
+       ASSERT_RTNL();
+
        mutex_lock(®_mutex);
 
        reset_regdomains(true, &world_regdom);
        spin_unlock(®_requests_lock);
 
        mutex_unlock(®_mutex);
-       mutex_unlock(&cfg80211_mutex);
 
        REG_DBG_PRINT("Kicking the queue\n");
 
        mutex_unlock(®_mutex);
 }
 
-/* Caller must hold cfg80211_mutex */
 void wiphy_regulatory_deregister(struct wiphy *wiphy)
 {
        struct wiphy *request_wiphy = NULL;
 
        union iwreq_data wrqu;
 #endif
 
-       lockdep_assert_held(&rdev->sched_scan_mtx);
+       ASSERT_RTNL();
 
        request = rdev->scan_req;
 
        rdev = container_of(wk, struct cfg80211_registered_device,
                            scan_done_wk);
 
-       mutex_lock(&rdev->sched_scan_mtx);
+       rtnl_lock();
        ___cfg80211_scan_done(rdev, false);
-       mutex_unlock(&rdev->sched_scan_mtx);
+       rtnl_unlock();
 }
 
 void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
        WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
 
        request->aborted = aborted;
+       request->notified = true;
        queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
 }
 EXPORT_SYMBOL(cfg80211_scan_done);
 
        request = rdev->sched_scan_req;
 
-       mutex_lock(&rdev->sched_scan_mtx);
+       rtnl_lock();
 
        /* we don't have sched_scan_req anymore if the scan is stopping */
        if (request) {
                nl80211_send_sched_scan_results(rdev, request->dev);
        }
 
-       mutex_unlock(&rdev->sched_scan_mtx);
+       rtnl_unlock();
 }
 
 void cfg80211_sched_scan_results(struct wiphy *wiphy)
 
        trace_cfg80211_sched_scan_stopped(wiphy);
 
-       mutex_lock(&rdev->sched_scan_mtx);
+       rtnl_lock();
        __cfg80211_stop_sched_scan(rdev, true);
-       mutex_unlock(&rdev->sched_scan_mtx);
+       rtnl_unlock();
 }
 EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
 
 {
        struct net_device *dev;
 
-       lockdep_assert_held(&rdev->sched_scan_mtx);
+       ASSERT_RTNL();
 
        if (!rdev->sched_scan_req)
                return -ENOENT;
 static struct cfg80211_registered_device *
 cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
 {
-       struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
 
-       mutex_lock(&cfg80211_mutex);
+       ASSERT_RTNL();
+
        dev = dev_get_by_index(net, ifindex);
        if (!dev)
-               goto out;
-       if (dev->ieee80211_ptr) {
+               return ERR_PTR(-ENODEV);
+       if (dev->ieee80211_ptr)
                rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
-               mutex_lock(&rdev->mtx);
-       } else
+       else
                rdev = ERR_PTR(-ENODEV);
        dev_put(dev);
- out:
-       mutex_unlock(&cfg80211_mutex);
        return rdev;
 }
 
        if (IS_ERR(rdev))
                return PTR_ERR(rdev);
 
-       mutex_lock(&rdev->sched_scan_mtx);
        if (rdev->scan_req) {
                err = -EBUSY;
                goto out;
                dev_hold(dev);
        }
  out:
-       mutex_unlock(&rdev->sched_scan_mtx);
        kfree(creq);
-       cfg80211_unlock_rdev(rdev);
        return err;
 }
 EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
        if (IS_ERR(rdev))
                return PTR_ERR(rdev);
 
-       if (rdev->scan_req) {
-               res = -EAGAIN;
-               goto out;
-       }
+       if (rdev->scan_req)
+               return -EAGAIN;
 
        res = ieee80211_scan_results(rdev, info, extra, data->length);
        data->length = 0;
                res = 0;
        }
 
- out:
-       cfg80211_unlock_rdev(rdev);
        return res;
 }
 EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
 
        struct wireless_dev *wdev;
        bool is_all_idle = true;
 
-       mutex_lock(&cfg80211_mutex);
-
        /*
         * All devices must be idle as otherwise if you are actively
         * scanning some new beacon hints could be learned and would
         * count as new regulatory hints.
         */
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
-               cfg80211_lock_rdev(rdev);
                list_for_each_entry(wdev, &rdev->wdev_list, list) {
                        wdev_lock(wdev);
                        if (wdev->sme_state != CFG80211_SME_IDLE)
                                is_all_idle = false;
                        wdev_unlock(wdev);
                }
-               cfg80211_unlock_rdev(rdev);
        }
 
-       mutex_unlock(&cfg80211_mutex);
-
        return is_all_idle;
 }
 
 static void disconnect_work(struct work_struct *work)
 {
-       if (!cfg80211_is_all_idle())
-               return;
-
-       regulatory_hint_disconnect();
+       rtnl_lock();
+       if (cfg80211_is_all_idle())
+               regulatory_hint_disconnect();
+       rtnl_unlock();
 }
 
 static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
        ASSERT_RTNL();
        ASSERT_RDEV_LOCK(rdev);
        ASSERT_WDEV_LOCK(wdev);
-       lockdep_assert_held(&rdev->sched_scan_mtx);
 
        if (rdev->scan_req)
                return -EBUSY;
        u8 bssid_buf[ETH_ALEN], *bssid = NULL;
 
        rtnl_lock();
-       cfg80211_lock_rdev(rdev);
-       mutex_lock(&rdev->devlist_mtx);
-       mutex_lock(&rdev->sched_scan_mtx);
 
        list_for_each_entry(wdev, &rdev->wdev_list, list) {
                if (!wdev->netdev)
                wdev_unlock(wdev);
        }
 
-       mutex_unlock(&rdev->sched_scan_mtx);
-       mutex_unlock(&rdev->devlist_mtx);
-       cfg80211_unlock_rdev(rdev);
        rtnl_unlock();
 }
 
 {
        int err;
 
-       mutex_lock(&rdev->devlist_mtx);
-       /* might request scan - scan_mtx -> wdev_mtx dependency */
-       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(dev->ieee80211_ptr);
        err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
        wdev_unlock(dev->ieee80211_ptr);
-       mutex_unlock(&rdev->sched_scan_mtx);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
 
        ASSERT_RTNL();
        ASSERT_RDEV_LOCK(rdev);
 
-       mutex_lock(&rdev->devlist_mtx);
-
        list_for_each_entry(wdev, &rdev->wdev_list, list)
                cfg80211_process_wdev_events(wdev);
-
-       mutex_unlock(&rdev->devlist_mtx);
 }
 
 int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
                return -EBUSY;
 
        if (ntype != otype && netif_running(dev)) {
-               mutex_lock(&rdev->devlist_mtx);
                err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
                                                    ntype);
-               mutex_unlock(&rdev->devlist_mtx);
                if (err)
                        return err;
 
        if (!beacon_int)
                return -EINVAL;
 
-       mutex_lock(&rdev->devlist_mtx);
-
        list_for_each_entry(wdev, &rdev->wdev_list, list) {
                if (!wdev->beacon_interval)
                        continue;
                }
        }
 
-       mutex_unlock(&rdev->devlist_mtx);
-
        return res;
 }
 
        int i, j;
 
        ASSERT_RTNL();
-       lockdep_assert_held(&rdev->devlist_mtx);
 
        if (WARN_ON(hweight32(radar_detect) > 1))
                return -EINVAL;
 
        struct cfg80211_registered_device *rdev;
        struct vif_params vifparams;
        enum nl80211_iftype type;
-       int ret;
 
        rdev = wiphy_to_dev(wdev->wiphy);
 
 
        memset(&vifparams, 0, sizeof(vifparams));
 
-       cfg80211_lock_rdev(rdev);
-       ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
-       cfg80211_unlock_rdev(rdev);
-
-       return ret;
+       return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
 }
 EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
 
 {
        int err;
 
-       /* devlist mutex needed for possible IBSS re-join */
-       mutex_lock(&rdev->devlist_mtx);
        wdev_lock(dev->ieee80211_ptr);
        err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
                                        remove, tx_key, idx, params);
        wdev_unlock(dev->ieee80211_ptr);
-       mutex_unlock(&rdev->devlist_mtx);
 
        return err;
 }
        struct cfg80211_chan_def chandef = {
                .width = NL80211_CHAN_WIDTH_20_NOHT,
        };
-       int freq, err;
+       int freq;
 
        switch (wdev->iftype) {
        case NL80211_IFTYPE_STATION:
                chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
                if (!chandef.chan)
                        return -EINVAL;
-               mutex_lock(&rdev->devlist_mtx);
-               err = cfg80211_set_monitor_channel(rdev, &chandef);
-               mutex_unlock(&rdev->devlist_mtx);
-               return err;
+               return cfg80211_set_monitor_channel(rdev, &chandef);
        case NL80211_IFTYPE_MESH_POINT:
                freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
                if (freq < 0)
                chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
                if (!chandef.chan)
                        return -EINVAL;
-               mutex_lock(&rdev->devlist_mtx);
-               err = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
-               mutex_unlock(&rdev->devlist_mtx);
-               return err;
+               return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
        default:
                return -EOPNOTSUPP;
        }
 
                        return -EINVAL;
        }
 
-       cfg80211_lock_rdev(rdev);
-       mutex_lock(&rdev->devlist_mtx);
-       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(wdev);
 
        if (wdev->sme_state != CFG80211_SME_IDLE) {
        err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
        wdev_unlock(wdev);
-       mutex_unlock(&rdev->sched_scan_mtx);
-       mutex_unlock(&rdev->devlist_mtx);
-       cfg80211_unlock_rdev(rdev);
        return err;
 }
 
        if (len > 0 && ssid[len - 1] == '\0')
                len--;
 
-       cfg80211_lock_rdev(rdev);
-       mutex_lock(&rdev->devlist_mtx);
-       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(wdev);
 
        err = 0;
        err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
        wdev_unlock(wdev);
-       mutex_unlock(&rdev->sched_scan_mtx);
-       mutex_unlock(&rdev->devlist_mtx);
-       cfg80211_unlock_rdev(rdev);
        return err;
 }
 
        if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
                bssid = NULL;
 
-       cfg80211_lock_rdev(rdev);
-       mutex_lock(&rdev->devlist_mtx);
-       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(wdev);
 
        if (wdev->sme_state != CFG80211_SME_IDLE) {
        err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
        wdev_unlock(wdev);
-       mutex_unlock(&rdev->sched_scan_mtx);
-       mutex_unlock(&rdev->devlist_mtx);
-       cfg80211_unlock_rdev(rdev);
        return err;
 }