diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2009-02-21 00:04:26 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-27 14:52:56 -0500 |
commit | 806a9e39670be4f1f861c346ec102a79e81b90c3 (patch) | |
tree | a83d6c06a1be211722385fd60433849db3a08625 /net/wireless | |
parent | 761cf7ecffc4bc079679e65c3b1ab107c1c1fb56 (diff) |
cfg80211: make regulatory_request use wiphy_idx instead of wiphy
We do this so later on we can move the pending requests onto a
workqueue. By using the wiphy_idx instead of the wiphy we can
later easily check if the wiphy has disappeared or not.
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 30 | ||||
-rw-r--r-- | net/wireless/core.h | 12 | ||||
-rw-r--r-- | net/wireless/reg.c | 64 |
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 */ |
41 | static struct dentry *ieee80211_debugfs_dir; | 41 | static struct dentry *ieee80211_debugfs_dir; |
42 | 42 | ||
43 | /* requires cfg80211_drv_mutex to be held! */ | 43 | /* requires cfg80211_mutex to be held! */ |
44 | static struct cfg80211_registered_device * | 44 | struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx) |
45 | cfg80211_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 | ||
63 | int 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! */ | ||
73 | struct 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! */ |
65 | static struct cfg80211_registered_device * | 89 | static 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 | |||
82 | struct cfg80211_internal_bss { | 88 | struct 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 | ||
97 | struct cfg80211_registered_device *cfg80211_drv_by_wiphy_idx(int wiphy_idx); | ||
98 | int 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 { | |||
111 | extern struct cfg80211_registered_device * | 120 | extern struct cfg80211_registered_device * |
112 | cfg80211_get_dev_from_info(struct genl_info *info); | 121 | cfg80211_get_dev_from_info(struct genl_info *info); |
113 | 122 | ||
123 | /* requires cfg80211_drv_mutex to be held! */ | ||
124 | struct 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 */ |
115 | extern struct cfg80211_registered_device * | 127 | extern struct cfg80211_registered_device * |
116 | cfg80211_get_dev_from_ifindex(int ifindex); | 128 | cfg80211_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 = ®_rule->power_rule; | 884 | power_rule = ®_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, | |||
1046 | static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | 1049 | static 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); | |||
1226 | static bool reg_same_country_ie_hint(struct wiphy *wiphy, | 1233 | static 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 */ |
1619 | void reg_device_remove(struct wiphy *wiphy) | 1631 | void 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 | ||