aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c30
-rw-r--r--net/wireless/core.h12
-rw-r--r--net/wireless/reg.c64
3 files changed, 79 insertions, 27 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index e347093ccc73..b1a354b7fc06 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -40,9 +40,8 @@ DEFINE_MUTEX(cfg80211_mutex);
40/* for debugfs */ 40/* for debugfs */
41static struct dentry *ieee80211_debugfs_dir; 41static struct dentry *ieee80211_debugfs_dir;
42 42
43/* requires cfg80211_drv_mutex to be held! */ 43/* requires cfg80211_mutex to be held! */
44static struct cfg80211_registered_device * 44struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx)
45cfg80211_drv_by_wiphy_idx(int wiphy_idx)
46{ 45{
47 struct cfg80211_registered_device *result = NULL, *drv; 46 struct cfg80211_registered_device *result = NULL, *drv;
48 47
@@ -61,6 +60,31 @@ cfg80211_drv_by_wiphy_idx(int wiphy_idx)
61 return result; 60 return result;
62} 61}
63 62
63int get_wiphy_idx(struct wiphy *wiphy)
64{
65 struct cfg80211_registered_device *drv;
66 if (!wiphy)
67 return WIPHY_IDX_STALE;
68 drv = wiphy_to_dev(wiphy);
69 return drv->wiphy_idx;
70}
71
72/* requires cfg80211_drv_mutex to be held! */
73struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
74{
75 struct cfg80211_registered_device *drv;
76
77 if (!wiphy_idx_valid(wiphy_idx))
78 return NULL;
79
80 assert_cfg80211_lock();
81
82 drv = cfg80211_drv_by_wiphy_idx(wiphy_idx);
83 if (!drv)
84 return NULL;
85 return &drv->wiphy;
86}
87
64/* requires cfg80211_mutex to be held! */ 88/* requires cfg80211_mutex to be held! */
65static struct cfg80211_registered_device * 89static struct cfg80211_registered_device *
66__cfg80211_drv_from_info(struct genl_info *info) 90__cfg80211_drv_from_info(struct genl_info *info)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 982cc6be3484..cd8e6e3ef116 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -79,6 +79,12 @@ static inline void assert_cfg80211_lock(void)
79 BUG_ON(!mutex_is_locked(&cfg80211_mutex)); 79 BUG_ON(!mutex_is_locked(&cfg80211_mutex));
80} 80}
81 81
82/*
83 * You can use this to mark a wiphy_idx as not having an associated wiphy.
84 * It guarantees cfg80211_drv_by_wiphy_idx(wiphy_idx) will return NULL
85 */
86#define WIPHY_IDX_STALE -1
87
82struct cfg80211_internal_bss { 88struct cfg80211_internal_bss {
83 struct list_head list; 89 struct list_head list;
84 struct rb_node rbn; 90 struct rb_node rbn;
@@ -88,6 +94,9 @@ struct cfg80211_internal_bss {
88 struct cfg80211_bss pub; 94 struct cfg80211_bss pub;
89}; 95};
90 96
97struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx);
98int get_wiphy_idx(struct wiphy *wiphy);
99
91/* 100/*
92 * This function returns a pointer to the driver 101 * This function returns a pointer to the driver
93 * that the genl_info item that is passed refers to. 102 * that the genl_info item that is passed refers to.
@@ -111,6 +120,9 @@ struct cfg80211_internal_bss {
111extern struct cfg80211_registered_device * 120extern struct cfg80211_registered_device *
112cfg80211_get_dev_from_info(struct genl_info *info); 121cfg80211_get_dev_from_info(struct genl_info *info);
113 122
123/* requires cfg80211_drv_mutex to be held! */
124struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
125
114/* identical to cfg80211_get_dev_from_info but only operate on ifindex */ 126/* identical to cfg80211_get_dev_from_info but only operate on ifindex */
115extern struct cfg80211_registered_device * 127extern struct cfg80211_registered_device *
116cfg80211_get_dev_from_ifindex(int ifindex); 128cfg80211_get_dev_from_ifindex(int ifindex);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e49ac9b2adac..d44f3b5481ad 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -831,9 +831,12 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
831 const struct ieee80211_power_rule *power_rule = NULL; 831 const struct ieee80211_power_rule *power_rule = NULL;
832 struct ieee80211_supported_band *sband; 832 struct ieee80211_supported_band *sband;
833 struct ieee80211_channel *chan; 833 struct ieee80211_channel *chan;
834 struct wiphy *request_wiphy;
834 835
835 assert_cfg80211_lock(); 836 assert_cfg80211_lock();
836 837
838 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
839
837 sband = wiphy->bands[band]; 840 sband = wiphy->bands[band];
838 BUG_ON(chan_idx >= sband->n_channels); 841 BUG_ON(chan_idx >= sband->n_channels);
839 chan = &sband->channels[chan_idx]; 842 chan = &sband->channels[chan_idx];
@@ -881,8 +884,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
881 power_rule = &reg_rule->power_rule; 884 power_rule = &reg_rule->power_rule;
882 885
883 if (last_request->initiator == REGDOM_SET_BY_DRIVER && 886 if (last_request->initiator == REGDOM_SET_BY_DRIVER &&
884 last_request->wiphy && last_request->wiphy == wiphy && 887 request_wiphy && request_wiphy == wiphy &&
885 last_request->wiphy->strict_regulatory) { 888 request_wiphy->strict_regulatory) {
886 /* This gaurantees the driver's requested regulatory domain 889 /* This gaurantees the driver's requested regulatory domain
887 * will always be used as a base for further regulatory 890 * will always be used as a base for further regulatory
888 * settings */ 891 * settings */
@@ -1046,6 +1049,7 @@ static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd,
1046static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, 1049static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
1047 const char *alpha2) 1050 const char *alpha2)
1048{ 1051{
1052 struct wiphy *last_wiphy = NULL;
1049 1053
1050 assert_cfg80211_lock(); 1054 assert_cfg80211_lock();
1051 1055
@@ -1059,10 +1063,13 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
1059 case REGDOM_SET_BY_CORE: 1063 case REGDOM_SET_BY_CORE:
1060 return -EINVAL; 1064 return -EINVAL;
1061 case REGDOM_SET_BY_COUNTRY_IE: 1065 case REGDOM_SET_BY_COUNTRY_IE:
1066
1067 last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
1068
1062 if (unlikely(!is_an_alpha2(alpha2))) 1069 if (unlikely(!is_an_alpha2(alpha2)))
1063 return -EINVAL; 1070 return -EINVAL;
1064 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { 1071 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
1065 if (last_request->wiphy != wiphy) { 1072 if (last_wiphy != wiphy) {
1066 /* 1073 /*
1067 * Two cards with two APs claiming different 1074 * Two cards with two APs claiming different
1068 * different Country IE alpha2s. We could 1075 * different Country IE alpha2s. We could
@@ -1163,7 +1170,7 @@ new_request:
1163 request->alpha2[0] = alpha2[0]; 1170 request->alpha2[0] = alpha2[0];
1164 request->alpha2[1] = alpha2[1]; 1171 request->alpha2[1] = alpha2[1];
1165 request->initiator = set_by; 1172 request->initiator = set_by;
1166 request->wiphy = wiphy; 1173 request->wiphy_idx = get_wiphy_idx(wiphy);
1167 request->intersect = intersect; 1174 request->intersect = intersect;
1168 request->country_ie_checksum = country_ie_checksum; 1175 request->country_ie_checksum = country_ie_checksum;
1169 request->country_ie_env = env; 1176 request->country_ie_env = env;
@@ -1226,11 +1233,16 @@ EXPORT_SYMBOL(regulatory_hint);
1226static bool reg_same_country_ie_hint(struct wiphy *wiphy, 1233static bool reg_same_country_ie_hint(struct wiphy *wiphy,
1227 u32 country_ie_checksum) 1234 u32 country_ie_checksum)
1228{ 1235{
1236 struct wiphy *request_wiphy;
1237
1229 assert_cfg80211_lock(); 1238 assert_cfg80211_lock();
1230 1239
1231 if (!last_request->wiphy) 1240 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
1241
1242 if (!request_wiphy)
1232 return false; 1243 return false;
1233 if (likely(last_request->wiphy != wiphy)) 1244
1245 if (likely(request_wiphy != wiphy))
1234 return !country_ie_integrity_changes(country_ie_checksum); 1246 return !country_ie_integrity_changes(country_ie_checksum);
1235 /* We should not have let these through at this point, they 1247 /* We should not have let these through at this point, they
1236 * should have been picked up earlier by the first alpha2 check 1248 * should have been picked up earlier by the first alpha2 check
@@ -1278,14 +1290,15 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1278 /* We will run this for *every* beacon processed for the BSSID, so 1290 /* We will run this for *every* beacon processed for the BSSID, so
1279 * we optimize an early check to exit out early if we don't have to 1291 * we optimize an early check to exit out early if we don't have to
1280 * do anything */ 1292 * do anything */
1281 if (likely(last_request->wiphy)) { 1293 if (likely(wiphy_idx_valid(last_request->wiphy_idx))) {
1282 struct cfg80211_registered_device *drv_last_ie; 1294 struct cfg80211_registered_device *drv_last_ie;
1283 1295
1284 drv_last_ie = wiphy_to_dev(last_request->wiphy); 1296 drv_last_ie =
1297 cfg80211_drv_by_wiphy_idx(last_request->wiphy_idx);
1285 1298
1286 /* Lets keep this simple -- we trust the first AP 1299 /* Lets keep this simple -- we trust the first AP
1287 * after we intersect with CRDA */ 1300 * after we intersect with CRDA */
1288 if (likely(last_request->wiphy == wiphy)) { 1301 if (likely(&drv_last_ie->wiphy == wiphy)) {
1289 /* Ignore IEs coming in on this wiphy with 1302 /* Ignore IEs coming in on this wiphy with
1290 * the same alpha2 and environment cap */ 1303 * the same alpha2 and environment cap */
1291 if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2, 1304 if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
@@ -1377,13 +1390,12 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
1377{ 1390{
1378 1391
1379 if (is_intersected_alpha2(rd->alpha2)) { 1392 if (is_intersected_alpha2(rd->alpha2)) {
1380 struct wiphy *wiphy = NULL;
1381 struct cfg80211_registered_device *drv;
1382 1393
1383 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { 1394 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
1384 if (last_request->wiphy) { 1395 struct cfg80211_registered_device *drv;
1385 wiphy = last_request->wiphy; 1396 drv = cfg80211_drv_by_wiphy_idx(
1386 drv = wiphy_to_dev(wiphy); 1397 last_request->wiphy_idx);
1398 if (drv) {
1387 printk(KERN_INFO "cfg80211: Current regulatory " 1399 printk(KERN_INFO "cfg80211: Current regulatory "
1388 "domain updated by AP to: %c%c\n", 1400 "domain updated by AP to: %c%c\n",
1389 drv->country_ie_alpha2[0], 1401 drv->country_ie_alpha2[0],
@@ -1449,7 +1461,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1449{ 1461{
1450 const struct ieee80211_regdomain *intersected_rd = NULL; 1462 const struct ieee80211_regdomain *intersected_rd = NULL;
1451 struct cfg80211_registered_device *drv = NULL; 1463 struct cfg80211_registered_device *drv = NULL;
1452 struct wiphy *wiphy = NULL; 1464 struct wiphy *request_wiphy;
1453 /* Some basic sanity checks first */ 1465 /* Some basic sanity checks first */
1454 1466
1455 if (is_world_regdom(rd->alpha2)) { 1467 if (is_world_regdom(rd->alpha2)) {
@@ -1477,8 +1489,6 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1477 return -EINVAL; 1489 return -EINVAL;
1478 } 1490 }
1479 1491
1480 wiphy = last_request->wiphy;
1481
1482 /* Now lets set the regulatory domain, update all driver channels 1492 /* Now lets set the regulatory domain, update all driver channels
1483 * and finally inform them of what we have done, in case they want 1493 * and finally inform them of what we have done, in case they want
1484 * to review or adjust their own settings based on their own 1494 * to review or adjust their own settings based on their own
@@ -1494,6 +1504,8 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1494 return -EINVAL; 1504 return -EINVAL;
1495 } 1505 }
1496 1506
1507 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
1508
1497 if (!last_request->intersect) { 1509 if (!last_request->intersect) {
1498 int r; 1510 int r;
1499 1511
@@ -1506,9 +1518,9 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1506 /* For a driver hint, lets copy the regulatory domain the 1518 /* For a driver hint, lets copy the regulatory domain the
1507 * driver wanted to the wiphy to deal with conflicts */ 1519 * driver wanted to the wiphy to deal with conflicts */
1508 1520
1509 BUG_ON(last_request->wiphy->regd); 1521 BUG_ON(request_wiphy->regd);
1510 1522
1511 r = reg_copy_regd(&last_request->wiphy->regd, rd); 1523 r = reg_copy_regd(&request_wiphy->regd, rd);
1512 if (r) 1524 if (r)
1513 return r; 1525 return r;
1514 1526
@@ -1529,7 +1541,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1529 * However if a driver requested this specific regulatory 1541 * However if a driver requested this specific regulatory
1530 * domain we keep it for its private use */ 1542 * domain we keep it for its private use */
1531 if (last_request->initiator == REGDOM_SET_BY_DRIVER) 1543 if (last_request->initiator == REGDOM_SET_BY_DRIVER)
1532 last_request->wiphy->regd = rd; 1544 request_wiphy->regd = rd;
1533 else 1545 else
1534 kfree(rd); 1546 kfree(rd);
1535 1547
@@ -1569,7 +1581,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1569 if (!intersected_rd) 1581 if (!intersected_rd)
1570 return -EINVAL; 1582 return -EINVAL;
1571 1583
1572 drv = wiphy_to_dev(wiphy); 1584 drv = wiphy_to_dev(request_wiphy);
1573 1585
1574 drv->country_ie_alpha2[0] = rd->alpha2[0]; 1586 drv->country_ie_alpha2[0] = rd->alpha2[0];
1575 drv->country_ie_alpha2[1] = rd->alpha2[1]; 1587 drv->country_ie_alpha2[1] = rd->alpha2[1];
@@ -1618,14 +1630,18 @@ int set_regdom(const struct ieee80211_regdomain *rd)
1618/* Caller must hold cfg80211_mutex */ 1630/* Caller must hold cfg80211_mutex */
1619void reg_device_remove(struct wiphy *wiphy) 1631void reg_device_remove(struct wiphy *wiphy)
1620{ 1632{
1633 struct wiphy *request_wiphy;
1634
1621 assert_cfg80211_lock(); 1635 assert_cfg80211_lock();
1622 1636
1637 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
1638
1623 kfree(wiphy->regd); 1639 kfree(wiphy->regd);
1624 if (!last_request || !last_request->wiphy) 1640 if (!last_request || !request_wiphy)
1625 return; 1641 return;
1626 if (last_request->wiphy != wiphy) 1642 if (request_wiphy != wiphy)
1627 return; 1643 return;
1628 last_request->wiphy = NULL; 1644 last_request->wiphy_idx = WIPHY_IDX_STALE;
1629 last_request->country_ie_env = ENVIRON_ANY; 1645 last_request->country_ie_env = ENVIRON_ANY;
1630} 1646}
1631 1647