summaryrefslogtreecommitdiff
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c116
1 files changed, 72 insertions, 44 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 58df98f10990..eb8b8ed16155 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -41,6 +41,7 @@
#include <net/cfg80211.h>
#include "core.h"
#include "reg.h"
+#include "nl80211.h"
/* Receipt of information from last regulatory request */
static struct regulatory_request *last_request;
@@ -86,20 +87,31 @@ struct reg_beacon {
/* We keep a static world regulatory domain in case of the absence of CRDA */
static const struct ieee80211_regdomain world_regdom = {
- .n_reg_rules = 3,
+ .n_reg_rules = 5,
.alpha2 = "00",
.reg_rules = {
/* IEEE 802.11b/g, channels 1..11 */
REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
- /* IEEE 802.11a, channel 36..48 */
- REG_RULE(5180-10, 5240+10, 40, 6, 23,
+ /* IEEE 802.11b/g, channels 12..13. No HT40
+ * channel fits here. */
+ REG_RULE(2467-10, 2472+10, 20, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
+ /* IEEE 802.11 channel 14 - Only JP enables
+ * this and for 802.11b only */
+ REG_RULE(2484-10, 2484+10, 20, 6, 20,
+ NL80211_RRF_PASSIVE_SCAN |
+ NL80211_RRF_NO_IBSS |
+ NL80211_RRF_NO_OFDM),
+ /* IEEE 802.11a, channel 36..48 */
+ REG_RULE(5180-10, 5240+10, 40, 6, 20,
+ NL80211_RRF_PASSIVE_SCAN |
+ NL80211_RRF_NO_IBSS),
/* NB: 5260 MHz - 5700 MHz requies DFS */
/* IEEE 802.11a, channel 149..165 */
- REG_RULE(5745-10, 5825+10, 40, 6, 23,
+ REG_RULE(5745-10, 5825+10, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
}
@@ -846,8 +858,8 @@ static int freq_reg_info_regd(struct wiphy *wiphy,
* Follow the driver's regulatory domain, if present, unless a country
* IE has been processed or a user wants to help complaince further
*/
- if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE &&
- last_request->initiator != REGDOM_SET_BY_USER &&
+ if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
+ last_request->initiator != NL80211_REGDOM_SET_BY_USER &&
wiphy->regd)
regd = wiphy->regd;
@@ -932,7 +944,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
* http://tinyurl.com/11d-clarification
*/
if (r == -ERANGE &&
- last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
+ last_request->initiator ==
+ NL80211_REGDOM_SET_BY_COUNTRY_IE) {
#ifdef CONFIG_CFG80211_REG_DEBUG
printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz "
"intact on %s - no rule found in band on "
@@ -945,7 +958,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
* for the band so we respect its band definitions
*/
#ifdef CONFIG_CFG80211_REG_DEBUG
- if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
+ if (last_request->initiator ==
+ NL80211_REGDOM_SET_BY_COUNTRY_IE)
printk(KERN_DEBUG "cfg80211: Disabling "
"channel %d MHz on %s due to "
"Country IE\n",
@@ -959,7 +973,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
power_rule = &reg_rule->power_rule;
- if (last_request->initiator == REGDOM_SET_BY_DRIVER &&
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
request_wiphy && request_wiphy == wiphy &&
request_wiphy->strict_regulatory) {
/*
@@ -1000,11 +1014,12 @@ static void handle_band(struct wiphy *wiphy, enum ieee80211_band band)
handle_channel(wiphy, band, i);
}
-static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby)
+static bool ignore_reg_update(struct wiphy *wiphy,
+ enum nl80211_reg_initiator initiator)
{
if (!last_request)
return true;
- if (setby == REGDOM_SET_BY_CORE &&
+ if (initiator == NL80211_REGDOM_SET_BY_CORE &&
wiphy->custom_regulatory)
return true;
/*
@@ -1017,12 +1032,12 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby)
return false;
}
-static void update_all_wiphy_regulatory(enum reg_set_by setby)
+static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
{
struct cfg80211_registered_device *drv;
list_for_each_entry(drv, &cfg80211_drv_list, list)
- wiphy_update_regulatory(&drv->wiphy, setby);
+ wiphy_update_regulatory(&drv->wiphy, initiator);
}
static void handle_reg_beacon(struct wiphy *wiphy,
@@ -1113,7 +1128,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy)
if (is_world_regdom(cfg80211_regdomain->alpha2) ||
(wiphy->regd && is_world_regdom(wiphy->regd->alpha2)))
return true;
- if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE &&
+ if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
wiphy->custom_regulatory)
return true;
return false;
@@ -1127,11 +1142,12 @@ static void reg_process_beacons(struct wiphy *wiphy)
wiphy_update_beacon_reg(wiphy);
}
-void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby)
+void wiphy_update_regulatory(struct wiphy *wiphy,
+ enum nl80211_reg_initiator initiator)
{
enum ieee80211_band band;
- if (ignore_reg_update(wiphy, setby))
+ if (ignore_reg_update(wiphy, initiator))
goto out;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (wiphy->bands[band])
@@ -1244,17 +1260,16 @@ static int ignore_request(struct wiphy *wiphy,
return 0;
switch (pending_request->initiator) {
- case REGDOM_SET_BY_INIT:
+ case NL80211_REGDOM_SET_BY_CORE:
return -EINVAL;
- case REGDOM_SET_BY_CORE:
- return -EINVAL;
- case REGDOM_SET_BY_COUNTRY_IE:
+ case NL80211_REGDOM_SET_BY_COUNTRY_IE:
last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
if (unlikely(!is_an_alpha2(pending_request->alpha2)))
return -EINVAL;
- if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
+ if (last_request->initiator ==
+ NL80211_REGDOM_SET_BY_COUNTRY_IE) {
if (last_wiphy != wiphy) {
/*
* Two cards with two APs claiming different
@@ -1275,8 +1290,8 @@ static int ignore_request(struct wiphy *wiphy,
return -EALREADY;
}
return REG_INTERSECT;
- case REGDOM_SET_BY_DRIVER:
- if (last_request->initiator == REGDOM_SET_BY_CORE) {
+ case NL80211_REGDOM_SET_BY_DRIVER:
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
if (is_old_static_regdom(cfg80211_regdomain))
return 0;
if (regdom_changes(pending_request->alpha2))
@@ -1289,28 +1304,28 @@ static int ignore_request(struct wiphy *wiphy,
* back in or if you add a new device for which the previously
* loaded card also agrees on the regulatory domain.
*/
- if (last_request->initiator == REGDOM_SET_BY_DRIVER &&
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
!regdom_changes(pending_request->alpha2))
return -EALREADY;
return REG_INTERSECT;
- case REGDOM_SET_BY_USER:
- if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
+ case NL80211_REGDOM_SET_BY_USER:
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
return REG_INTERSECT;
/*
* If the user knows better the user should set the regdom
* to their country before the IE is picked up
*/
- if (last_request->initiator == REGDOM_SET_BY_USER &&
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_USER &&
last_request->intersect)
return -EOPNOTSUPP;
/*
* Process user requests only after previous user/driver/core
* requests have been processed
*/
- if (last_request->initiator == REGDOM_SET_BY_CORE ||
- last_request->initiator == REGDOM_SET_BY_DRIVER ||
- last_request->initiator == REGDOM_SET_BY_USER) {
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE ||
+ last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
+ last_request->initiator == NL80211_REGDOM_SET_BY_USER) {
if (regdom_changes(last_request->alpha2))
return -EAGAIN;
}
@@ -1350,7 +1365,8 @@ static int __regulatory_hint(struct wiphy *wiphy,
r = ignore_request(wiphy, pending_request);
if (r == REG_INTERSECT) {
- if (pending_request->initiator == REGDOM_SET_BY_DRIVER) {
+ if (pending_request->initiator ==
+ NL80211_REGDOM_SET_BY_DRIVER) {
r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain);
if (r) {
kfree(pending_request);
@@ -1365,7 +1381,8 @@ static int __regulatory_hint(struct wiphy *wiphy,
* wiphy
*/
if (r == -EALREADY &&
- pending_request->initiator == REGDOM_SET_BY_DRIVER) {
+ pending_request->initiator ==
+ NL80211_REGDOM_SET_BY_DRIVER) {
r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain);
if (r) {
kfree(pending_request);
@@ -1387,8 +1404,16 @@ new_request:
pending_request = NULL;
/* When r == REG_INTERSECT we do need to call CRDA */
- if (r < 0)
+ if (r < 0) {
+ /*
+ * Since CRDA will not be called in this case as we already
+ * have applied the requested regulatory domain before we just
+ * inform userspace we have processed the request
+ */
+ if (r == -EALREADY)
+ nl80211_send_reg_change_event(last_request);
return r;
+ }
/*
* Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled
@@ -1416,7 +1441,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
if (wiphy_idx_valid(reg_request->wiphy_idx))
wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
- if (reg_request->initiator == REGDOM_SET_BY_DRIVER &&
+ if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
!wiphy) {
kfree(reg_request);
goto out;
@@ -1430,7 +1455,7 @@ out:
mutex_unlock(&cfg80211_mutex);
}
-/* Processes regulatory hints, this is all the REGDOM_SET_BY_* */
+/* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */
static void reg_process_pending_hints(void)
{
struct regulatory_request *reg_request;
@@ -1514,7 +1539,7 @@ static int regulatory_hint_core(const char *alpha2)
request->alpha2[0] = alpha2[0];
request->alpha2[1] = alpha2[1];
- request->initiator = REGDOM_SET_BY_CORE;
+ request->initiator = NL80211_REGDOM_SET_BY_CORE;
queue_regulatory_request(request);
@@ -1535,7 +1560,7 @@ int regulatory_hint_user(const char *alpha2)
request->wiphy_idx = WIPHY_IDX_STALE;
request->alpha2[0] = alpha2[0];
request->alpha2[1] = alpha2[1];
- request->initiator = REGDOM_SET_BY_USER,
+ request->initiator = NL80211_REGDOM_SET_BY_USER,
queue_regulatory_request(request);
@@ -1561,7 +1586,7 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
request->alpha2[0] = alpha2[0];
request->alpha2[1] = alpha2[1];
- request->initiator = REGDOM_SET_BY_DRIVER;
+ request->initiator = NL80211_REGDOM_SET_BY_DRIVER;
queue_regulatory_request(request);
@@ -1710,7 +1735,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
request->wiphy_idx = get_wiphy_idx(wiphy);
request->alpha2[0] = rd->alpha2[0];
request->alpha2[1] = rd->alpha2[1];
- request->initiator = REGDOM_SET_BY_COUNTRY_IE;
+ request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
request->country_ie_checksum = checksum;
request->country_ie_env = env;
@@ -1818,7 +1843,8 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
if (is_intersected_alpha2(rd->alpha2)) {
- if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
+ if (last_request->initiator ==
+ NL80211_REGDOM_SET_BY_COUNTRY_IE) {
struct cfg80211_registered_device *drv;
drv = cfg80211_drv_by_wiphy_idx(
last_request->wiphy_idx);
@@ -1910,7 +1936,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
* rd is non static (it means CRDA was present and was used last)
* and the pending request came in from a country IE
*/
- if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) {
+ if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
/*
* If someone else asked us to change the rd lets only bother
* checking if the alpha2 changes if CRDA was already called
@@ -1942,7 +1968,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
if (!last_request->intersect) {
int r;
- if (last_request->initiator != REGDOM_SET_BY_DRIVER) {
+ if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
reset_regdomains();
cfg80211_regdomain = rd;
return 0;
@@ -1966,7 +1992,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
/* Intersection requires a bit more work */
- if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) {
+ if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
intersected_rd = regdom_intersect(rd, cfg80211_regdomain);
if (!intersected_rd)
@@ -1977,7 +2003,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
* However if a driver requested this specific regulatory
* domain we keep it for its private use
*/
- if (last_request->initiator == REGDOM_SET_BY_DRIVER)
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER)
request_wiphy->regd = rd;
else
kfree(rd);
@@ -2067,6 +2093,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
print_regdomain(cfg80211_regdomain);
+ nl80211_send_reg_change_event(last_request);
+
return r;
}