From de3584bd62d87b4c250129fbc46ca52c80330add Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 21 Nov 2011 10:44:00 +0100 Subject: cfg80211: fix regulatory NULL dereference By the time userspace returns with a response to the regulatory domain request, the wiphy causing the request might have gone away. If this is so, reject the update but mark the request as having been processed anyway. Cc: Luis R. Rodriguez Signed-off-by: Johannes Berg Cc: stable@vger.kernel.org Signed-off-by: John W. Linville --- net/wireless/reg.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net/wireless/reg.c') diff --git a/net/wireless/reg.c b/net/wireless/reg.c index bc1ec2c26fd0..186b7f2a27b6 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2035,6 +2035,10 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) } request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); + if (!request_wiphy) { + reg_set_request_processed(); + return -ENODEV; + } if (!last_request->intersect) { int r; -- cgit v1.2.3 From 8b60b07805d557542160d852874fa6a1b969184e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 11 Oct 2011 10:59:02 -0700 Subject: cfg80211: process regulatory DFS region for countries The wireless-regdb now has support for mapping a country to one DFS region. CRDA sends this to us now so process it so we can provide that hint to drivers. This will later be used by code for processing DFS in a way that meets the criteria for the DFS region the country belongs to. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/linux/nl80211.h | 21 +++++++++++++++++++++ include/net/regulatory.h | 1 + net/wireless/nl80211.c | 15 +++++++++++++++ net/wireless/reg.c | 37 +++++++++++++++++++++++++++++++++++++ net/wireless/reg.h | 1 + 5 files changed, 75 insertions(+) (limited to 'net/wireless/reg.c') diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index f9261c253735..6396819a7e41 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1170,6 +1170,10 @@ enum nl80211_commands { * probe-response frame. The DA field in the 802.11 header is zero-ed out, * to be filled by the FW. * + * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country + * abides to when initiating radiation on DFS channels. A country maps + * to one DFS region. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1408,6 +1412,8 @@ enum nl80211_attrs { NL80211_ATTR_PROBE_RESP, + NL80211_ATTR_DFS_REGION, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1916,6 +1922,21 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_IBSS = 1<<8, }; +/** + * enum nl80211_dfs_regions - regulatory DFS regions + * + * @NL80211_DFS_UNSET: Country has no DFS master region specified + * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC + * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI + * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec + */ +enum nl80211_dfs_regions { + NL80211_DFS_UNSET = 0, + NL80211_DFS_FCC = 1, + NL80211_DFS_ETSI = 2, + NL80211_DFS_JP = 3, +}; + /** * enum nl80211_survey_info - survey information * diff --git a/include/net/regulatory.h b/include/net/regulatory.h index eb7d3c2d4274..7399c93cb4bc 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -93,6 +93,7 @@ struct ieee80211_reg_rule { struct ieee80211_regdomain { u32 n_reg_rules; char alpha2[2]; + u8 dfs_region; struct ieee80211_reg_rule reg_rules[]; }; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6bc7c4b32fa5..50482e129263 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -199,6 +199,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG }, [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 }, }; /* policy for the key attributes */ @@ -3382,6 +3383,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, cfg80211_regdomain->alpha2); + if (cfg80211_regdomain->dfs_region) + NLA_PUT_U8(msg, NL80211_ATTR_DFS_REGION, + cfg80211_regdomain->dfs_region); nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES); if (!nl_reg_rules) @@ -3440,6 +3444,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) char *alpha2 = NULL; int rem_reg_rules = 0, r = 0; u32 num_rules = 0, rule_idx = 0, size_of_regd; + u8 dfs_region = 0; struct ieee80211_regdomain *rd = NULL; if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) @@ -3450,6 +3455,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); + if (info->attrs[NL80211_ATTR_DFS_REGION]) + dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]); + nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], rem_reg_rules) { num_rules++; @@ -3477,6 +3485,13 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) rd->alpha2[0] = alpha2[0]; rd->alpha2[1] = alpha2[1]; + /* + * Disable DFS master mode if the DFS region was + * not supported or known on this kernel. + */ + if (reg_supported_dfs_region(dfs_region)) + rd->dfs_region = dfs_region; + nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], rem_reg_rules) { nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2520a1b7e7db..69141ed1f6df 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1946,6 +1946,42 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) } } +bool reg_supported_dfs_region(u8 dfs_region) +{ + switch (dfs_region) { + case NL80211_DFS_UNSET: + case NL80211_DFS_FCC: + case NL80211_DFS_ETSI: + case NL80211_DFS_JP: + return true; + default: + REG_DBG_PRINT("Ignoring uknown DFS master region: %d\n", + dfs_region); + return false; + } +} + +static void print_dfs_region(u8 dfs_region) +{ + if (!dfs_region) + return; + + switch (dfs_region) { + case NL80211_DFS_FCC: + pr_info(" DFS Master region FCC"); + break; + case NL80211_DFS_ETSI: + pr_info(" DFS Master region ETSI"); + break; + case NL80211_DFS_JP: + pr_info(" DFS Master region JP"); + break; + default: + pr_info(" DFS Master region Uknown"); + break; + } +} + static void print_regdomain(const struct ieee80211_regdomain *rd) { @@ -1973,6 +2009,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) pr_info("Regulatory domain changed to country: %c%c\n", rd->alpha2[0], rd->alpha2[1]); } + print_dfs_region(rd->dfs_region); print_rd_rules(rd); } diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 4a56799d868d..786e414afd91 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -5,6 +5,7 @@ extern const struct ieee80211_regdomain *cfg80211_regdomain; bool is_world_regdom(const char *alpha2); bool reg_is_valid_request(const char *alpha2); +bool reg_supported_dfs_region(u8 dfs_region); int regulatory_hint_user(const char *alpha2); -- cgit v1.2.3 From b68e6b3b33b208c5690355fd9804ea65cc53d3a5 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 11 Oct 2011 10:59:03 -0700 Subject: cfg80211: pass DFS region to drivers through reg_notifier() This grants drivers access to the DFS region that a regulatory domain belongs to. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/net/regulatory.h | 5 +++++ net/wireless/reg.c | 2 ++ 2 files changed, 7 insertions(+) (limited to 'net/wireless/reg.c') diff --git a/include/net/regulatory.h b/include/net/regulatory.h index 7399c93cb4bc..a5f79933e211 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -48,6 +48,10 @@ enum environment_cap { * 99 - built by driver but a specific alpha2 cannot be determined * 98 - result of an intersection between two regulatory domains * 97 - regulatory domain has not yet been configured + * @dfs_region: If CRDA responded with a regulatory domain that requires + * DFS master operation on a known DFS region (NL80211_DFS_*), + * dfs_region represents that region. Drivers can use this and the + * @alpha2 to adjust their device's DFS parameters as required. * @intersect: indicates whether the wireless core should intersect * the requested regulatory domain with the presently set regulatory * domain. @@ -67,6 +71,7 @@ struct regulatory_request { int wiphy_idx; enum nl80211_reg_initiator initiator; char alpha2[2]; + u8 dfs_region; bool intersect; bool processed; enum environment_cap country_ie_env; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 69141ed1f6df..b66444d048d5 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1121,6 +1121,8 @@ static void wiphy_update_regulatory(struct wiphy *wiphy, if (ignore_reg_update(wiphy, initiator)) return; + last_request->dfs_region = cfg80211_regdomain->dfs_region; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (wiphy->bands[band]) handle_band(wiphy, band, initiator); -- cgit v1.2.3 From a042994dd377d86bff9446ee76151ceb6267c9ba Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 28 Nov 2011 16:47:15 -0500 Subject: cfg80211: fix race on init and driver registration There is a theoretical race that if hit will trigger a crash. The race is between when we issue the first regulatory hint, regulatory_hint_core(), gets processed by the workqueue and between when the first device gets registered to the wireless core. This is not easy to reproduce but it was easy to do so through the regulatory simulator I have been working on. This is a port of the fix I implemented there [1]. [1] https://github.com/mcgrof/regsim/commit/a246ccf81f059cb662eee288aa13100f631e4cc8 Cc: stable@vger.kernel.org Cc: Johannes Berg Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'net/wireless/reg.c') diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 186b7f2a27b6..0ec40715a67b 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -55,8 +55,17 @@ #define REG_DBG_PRINT(args...) #endif +static struct regulatory_request core_request_world = { + .initiator = NL80211_REGDOM_SET_BY_CORE, + .alpha2[0] = '0', + .alpha2[1] = '0', + .intersect = false, + .processed = true, + .country_ie_env = ENVIRON_ANY, +}; + /* Receipt of information from last regulatory request */ -static struct regulatory_request *last_request; +static struct regulatory_request *last_request = &core_request_world; /* To trigger userspace events */ static struct platform_device *reg_pdev; @@ -148,7 +157,7 @@ static char user_alpha2[2]; module_param(ieee80211_regdom, charp, 0444); MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); -static void reset_regdomains(void) +static void reset_regdomains(bool full_reset) { /* avoid freeing static information or freeing something twice */ if (cfg80211_regdomain == cfg80211_world_regdom) @@ -163,6 +172,13 @@ static void reset_regdomains(void) cfg80211_world_regdom = &world_regdom; cfg80211_regdomain = NULL; + + if (!full_reset) + return; + + if (last_request != &core_request_world) + kfree(last_request); + last_request = &core_request_world; } /* @@ -173,7 +189,7 @@ static void update_world_regdomain(const struct ieee80211_regdomain *rd) { BUG_ON(!last_request); - reset_regdomains(); + reset_regdomains(false); cfg80211_world_regdom = rd; cfg80211_regdomain = rd; @@ -1405,7 +1421,8 @@ static int __regulatory_hint(struct wiphy *wiphy, } new_request: - kfree(last_request); + if (last_request != &core_request_world) + kfree(last_request); last_request = pending_request; last_request->intersect = intersect; @@ -1575,9 +1592,6 @@ static int regulatory_hint_core(const char *alpha2) { struct regulatory_request *request; - kfree(last_request); - last_request = NULL; - request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); if (!request) @@ -1775,7 +1789,7 @@ static void restore_regulatory_settings(bool reset_user) mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); - reset_regdomains(); + reset_regdomains(true); restore_alpha2(alpha2, reset_user); /* @@ -2044,7 +2058,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) int r; if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = rd; return 0; } @@ -2065,7 +2079,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) if (r) return r; - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = rd; return 0; } @@ -2090,7 +2104,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) rd = NULL; - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = intersected_rd; return 0; @@ -2110,7 +2124,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) kfree(rd); rd = NULL; - reset_regdomains(); + reset_regdomains(false); cfg80211_regdomain = intersected_rd; return 0; @@ -2263,11 +2277,8 @@ void /* __init_or_exit */ regulatory_exit(void) mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); - reset_regdomains(); - - kfree(last_request); + reset_regdomains(true); - last_request = NULL; dev_set_uevent_suppress(®_pdev->dev, true); platform_device_unregister(reg_pdev); -- cgit v1.2.3 From 0bac71af6e66dc798bf07d0c0dd14ee5503362f9 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 28 Nov 2011 16:47:16 -0500 Subject: cfg80211: amend regulatory NULL dereference fix Johannes' patch for "cfg80211: fix regulatory NULL dereference" broke user regulaotry hints and it did not address the fact that last_request was left populated even if the previous regulatory hint was stale due to the wiphy disappearing. Fix user reguluatory hints by only bailing out if for those regulatory hints where a request_wiphy is expected. The stale last_request considerations are addressed through the previous fixes on last_request where we reset the last_request to a static world regdom request upon reset_regdomains(). In this case though we further enhance the effect by simply restoring reguluatory settings completely. Cc: stable@vger.kernel.org Cc: Johannes Berg Signed-off-by: Luis R. Rodriguez Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/reg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net/wireless/reg.c') diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 0ec40715a67b..074c1122ce42 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2049,8 +2049,10 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) } request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); - if (!request_wiphy) { - reg_set_request_processed(); + if (!request_wiphy && + (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || + last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) { + schedule_delayed_work(®_timeout, 0); return -ENODEV; } -- cgit v1.2.3 From 4a38994f1c43351b4aaca01ae93bd574f5b5075e Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 8 Dec 2011 23:59:26 +0530 Subject: cfg80211: notify core hints that helps to restore regd settings Regulatory updates set by CORE are ignored for custom regulatory cards. Let us notify the changes to the driver, as some drivers uses core hint to restore its orig_* reg domain setting. Cc: Paul Stewart Signed-off-by: Rajkumar Manoharan Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'net/wireless/reg.c') diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 70b171a52aea..2f5b0505c95d 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1163,9 +1163,21 @@ void regulatory_update(struct wiphy *wiphy, static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) { struct cfg80211_registered_device *rdev; + struct wiphy *wiphy; - list_for_each_entry(rdev, &cfg80211_rdev_list, list) - wiphy_update_regulatory(&rdev->wiphy, initiator); + list_for_each_entry(rdev, &cfg80211_rdev_list, list) { + wiphy = &rdev->wiphy; + wiphy_update_regulatory(wiphy, initiator); + /* + * Regulatory updates set by CORE are ignored for custom + * regulatory cards. Let us notify the changes to the driver, + * as some drivers used this to restore its orig_* reg domain. + */ + if (initiator == NL80211_REGDOM_SET_BY_CORE && + wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && + wiphy->reg_notifier) + wiphy->reg_notifier(wiphy, last_request); + } } static void handle_channel_custom(struct wiphy *wiphy, -- cgit v1.2.3 From 061acaae76dfb760f4f3fddf0cde43915b7d673c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 7 Dec 2011 21:50:07 +0530 Subject: cfg80211: allow following country IE power for custom regdom cards By definition WIPHY_FLAG_STRICT_REGULATORY was intended to allow the wiphy to adjust itself to the country IE power information if the card had no regulatory data but we had no way to tell cfg80211 that if the card also had its own custom regulatory domain (these are typically custom world regulatory domains) that we want to follow the country IE's noted values for power for each channel. We add support for this and document it. This is not a critical fix but a performance optimization for cards with custom regulatory domains that associate to an AP with sends out country IEs with a higher EIRP than the one on the custom regulatory domain. In practice the only driver affected right now are the Atheros drivers as they are the only drivers using both WIPHY_FLAG_STRICT_REGULATORY and WIPHY_FLAG_CUSTOM_REGULATORY -- used on cards that have an Atheros world regulatory domain. Cards that have been programmed to follow a country specifically will not follow the country IE power. So although not a stable fix distributions should consider cherry picking this. Cc: compat@orbit-lab.org Cc: Paul Stewart Cc: Rajkumar Manoharan Cc: Senthilkumar Balasubramanian Reported-by: Rajkumar Manoharan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/net/cfg80211.h | 4 +++- net/wireless/reg.c | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'net/wireless/reg.c') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5eda5933ae01..9f85fca0b676 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1699,7 +1699,9 @@ struct cfg80211_ops { * regulatory domain no user regulatory domain can enable these channels * at a later time. This can be used for devices which do not have * calibration information guaranteed for frequencies or settings - * outside of its regulatory domain. + * outside of its regulatory domain. If used in combination with + * WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings + * will be followed. * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure * that passive scan flags and beaconing flags may not be lifted by * cfg80211 due to regulatory beacon hints. For more information on beacon diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2f5b0505c95d..481caafc6ba5 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -873,10 +873,22 @@ static void handle_channel(struct wiphy *wiphy, chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); chan->max_antenna_gain = min(chan->orig_mag, (int) MBI_TO_DBI(power_rule->max_antenna_gain)); - if (chan->orig_mpwr) - chan->max_power = min(chan->orig_mpwr, - (int) MBM_TO_DBM(power_rule->max_eirp)); - else + if (chan->orig_mpwr) { + /* + * Devices that have their own custom regulatory domain + * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the + * passed country IE power settings. + */ + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && + wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && + wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { + chan->max_power = + MBM_TO_DBM(power_rule->max_eirp); + } else { + chan->max_power = min(chan->orig_mpwr, + (int) MBM_TO_DBM(power_rule->max_eirp)); + } + } else chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); } -- cgit v1.2.3 From 5ce543d148bf7590294e76bc30f4c4d6777fe094 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 7 Dec 2011 21:50:08 +0530 Subject: cfg80211: Restore orig channel values upon disconnect When we restore regulatory settings the world regulatory domain is properly reset on cfg80211 (or user prefered regulatory domain) but we were never setting back channel values for drivers that use WIPHY_FLAG_CUSTOM_REGULATORY. Set these values up again by using the orig_ channel parameters. This fixes restoring custom regulatory settings upon disconnect events. Cc: compat@orbit-lab.org Cc: Paul Stewart Cc: Rajkumar Manoharan Cc: Senthilkumar Balasubramanian Signed-off-by: Rajkumar Manoharan Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'net/wireless/reg.c') diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 481caafc6ba5..c45c8b772ddd 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1792,6 +1792,26 @@ static void restore_alpha2(char *alpha2, bool reset_user) REG_DBG_PRINT("Restoring regulatory settings\n"); } +static void restore_custom_reg_settings(struct wiphy *wiphy) +{ + struct ieee80211_supported_band *sband; + enum ieee80211_band band; + struct ieee80211_channel *chan; + int i; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + sband = wiphy->bands[band]; + if (!sband) + continue; + for (i = 0; i < sband->n_channels; i++) { + chan = &sband->channels[i]; + chan->flags = chan->orig_flags; + chan->max_antenna_gain = chan->orig_mag; + chan->max_power = chan->orig_mpwr; + } + } +} + /* * Restoring regulatory settings involves ingoring any * possibly stale country IE information and user regulatory @@ -1813,6 +1833,7 @@ static void restore_regulatory_settings(bool reset_user) struct reg_beacon *reg_beacon, *btmp; struct regulatory_request *reg_request, *tmp; LIST_HEAD(tmp_reg_req_list); + struct cfg80211_registered_device *rdev; mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); @@ -1861,6 +1882,11 @@ static void restore_regulatory_settings(bool reset_user) /* First restore to the basic regulatory settings */ cfg80211_regdomain = cfg80211_world_regdom; + list_for_each_entry(rdev, &cfg80211_rdev_list, list) { + if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY) + restore_custom_reg_settings(&rdev->wiphy); + } + mutex_unlock(®_mutex); mutex_unlock(&cfg80211_mutex); -- cgit v1.2.3 From cee0bec58a922976a5f4d70081a3b2fd73e108e9 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 19 Dec 2011 12:32:21 -0800 Subject: wireless: Protect regdomain change by mutex Signed-off-by: Dmitry Shmidt Signed-off-by: John W. Linville --- net/wireless/reg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/wireless/reg.c') diff --git a/net/wireless/reg.c b/net/wireless/reg.c index c45c8b772ddd..58d393766035 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1830,6 +1830,7 @@ static void restore_custom_reg_settings(struct wiphy *wiphy) static void restore_regulatory_settings(bool reset_user) { char alpha2[2]; + char world_alpha2[2]; struct reg_beacon *reg_beacon, *btmp; struct regulatory_request *reg_request, *tmp; LIST_HEAD(tmp_reg_req_list); @@ -1881,6 +1882,8 @@ static void restore_regulatory_settings(bool reset_user) /* First restore to the basic regulatory settings */ cfg80211_regdomain = cfg80211_world_regdom; + world_alpha2[0] = cfg80211_regdomain->alpha2[0]; + world_alpha2[1] = cfg80211_regdomain->alpha2[1]; list_for_each_entry(rdev, &cfg80211_rdev_list, list) { if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY) @@ -1890,7 +1893,7 @@ static void restore_regulatory_settings(bool reset_user) mutex_unlock(®_mutex); mutex_unlock(&cfg80211_mutex); - regulatory_hint_core(cfg80211_regdomain->alpha2); + regulatory_hint_core(world_alpha2); /* * This restores the ieee80211_regdom module parameter -- cgit v1.2.3 From 8848bef0382af53a7c9568bbc6757db97c53a0e3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 20 Dec 2011 12:23:36 -0800 Subject: cfg80211: replace reg.c Nokia commit c4c32294 Nokia hasn't gotten back to me in over 1 month for a relicense change request. There are only a few changes that they contributed, so just reverting their changes but replacing with another set. This change replaces this commit: commit c4c322941ce0d7e2b7b8794ad70683123d9cb26a Author: Yuri Ershov Date: Tue Jun 29 15:08:08 2010 +0400 cfg80211: Update of regulatory request initiator handling In some cases there could be possible dereferencing freed pointer. The update is intended to avoid this issue. Signed-off-by: Yuri Ershov Signed-off-by: John W. Linville Cc: Petri Karhula Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'net/wireless/reg.c') diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 58d393766035..728a8fdf04b3 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1480,18 +1480,18 @@ new_request: } /* This processes *all* regulatory hints */ -static void reg_process_hint(struct regulatory_request *reg_request) +static void reg_process_hint(struct regulatory_request *reg_request, + enum nl80211_reg_initiator reg_initiator) { int r = 0; struct wiphy *wiphy = NULL; - enum nl80211_reg_initiator initiator = reg_request->initiator; BUG_ON(!reg_request->alpha2); if (wiphy_idx_valid(reg_request->wiphy_idx)) wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); - if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && + if (reg_initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) { kfree(reg_request); return; @@ -1501,7 +1501,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) /* This is required so that the orig_* parameters are saved */ if (r == -EALREADY && wiphy && wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { - wiphy_update_regulatory(wiphy, initiator); + wiphy_update_regulatory(wiphy, reg_initiator); return; } @@ -1510,7 +1510,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) * source of bogus requests. */ if (r != -EALREADY && - reg_request->initiator == NL80211_REGDOM_SET_BY_USER) + reg_initiator == NL80211_REGDOM_SET_BY_USER) schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); } @@ -1547,7 +1547,7 @@ static void reg_process_pending_hints(void) spin_unlock(®_requests_lock); - reg_process_hint(reg_request); + reg_process_hint(reg_request, reg_request->initiator); out: mutex_unlock(®_mutex); -- cgit v1.2.3 From 6653325a556ef5a838ed7d3a0a6552f0efc72739 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 20 Dec 2011 12:23:37 -0800 Subject: cfg80211: replace reg.c Nokia commit 269ac5 Nokia hasn't gotten back to me in over 1 month for a relicense change request. There are only a few changes that they contributed, so just reverting their changes but replacing with another set. This change replaces this commit: commit 269ac5fd2d75b118d76a2291e28796527db2f3f8 Author: Kalle Valo Date: Tue Dec 1 10:47:15 2009 +0200 cfg80211: indent regulatory messages with spaces The regulatory messages in syslog look weird: kernel: cfg80211: Regulatory domain: US kernel: ^I(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp) kernel: ^I(2402000 KHz - 2472000 KHz @ 40000 KHz), (600 mBi, 2700 mBm) kernel: ^I(5170000 KHz - 5190000 KHz @ 40000 KHz), (600 mBi, 2300 mBm) kernel: ^I(5190000 KHz - 5210000 KHz @ 40000 KHz), (600 mBi, 2300 mBm) kernel: ^I(5210000 KHz - 5230000 KHz @ 40000 KHz), (600 mBi, 2300 mBm) kernel: ^I(5230000 KHz - 5330000 KHz @ 40000 KHz), (600 mBi, 2300 mBm) kernel: ^I(5735000 KHz - 5835000 KHz @ 40000 KHz), (600 mBi, 3000 mBm) Indent them with four spaces instead of the tab character to get prettier output. Signed-off-by: Kalle Valo Acked: Luis R. Rodriguez Signed-off-by: John W. Linville Cc: Petri Karhula Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/wireless/reg.c') diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 728a8fdf04b3..ef47b418c862 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1990,7 +1990,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) const struct ieee80211_freq_range *freq_range = NULL; const struct ieee80211_power_rule *power_rule = NULL; - pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n"); + pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n"); for (i = 0; i < rd->n_reg_rules; i++) { reg_rule = &rd->reg_rules[i]; @@ -2002,14 +2002,14 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) * in certain regions */ if (power_rule->max_antenna_gain) - pr_info(" (%d KHz - %d KHz @ %d KHz), (%d mBi, %d mBm)\n", + pr_info(" (%d KHz - %d KHz @ %d KHz), (%d mBi, %d mBm)\n", freq_range->start_freq_khz, freq_range->end_freq_khz, freq_range->max_bandwidth_khz, power_rule->max_antenna_gain, power_rule->max_eirp); else - pr_info(" (%d KHz - %d KHz @ %d KHz), (N/A, %d mBm)\n", + pr_info(" (%d KHz - %d KHz @ %d KHz), (N/A, %d mBm)\n", freq_range->start_freq_khz, freq_range->end_freq_khz, freq_range->max_bandwidth_khz, -- cgit v1.2.3 From 3b77d5ec0c86b8a9594217ff9024b00e4d1c5795 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 20 Dec 2011 12:23:38 -0800 Subject: cfg80211: relicense reg.c reg.h and genregdb.awk to ISC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following the tradition we have had with ath5k, ath9k, CRDA, wireless-regdb I'd like to license this code under the permissive ISC license for the code sharing purposes with other OSes, it'd sure be nice to help the landscape in this area. Although I am %82.89 owner of the regulatory code I have asked every contributor to the regulatory code and have receieved positive Acked-bys from everyone except two deceased entities: o Frans Pop RIP 2010 [0] - Frans Pop - Frans Pop o Nokia RIP February, 11, 2011 [1], [2] - ext-yuri.ershov@nokia.com - kalle.valo@nokia.com Frans Pop's contribution was a simple patch 55f98938, titled, "wireless: remove trailing space in messages" which just add a \n to some printk lines. I'm going to treat these additions as uncopyrightable. As for the contributions made by employees on behalf of Nokia my contact point was Petri Karhula but after one month he noted he had not been able to get traction from the legal department on this request, as such it I proceeded by replacing their contributions in previous patches. The end goal is to help a clean rewrite that starts in userspace that is shared under ISC license which currently is taking place with the regulatory simulator [3]. [0] http://lists.debian.org/debian-devel/2011/12/msg00263.html [1] http://press.nokia.com/2011/02/11/nokia-outlines-new-strategy-introduces-new-leadership-operational-structure/ [2] http://NokiaPlanB.com [3] git://github.com/mcgrof/regsim.git Acked-by: Thadeu Lima de Souza Cascardo Acked-by: Dan Carpenter Acked-by: Mihai Moldovan Acked-by: Uwe Kleine-König Acked-by: Sven Neumann Acked-by: Johannes Berg Acked-by: Tomas Winkler Acked-by: Tony Vroon Acked-by: Pavel Roskin Acked-by: Bob Copeland Acked-by: Lucas De Marchi Acked-by: Pat Erley Acked-by: Tejun Heo Acked-by: John W. Linville Acked-by: Chris Wright Acked-by: Joe Perches Acked-by: Paul Gortmaker Acked-by: John Gordon Acked-by: Simon Barber Acked-by: Rajkumar Manoharan Acked-by: Jiri Benc Acked-by: Bruno Randolf Acked-by: Scott James Remnant Acked-by: Roel Kluin Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/genregdb.awk | 13 ++++++++++--- net/wireless/reg.c | 17 +++++++++++++---- net/wireless/reg.h | 15 +++++++++++++++ net/wireless/regdb.h | 16 ++++++++++++++++ 4 files changed, 54 insertions(+), 7 deletions(-) (limited to 'net/wireless/reg.c') diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index 53c143f5e770..9392f8cbb901 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk @@ -7,10 +7,17 @@ # # Copyright 2009 John W. Linville # -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. # +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. BEGIN { active = 0 diff --git a/net/wireless/reg.c b/net/wireless/reg.c index ef47b418c862..f65feaad155f 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2,13 +2,22 @@ * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. * Copyright 2007 Johannes Berg - * Copyright 2008 Luis R. Rodriguez + * Copyright 2008-2011 Luis R. Rodriguez * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + /** * DOC: Wireless regulatory infrastructure * diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 786e414afd91..e2aaaf525a22 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -1,5 +1,20 @@ #ifndef __NET_WIRELESS_REG_H #define __NET_WIRELESS_REG_H +/* + * Copyright 2008-2011 Luis R. Rodriguez + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ extern const struct ieee80211_regdomain *cfg80211_regdomain; diff --git a/net/wireless/regdb.h b/net/wireless/regdb.h index 818222c92513..3279cfcefb0c 100644 --- a/net/wireless/regdb.h +++ b/net/wireless/regdb.h @@ -1,6 +1,22 @@ #ifndef __REGDB_H__ #define __REGDB_H__ +/* + * Copyright 2009 John W. Linville + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + extern const struct ieee80211_regdomain *reg_regdb[]; extern int reg_regdb_size; -- cgit v1.2.3