summaryrefslogtreecommitdiffstats
path: root/net/wireless/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r--net/wireless/core.c103
1 files changed, 70 insertions, 33 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 0668b2bfc1da..dd7f222919fe 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -7,7 +7,6 @@
#include <linux/if.h>
#include <linux/module.h>
#include <linux/err.h>
-#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/nl80211.h>
#include <linux/debugfs.h>
@@ -31,18 +30,29 @@ MODULE_DESCRIPTION("wireless configuration support");
* only read the list, and that can happen quite
* often because we need to do it for each command */
LIST_HEAD(cfg80211_drv_list);
-DEFINE_MUTEX(cfg80211_drv_mutex);
+
+/*
+ * This is used to protect the cfg80211_drv_list, cfg80211_regdomain,
+ * country_ie_regdomain, the reg_beacon_list and the the last regulatory
+ * request receipt (last_request).
+ */
+DEFINE_MUTEX(cfg80211_mutex);
/* for debugfs */
static struct dentry *ieee80211_debugfs_dir;
-/* requires cfg80211_drv_mutex to be held! */
-static struct cfg80211_registered_device *cfg80211_drv_by_wiphy(int wiphy)
+/* requires cfg80211_mutex to be held! */
+struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx)
{
struct cfg80211_registered_device *result = NULL, *drv;
+ if (!wiphy_idx_valid(wiphy_idx))
+ return NULL;
+
+ assert_cfg80211_lock();
+
list_for_each_entry(drv, &cfg80211_drv_list, list) {
- if (drv->idx == wiphy) {
+ if (drv->wiphy_idx == wiphy_idx) {
result = drv;
break;
}
@@ -51,17 +61,44 @@ static struct cfg80211_registered_device *cfg80211_drv_by_wiphy(int wiphy)
return result;
}
+int get_wiphy_idx(struct wiphy *wiphy)
+{
+ struct cfg80211_registered_device *drv;
+ if (!wiphy)
+ return WIPHY_IDX_STALE;
+ drv = wiphy_to_dev(wiphy);
+ return drv->wiphy_idx;
+}
+
/* requires cfg80211_drv_mutex to be held! */
+struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
+{
+ struct cfg80211_registered_device *drv;
+
+ if (!wiphy_idx_valid(wiphy_idx))
+ return NULL;
+
+ assert_cfg80211_lock();
+
+ drv = cfg80211_drv_by_wiphy_idx(wiphy_idx);
+ if (!drv)
+ return NULL;
+ return &drv->wiphy;
+}
+
+/* requires cfg80211_mutex to be held! */
static struct cfg80211_registered_device *
__cfg80211_drv_from_info(struct genl_info *info)
{
int ifindex;
- struct cfg80211_registered_device *bywiphy = NULL, *byifidx = NULL;
+ struct cfg80211_registered_device *bywiphyidx = NULL, *byifidx = NULL;
struct net_device *dev;
int err = -EINVAL;
+ assert_cfg80211_lock();
+
if (info->attrs[NL80211_ATTR_WIPHY]) {
- bywiphy = cfg80211_drv_by_wiphy(
+ bywiphyidx = cfg80211_drv_by_wiphy_idx(
nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
err = -ENODEV;
}
@@ -78,14 +115,14 @@ __cfg80211_drv_from_info(struct genl_info *info)
err = -ENODEV;
}
- if (bywiphy && byifidx) {
- if (bywiphy != byifidx)
+ if (bywiphyidx && byifidx) {
+ if (bywiphyidx != byifidx)
return ERR_PTR(-EINVAL);
else
- return bywiphy; /* == byifidx */
+ return bywiphyidx; /* == byifidx */
}
- if (bywiphy)
- return bywiphy;
+ if (bywiphyidx)
+ return bywiphyidx;
if (byifidx)
return byifidx;
@@ -98,7 +135,7 @@ cfg80211_get_dev_from_info(struct genl_info *info)
{
struct cfg80211_registered_device *drv;
- mutex_lock(&cfg80211_drv_mutex);
+ mutex_lock(&cfg80211_mutex);
drv = __cfg80211_drv_from_info(info);
/* if it is not an error we grab the lock on
@@ -107,7 +144,7 @@ cfg80211_get_dev_from_info(struct genl_info *info)
if (!IS_ERR(drv))
mutex_lock(&drv->mtx);
- mutex_unlock(&cfg80211_drv_mutex);
+ mutex_unlock(&cfg80211_mutex);
return drv;
}
@@ -118,7 +155,7 @@ cfg80211_get_dev_from_ifindex(int ifindex)
struct cfg80211_registered_device *drv = ERR_PTR(-ENODEV);
struct net_device *dev;
- mutex_lock(&cfg80211_drv_mutex);
+ mutex_lock(&cfg80211_mutex);
dev = dev_get_by_index(&init_net, ifindex);
if (!dev)
goto out;
@@ -129,7 +166,7 @@ cfg80211_get_dev_from_ifindex(int ifindex)
drv = ERR_PTR(-ENODEV);
dev_put(dev);
out:
- mutex_unlock(&cfg80211_drv_mutex);
+ mutex_unlock(&cfg80211_mutex);
return drv;
}
@@ -143,16 +180,16 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname)
{
struct cfg80211_registered_device *drv;
- int idx, taken = -1, result, digits;
+ int wiphy_idx, taken = -1, result, digits;
- mutex_lock(&cfg80211_drv_mutex);
+ mutex_lock(&cfg80211_mutex);
/* prohibit calling the thing phy%d when %d is not its number */
- sscanf(newname, PHY_NAME "%d%n", &idx, &taken);
- if (taken == strlen(newname) && idx != rdev->idx) {
- /* count number of places needed to print idx */
+ sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
+ if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
+ /* count number of places needed to print wiphy_idx */
digits = 1;
- while (idx /= 10)
+ while (wiphy_idx /= 10)
digits++;
/*
* deny the name if it is phy<idx> where <idx> is printed
@@ -193,7 +230,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
result = 0;
out_unlock:
- mutex_unlock(&cfg80211_drv_mutex);
+ mutex_unlock(&cfg80211_mutex);
if (result == 0)
nl80211_notify_dev_rename(rdev);
@@ -220,22 +257,22 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
drv->ops = ops;
- mutex_lock(&cfg80211_drv_mutex);
+ mutex_lock(&cfg80211_mutex);
- drv->idx = wiphy_counter++;
+ drv->wiphy_idx = wiphy_counter++;
- if (unlikely(drv->idx < 0)) {
+ if (unlikely(!wiphy_idx_valid(drv->wiphy_idx))) {
wiphy_counter--;
- mutex_unlock(&cfg80211_drv_mutex);
+ mutex_unlock(&cfg80211_mutex);
/* ugh, wrapped! */
kfree(drv);
return NULL;
}
- mutex_unlock(&cfg80211_drv_mutex);
+ mutex_unlock(&cfg80211_mutex);
/* give it a proper name */
- dev_set_name(&drv->wiphy.dev, PHY_NAME "%d", drv->idx);
+ dev_set_name(&drv->wiphy.dev, PHY_NAME "%d", drv->wiphy_idx);
mutex_init(&drv->mtx);
mutex_init(&drv->devlist_mtx);
@@ -310,7 +347,7 @@ int wiphy_register(struct wiphy *wiphy)
/* check and set up bitrates */
ieee80211_set_bitrate_flags(wiphy);
- mutex_lock(&cfg80211_drv_mutex);
+ mutex_lock(&cfg80211_mutex);
/* set up regulatory info */
wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE);
@@ -330,7 +367,7 @@ int wiphy_register(struct wiphy *wiphy)
res = 0;
out_unlock:
- mutex_unlock(&cfg80211_drv_mutex);
+ mutex_unlock(&cfg80211_mutex);
return res;
}
EXPORT_SYMBOL(wiphy_register);
@@ -340,7 +377,7 @@ void wiphy_unregister(struct wiphy *wiphy)
struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
/* protect the device list */
- mutex_lock(&cfg80211_drv_mutex);
+ mutex_lock(&cfg80211_mutex);
BUG_ON(!list_empty(&drv->netdev_list));
@@ -366,7 +403,7 @@ void wiphy_unregister(struct wiphy *wiphy)
device_del(&drv->wiphy.dev);
debugfs_remove(drv->wiphy.debugfsdir);
- mutex_unlock(&cfg80211_drv_mutex);
+ mutex_unlock(&cfg80211_mutex);
}
EXPORT_SYMBOL(wiphy_unregister);