Commit 5fe231e8 authored by Johannes Berg's avatar Johannes Berg

cfg80211: vastly simplify locking

Virtually all code paths in cfg80211 already (need to) hold
the RTNL. As such, there's little point in having another
four mutexes for various parts of the code, they just cause
lock ordering issues (and much of the time, the RTNL and a
few of the others need thus be held.)

Simplify all this by getting rid of the extra four mutexes
and just use the RTNL throughout. Only a few code changes
were needed to do this and we can get rid of a work struct
for bonus points.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 73810b77
...@@ -1257,6 +1257,7 @@ struct cfg80211_ssid { ...@@ -1257,6 +1257,7 @@ struct cfg80211_ssid {
* @scan_start: time (in jiffies) when the scan started * @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for * @wdev: the wireless device to scan for
* @aborted: (internal) scan request was notified as aborted * @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 * @no_cck: used to send probe requests at non CCK rate in 2GHz band
*/ */
struct cfg80211_scan_request { struct cfg80211_scan_request {
...@@ -1274,7 +1275,7 @@ struct cfg80211_scan_request { ...@@ -1274,7 +1275,7 @@ struct cfg80211_scan_request {
/* internal */ /* internal */
struct wiphy *wiphy; struct wiphy *wiphy;
unsigned long scan_start; unsigned long scan_start;
bool aborted; bool aborted, notified;
bool no_cck; bool no_cck;
/* keep last */ /* keep last */
...@@ -2874,8 +2875,6 @@ struct wireless_dev { ...@@ -2874,8 +2875,6 @@ struct wireless_dev {
struct mutex mtx; struct mutex mtx;
struct work_struct cleanup_work;
bool use_4addr, p2p_started; bool use_4addr, p2p_started;
u8 address[ETH_ALEN] __aligned(sizeof(u16)); u8 address[ETH_ALEN] __aligned(sizeof(u16));
......
This diff is collapsed.
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
*/ */
#ifndef __NET_WIRELESS_CORE_H #ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H #define __NET_WIRELESS_CORE_H
#include <linux/mutex.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
...@@ -23,11 +22,6 @@ ...@@ -23,11 +22,6 @@
struct cfg80211_registered_device { struct cfg80211_registered_device {
const struct cfg80211_ops *ops; const struct cfg80211_ops *ops;
struct list_head list; 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 */ /* rfkill support */
struct rfkill_ops rfkill_ops; struct rfkill_ops rfkill_ops;
...@@ -49,9 +43,7 @@ struct cfg80211_registered_device { ...@@ -49,9 +43,7 @@ struct cfg80211_registered_device {
/* wiphy index, internal only */ /* wiphy index, internal only */
int wiphy_idx; int wiphy_idx;
/* associated wireless interfaces */ /* associated wireless interfaces, protected by rtnl or RCU */
struct mutex devlist_mtx;
/* protected by devlist_mtx or RCU */
struct list_head wdev_list; struct list_head wdev_list;
int devlist_generation, wdev_id; int devlist_generation, wdev_id;
int opencount; /* also protected by devlist_mtx */ int opencount; /* also protected by devlist_mtx */
...@@ -75,8 +67,6 @@ struct cfg80211_registered_device { ...@@ -75,8 +67,6 @@ struct cfg80211_registered_device {
struct work_struct scan_done_wk; struct work_struct scan_done_wk;
struct work_struct sched_scan_results_wk; struct work_struct sched_scan_results_wk;
struct mutex sched_scan_mtx;
#ifdef CONFIG_NL80211_TESTMODE #ifdef CONFIG_NL80211_TESTMODE
struct genl_info *testmode_info; struct genl_info *testmode_info;
#endif #endif
...@@ -120,15 +110,9 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) ...@@ -120,15 +110,9 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
} }
extern struct workqueue_struct *cfg80211_wq; extern struct workqueue_struct *cfg80211_wq;
extern struct mutex cfg80211_mutex;
extern struct list_head cfg80211_rdev_list; extern struct list_head cfg80211_rdev_list;
extern int cfg80211_rdev_list_generation; extern int cfg80211_rdev_list_generation;
static inline void assert_cfg80211_lock(void)
{
lockdep_assert_held(&cfg80211_mutex);
}
struct cfg80211_internal_bss { struct cfg80211_internal_bss {
struct list_head list; struct list_head list;
struct list_head hidden_list; struct list_head hidden_list;
...@@ -161,23 +145,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss) ...@@ -161,23 +145,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
int get_wiphy_idx(struct wiphy *wiphy); int get_wiphy_idx(struct wiphy *wiphy);
/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
struct net *net); 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) static inline void wdev_lock(struct wireless_dev *wdev)
__acquires(wdev) __acquires(wdev)
{ {
...@@ -192,7 +164,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev) ...@@ -192,7 +164,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
mutex_unlock(&wdev->mtx); 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) #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
......
...@@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file, ...@@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file,
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
mutex_lock(&cfg80211_mutex); rtnl_lock();
for (band = 0; band < IEEE80211_NUM_BANDS; band++) { for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
sband = wiphy->bands[band]; sband = wiphy->bands[band];
...@@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file, ...@@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file,
buf, buf_size, offset); buf, buf_size, offset);
} }
mutex_unlock(&cfg80211_mutex); rtnl_unlock();
r = simple_read_from_buffer(user_buf, count, ppos, buf, offset); r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
......
...@@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, ...@@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
int err; int err;
mutex_lock(&rdev->devlist_mtx); ASSERT_RTNL();
wdev_lock(wdev); wdev_lock(wdev);
err = __cfg80211_join_ibss(rdev, dev, params, connkeys); err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
...@@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, ...@@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
wdev->wext.ibss.channel_fixed = false; wdev->wext.ibss.channel_fixed = false;
} }
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev); wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev); err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
...@@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, ...@@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
memcpy(wdev->wext.ibss.ssid, ssid, len); memcpy(wdev->wext.ibss.ssid, ssid, len);
wdev->wext.ibss.ssid_len = len; wdev->wext.ibss.ssid_len = len;
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev); wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev); err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
...@@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, ...@@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
} else } else
wdev->wext.ibss.bssid = NULL; wdev->wext.ibss.bssid = NULL;
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev); wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev); err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
......
...@@ -186,11 +186,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, ...@@ -186,11 +186,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
int err; int err;
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev); wdev_lock(wdev);
err = __cfg80211_join_mesh(rdev, dev, setup, conf); err = __cfg80211_join_mesh(rdev, dev, setup, conf);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
......
...@@ -313,14 +313,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, ...@@ -313,14 +313,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
{ {
int err; int err;
mutex_lock(&rdev->devlist_mtx); ASSERT_RTNL();
wdev_lock(dev->ieee80211_ptr); wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
ssid, ssid_len, ie, ie_len, ssid, ssid_len, ie, ie_len,
key, key_len, key_idx, key, key_len, key_idx,
sae_data, sae_data_len); sae_data, sae_data_len);
wdev_unlock(dev->ieee80211_ptr); wdev_unlock(dev->ieee80211_ptr);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
...@@ -424,12 +424,12 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, ...@@ -424,12 +424,12 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
int err; int err;
mutex_lock(&rdev->devlist_mtx); ASSERT_RTNL();
wdev_lock(wdev); wdev_lock(wdev);
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid,
ssid, ssid_len, req); ssid, ssid_len, req);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
...@@ -844,7 +844,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) ...@@ -844,7 +844,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
dfs_update_channels_wk); dfs_update_channels_wk);
wiphy = &rdev->wiphy; wiphy = &rdev->wiphy;
mutex_lock(&cfg80211_mutex); rtnl_lock();
for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) { for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
sband = wiphy->bands[bandid]; sband = wiphy->bands[bandid];
if (!sband) if (!sband)
...@@ -877,7 +877,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) ...@@ -877,7 +877,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
check_again = true; check_again = true;
} }
} }
mutex_unlock(&cfg80211_mutex); rtnl_unlock();
/* reschedule if there are other channels waiting to be cleared again */ /* reschedule if there are other channels waiting to be cleared again */
if (check_again) if (check_again)
......
This diff is collapsed.
...@@ -377,7 +377,7 @@ static void reg_regdb_search(struct work_struct *work) ...@@ -377,7 +377,7 @@ static void reg_regdb_search(struct work_struct *work)
const struct ieee80211_regdomain *curdom, *regdom = NULL; const struct ieee80211_regdomain *curdom, *regdom = NULL;
int i; int i;
mutex_lock(&cfg80211_mutex); rtnl_lock();
mutex_lock(&reg_regdb_search_mutex); mutex_lock(&reg_regdb_search_mutex);
while (!list_empty(&reg_regdb_search_list)) { while (!list_empty(&reg_regdb_search_list)) {
...@@ -402,7 +402,7 @@ static void reg_regdb_search(struct work_struct *work) ...@@ -402,7 +402,7 @@ static void reg_regdb_search(struct work_struct *work)
if (!IS_ERR_OR_NULL(regdom)) if (!IS_ERR_OR_NULL(regdom))
set_regdom(regdom); set_regdom(regdom);
mutex_unlock(&cfg80211_mutex); rtnl_unlock();
} }
static DECLARE_WORK(reg_regdb_work, reg_regdb_search); static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
...@@ -1225,7 +1225,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) ...@@ -1225,7 +1225,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
struct wiphy *wiphy; struct wiphy *wiphy;
assert_cfg80211_lock(); ASSERT_RTNL();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) { list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
wiphy = &rdev->wiphy; wiphy = &rdev->wiphy;
...@@ -1570,21 +1570,19 @@ static void reg_process_pending_hints(void) ...@@ -1570,21 +1570,19 @@ static void reg_process_pending_hints(void)
{ {
struct regulatory_request *reg_request, *lr; struct regulatory_request *reg_request, *lr;
mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_mutex);
lr = get_last_request(); lr = get_last_request();
/* When last_request->processed becomes true this will be rescheduled */ /* When last_request->processed becomes true this will be rescheduled */
if (lr && !lr->processed) { if (lr && !lr->processed) {
REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n"); REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n");
goto out; return;
} }
spin_lock(&reg_requests_lock); spin_lock(&reg_requests_lock);
if (list_empty(&reg_requests_list)) { if (list_empty(&reg_requests_list)) {
spin_unlock(&reg_requests_lock); spin_unlock(&reg_requests_lock);
goto out; return;
} }
reg_request = list_first_entry(&reg_requests_list, reg_request = list_first_entry(&reg_requests_list,
...@@ -1595,10 +1593,6 @@ static void reg_process_pending_hints(void) ...@@ -1595,10 +1593,6 @@ static void reg_process_pending_hints(void)
spin_unlock(&reg_requests_lock); spin_unlock(&reg_requests_lock);
reg_process_hint(reg_request, reg_request->initiator); reg_process_hint(reg_request, reg_request->initiator);
out:
mutex_unlock(&reg_mutex);
mutex_unlock(&cfg80211_mutex);
} }
/* Processes beacon hints -- this has nothing to do with country IEs */ /* Processes beacon hints -- this has nothing to do with country IEs */
...@@ -1607,9 +1601,6 @@ static void reg_process_pending_beacon_hints(void) ...@@ -1607,9 +1601,6 @@ static void reg_process_pending_beacon_hints(void)
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
struct reg_beacon *pending_beacon, *tmp; struct reg_beacon *pending_beacon, *tmp;
mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_mutex);
/* This goes through the _pending_ beacon list */ /* This goes through the _pending_ beacon list */
spin_lock_bh(&reg_pending_beacons_lock); spin_lock_bh(&reg_pending_beacons_lock);
...@@ -1626,14 +1617,16 @@ static void reg_process_pending_beacon_hints(void) ...@@ -1626,14 +1617,16 @@ static void reg_process_pending_beacon_hints(void)
} }
spin_unlock_bh(&reg_pending_beacons_lock); spin_unlock_bh(&reg_pending_beacons_lock);
mutex_unlock(&reg_mutex);
mutex_unlock(&cfg80211_mutex);
} }
static void reg_todo(struct work_struct *work) static void reg_todo(struct work_struct *work)
{ {
rtnl_lock();
mutex_lock(&reg_mutex);
reg_process_pending_hints(); reg_process_pending_hints();
reg_process_pending_beacon_hints(); reg_process_pending_beacon_hints();
mutex_unlock(&reg_mutex);
rtnl_unlock();
} }
static void queue_regulatory_request(struct regulatory_request *request) static void queue_regulatory_request(struct regulatory_request *request)
...@@ -1717,10 +1710,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) ...@@ -1717,10 +1710,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
} }
EXPORT_SYMBOL(regulatory_hint); 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, void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
const u8 *country_ie, u8 country_ie_len) const u8 *country_ie, u8 country_ie_len)
{ {
...@@ -1752,7 +1741,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, ...@@ -1752,7 +1741,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
/* /*
* We will run this only upon a successful connection on cfg80211. * We will run this only upon a successful connection on cfg80211.
* We leave conflict resolution to the workqueue, where can hold * We leave conflict resolution to the workqueue, where can hold
* cfg80211_mutex. * the RTNL.
*/ */
if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
lr->wiphy_idx != WIPHY_IDX_INVALID) lr->wiphy_idx != WIPHY_IDX_INVALID)
...@@ -1858,7 +1847,8 @@ static void restore_regulatory_settings(bool reset_user) ...@@ -1858,7 +1847,8 @@ static void restore_regulatory_settings(bool reset_user)
LIST_HEAD(tmp_reg_req_list); LIST_HEAD(tmp_reg_req_list);
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
mutex_lock(&cfg80211_mutex); ASSERT_RTNL();
mutex_lock(&reg_mutex); mutex_lock(&reg_mutex);
reset_regdomains(true, &world_regdom); reset_regdomains(true, &world_regdom);
...@@ -1915,7 +1905,6 @@ static void restore_regulatory_settings(bool reset_user) ...@@ -1915,7 +1905,6 @@ static void restore_regulatory_settings(bool reset_user)
spin_unlock(&reg_requests_lock); spin_unlock(&reg_requests_lock);
mutex_unlock(&reg_mutex); mutex_unlock(&reg_mutex);
mutex_unlock(&cfg80211_mutex);
REG_DBG_PRINT("Kicking the queue\n"); REG_DBG_PRINT("Kicking the queue\n");
...@@ -2297,7 +2286,6 @@ void wiphy_regulatory_register(struct wiphy *wiphy) ...@@ -2297,7 +2286,6 @@ void wiphy_regulatory_register(struct wiphy *wiphy)
mutex_unlock(&reg_mutex); mutex_unlock(&reg_mutex);
} }
/* Caller must hold cfg80211_mutex */
void wiphy_regulatory_deregister(struct wiphy *wiphy) void wiphy_regulatory_deregister(struct wiphy *wiphy)
{ {
struct wiphy *request_wiphy = NULL; struct wiphy *request_wiphy = NULL;
......
...@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) ...@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
union iwreq_data wrqu; union iwreq_data wrqu;
#endif #endif
lockdep_assert_held(&rdev->sched_scan_mtx); ASSERT_RTNL();
request = rdev->scan_req; request = rdev->scan_req;
...@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk) ...@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device, rdev = container_of(wk, struct cfg80211_registered_device,
scan_done_wk); scan_done_wk);
mutex_lock(&rdev->sched_scan_mtx); rtnl_lock();
___cfg80211_scan_done(rdev, false); ___cfg80211_scan_done(rdev, false);
mutex_unlock(&rdev->sched_scan_mtx); rtnl_unlock();
} }
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
...@@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) ...@@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
request->aborted = aborted; request->aborted = aborted;
request->notified = true;
queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk); queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
} }
EXPORT_SYMBOL(cfg80211_scan_done); EXPORT_SYMBOL(cfg80211_scan_done);
...@@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) ...@@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
request = rdev->sched_scan_req; 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 */ /* we don't have sched_scan_req anymore if the scan is stopping */
if (request) { if (request) {
...@@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) ...@@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
nl80211_send_sched_scan_results(rdev, request->dev); nl80211_send_sched_scan_results(rdev, request->dev);
} }
mutex_unlock(&rdev->sched_scan_mtx); rtnl_unlock();
} }
void cfg80211_sched_scan_results(struct wiphy *wiphy) void cfg80211_sched_scan_results(struct wiphy *wiphy)
...@@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy) ...@@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
trace_cfg80211_sched_scan_stopped(wiphy); trace_cfg80211_sched_scan_stopped(wiphy);
mutex_lock(&rdev->sched_scan_mtx); rtnl_lock();
__cfg80211_stop_sched_scan(rdev, true); __cfg80211_stop_sched_scan(rdev, true);
mutex_unlock(&rdev->sched_scan_mtx); rtnl_unlock();
} }
EXPORT_SYMBOL(cfg80211_sched_scan_stopped); EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
...@@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, ...@@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
{ {
struct net_device *dev; struct net_device *dev;
lockdep_assert_held(&rdev->sched_scan_mtx); ASSERT_RTNL();
if (!rdev->sched_scan_req) if (!rdev->sched_scan_req)
return -ENOENT; return -ENOENT;
...@@ -1043,21 +1044,19 @@ EXPORT_SYMBOL(cfg80211_unlink_bss); ...@@ -1043,21 +1044,19 @@ EXPORT_SYMBOL(cfg80211_unlink_bss);
static struct cfg80211_registered_device * static struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) 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; struct net_device *dev;
mutex_lock(&cfg80211_mutex); ASSERT_RTNL();
dev = dev_get_by_index(net, ifindex); dev = dev_get_by_index(net, ifindex);
if (!dev) if (!dev)
goto out; return ERR_PTR(-ENODEV);
if (dev->ieee80211_ptr) { if (dev->ieee80211_ptr)
rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
mutex_lock(&rdev->mtx); else
} else
rdev = ERR_PTR(-ENODEV); rdev = ERR_PTR(-ENODEV);
dev_put(dev); dev_put(dev);
out:
mutex_unlock(&cfg80211_mutex);
return rdev; return rdev;
} }
...@@ -1083,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev, ...@@ -1083,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev,
if (IS_ERR(rdev)) if (IS_ERR(rdev))
return PTR_ERR(rdev); return PTR_ERR(rdev);
mutex_lock(&rdev->sched_scan_mtx);
if (rdev->scan_req) { if (rdev->scan_req) {
err = -EBUSY; err = -EBUSY;
goto out; goto out;
...@@ -1190,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, ...@@ -1190,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
dev_hold(dev); dev_hold(dev);
} }
out: out:
mutex_unlock(&rdev->sched_scan_mtx);
kfree(creq); kfree(creq);
cfg80211_unlock_rdev(rdev);
return err; return err;
} }
EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
...@@ -1491,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev, ...@@ -1491,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev,
if (IS_ERR(rdev)) if (IS_ERR(rdev))
return PTR_ERR(rdev); return PTR_ERR(rdev);
if (rdev->scan_req) { if (rdev->scan_req)
res = -EAGAIN; return -EAGAIN;
goto out;
}
res = ieee80211_scan_results(rdev, info, extra, data->length); res = ieee80211_scan_results(rdev, info, extra, data->length);
data->length = 0; data->length = 0;
...@@ -1503,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev, ...@@ -1503,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev,
res = 0; res = 0;
} }
out:
cfg80211_unlock_rdev(rdev);
return res; return res;
} }
EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
......
...@@ -43,35 +43,29 @@ static bool cfg80211_is_all_idle(void) ...@@ -43,35 +43,29 @@ static bool cfg80211_is_all_idle(void)
struct wireless_dev *wdev; struct wireless_dev *wdev;
bool is_all_idle = true; bool is_all_idle = true;
mutex_lock(&cfg80211_mutex);
/* /*
* All devices must be idle as otherwise if you are actively * All devices must be idle as otherwise if you are actively
* scanning some new beacon hints could be learned and would * scanning some new beacon hints could be learned and would
* count as new regulatory hints. * count as new regulatory hints.
*/ */
list_for_each_entry(rdev, &cfg80211_rdev_list, list) { list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
cfg80211_lock_rdev(rdev);
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev); wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) if (wdev->sme_state != CFG80211_SME_IDLE)
is_all_idle = false; is_all_idle = false;
wdev_unlock(wdev); wdev_unlock(wdev);
} }
cfg80211_unlock_rdev(rdev);
} }
mutex_unlock(&cfg80211_mutex);
return is_all_idle; return is_all_idle;
} }
static void disconnect_work(struct work_struct *work) static void disconnect_work(struct work_struct *work)
{ {
if (!cfg80211_is_all_idle()) rtnl_lock();
return; if (cfg80211_is_all_idle())
regulatory_hint_disconnect();
regulatory_hint_disconnect(); rtnl_unlock();
} }
static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
...@@ -85,7 +79,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) ...@@ -85,7 +79,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
ASSERT_RTNL(); ASSERT_RTNL();
ASSERT_RDEV_LOCK(rdev); ASSERT_RDEV_LOCK(rdev);
ASSERT_WDEV_LOCK(wdev); ASSERT_WDEV_LOCK(wdev);
lockdep_assert_held(&rdev->sched_scan_mtx);
if (rdev->scan_req) if (rdev->scan_req)
return -EBUSY; return -EBUSY;
...@@ -226,9 +219,6 @@ void cfg80211_conn_work(struct work_struct *work) ...@@ -226,9 +219,6 @@ void cfg80211_conn_work(struct work_struct *work)
u8 bssid_buf[ETH_ALEN], *bssid = NULL; u8 bssid_buf[ETH_ALEN], *bssid = NULL;
rtnl_lock(); 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) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (!wdev->netdev) if (!wdev->netdev)
...@@ -256,9 +246,6 @@ void cfg80211_conn_work(struct work_struct *work) ...@@ -256,9 +246,6 @@ void cfg80211_conn_work(struct work_struct *work)
wdev_unlock(wdev); wdev_unlock(wdev);
} }
mutex_unlock(&rdev->sched_scan_mtx);
mutex_unlock(&rdev->devlist_mtx);
cfg80211_unlock_rdev(rdev);
rtnl_unlock(); rtnl_unlock();
} }
...@@ -931,14 +918,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, ...@@ -931,14 +918,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
{ {
int err; 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); wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
wdev_unlock(dev->ieee80211_ptr); wdev_unlock(dev->ieee80211_ptr);
mutex_unlock(&rdev->sched_scan_mtx);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
......
...@@ -808,12 +808,8 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev) ...@@ -808,12 +808,8 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
ASSERT_RTNL(); ASSERT_RTNL();
ASSERT_RDEV_LOCK(rdev); ASSERT_RDEV_LOCK(rdev);
mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) list_for_each_entry(wdev, &rdev->wdev_list, list)
cfg80211_process_wdev_events(wdev); cfg80211_process_wdev_events(wdev);
mutex_unlock(&rdev->devlist_mtx);
} }
int cfg80211_change_iface(struct cfg80211_registered_device *rdev, int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
...@@ -845,10 +841,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, ...@@ -845,10 +841,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
return -EBUSY; return -EBUSY;
if (ntype != otype && netif_running(dev)) { if (ntype != otype && netif_running(dev)) {
mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
ntype); ntype);
mutex_unlock(&rdev->devlist_mtx);
if (err) if (err)
return err; return err;
...@@ -1210,8 +1204,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, ...@@ -1210,8 +1204,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
if (!beacon_int) if (!beacon_int)
return -EINVAL; return -EINVAL;
mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (!wdev->beacon_interval) if (!wdev->beacon_interval)
continue; continue;
...@@ -1221,8 +1213,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, ...@@ -1221,8 +1213,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
} }
} }
mutex_unlock(&rdev->devlist_mtx);
return res; return res;
} }
...@@ -1246,7 +1236,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, ...@@ -1246,7 +1236,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
int i, j; int i, j;
ASSERT_RTNL(); ASSERT_RTNL();
lockdep_assert_held(&rdev->devlist_mtx);
if (WARN_ON(hweight32(radar_detect) > 1)) if (WARN_ON(hweight32(radar_detect) > 1))
return -EINVAL; return -EINVAL;
......
...@@ -72,7 +72,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, ...@@ -72,7 +72,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
struct vif_params vifparams; struct vif_params vifparams;
enum nl80211_iftype type; enum nl80211_iftype type;
int ret;
rdev = wiphy_to_dev(wdev->wiphy); rdev = wiphy_to_dev(wdev->wiphy);
...@@ -98,11 +97,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, ...@@ -98,11 +97,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
memset(&vifparams, 0, sizeof(vifparams)); memset(&vifparams, 0, sizeof(vifparams));
cfg80211_lock_rdev(rdev); return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
cfg80211_unlock_rdev(rdev);
return ret;
} }
EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode); EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
...@@ -579,13 +574,10 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, ...@@ -579,13 +574,10 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
{ {
int err; int err;
/* devlist mutex needed for possible IBSS re-join */
mutex_lock(&rdev->devlist_mtx);
wdev_lock(dev->ieee80211_ptr); wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_set_encryption(rdev, dev, pairwise, addr, err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
remove, tx_key, idx, params); remove, tx_key, idx, params);
wdev_unlock(dev->ieee80211_ptr); wdev_unlock(dev->ieee80211_ptr);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
...@@ -787,7 +779,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, ...@@ -787,7 +779,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
struct cfg80211_chan_def chandef = { struct cfg80211_chan_def chandef = {
.width = NL80211_CHAN_WIDTH_20_NOHT, .width = NL80211_CHAN_WIDTH_20_NOHT,
}; };
int freq, err; int freq;
switch (wdev->iftype) { switch (wdev->iftype) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
...@@ -804,10 +796,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, ...@@ -804,10 +796,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
if (!chandef.chan) if (!chandef.chan)
return -EINVAL; return -EINVAL;
mutex_lock(&rdev->devlist_mtx); return cfg80211_set_monitor_channel(rdev, &chandef);
err = cfg80211_set_monitor_channel(rdev, &chandef);
mutex_unlock(&rdev->devlist_mtx);
return err;
case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
if (freq < 0) if (freq < 0)
...@@ -818,10 +807,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, ...@@ -818,10 +807,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
if (!chandef.chan) if (!chandef.chan)
return -EINVAL; return -EINVAL;
mutex_lock(&rdev->devlist_mtx); return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
err = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
mutex_unlock(&rdev->devlist_mtx);
return err;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -87,9 +87,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, ...@@ -87,9 +87,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
return -EINVAL; return -EINVAL;
} }
cfg80211_lock_rdev(rdev);
mutex_lock(&rdev->devlist_mtx);
mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev); wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) { if (wdev->sme_state != CFG80211_SME_IDLE) {
...@@ -136,9 +133,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, ...@@ -136,9 +133,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev); err = cfg80211_mgd_wext_connect(rdev, wdev);
out: out:
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->sched_scan_mtx);
mutex_unlock(&rdev->devlist_mtx);
cfg80211_unlock_rdev(rdev);
return err; return err;
} }
...@@ -190,9 +184,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, ...@@ -190,9 +184,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
if (len > 0 && ssid[len - 1] == '\0') if (len > 0 && ssid[len - 1] == '\0')
len--; len--;
cfg80211_lock_rdev(rdev);
mutex_lock(&rdev->devlist_mtx);
mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev); wdev_lock(wdev);
err = 0; err = 0;
...@@ -226,9 +217,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, ...@@ -226,9 +217,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev); err = cfg80211_mgd_wext_connect(rdev, wdev);
out: out:
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->sched_scan_mtx);
mutex_unlock(&rdev->devlist_mtx);
cfg80211_unlock_rdev(rdev);
return err; return err;
} }
...@@ -287,9 +275,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, ...@@ -287,9 +275,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
bssid = NULL; bssid = NULL;
cfg80211_lock_rdev(rdev);
mutex_lock(&rdev->devlist_mtx);
mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev); wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) { if (wdev->sme_state != CFG80211_SME_IDLE) {
...@@ -318,9 +303,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, ...@@ -318,9 +303,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev); err = cfg80211_mgd_wext_connect(rdev, wdev);
out: out:
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->sched_scan_mtx);
mutex_unlock(&rdev->devlist_mtx);
cfg80211_unlock_rdev(rdev);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment