diff options
Diffstat (limited to 'only-use-alpha2-regulatory-information-from-country-IE.patch')
-rw-r--r-- | only-use-alpha2-regulatory-information-from-country-IE.patch | 788 |
1 files changed, 788 insertions, 0 deletions
diff --git a/only-use-alpha2-regulatory-information-from-country-IE.patch b/only-use-alpha2-regulatory-information-from-country-IE.patch new file mode 100644 index 000000000..5e7459cf8 --- /dev/null +++ b/only-use-alpha2-regulatory-information-from-country-IE.patch @@ -0,0 +1,788 @@ +From linville@tuxdriver.com Thu Jul 15 15:40:22 2010 +From: "John W. Linville" <linville@tuxdriver.com> +Subject: [RFC] wireless: only use alpha2 regulatory information from country IE +Date: Thu, 15 Jul 2010 15:06:47 -0400 + +The meaning and/or usage of the country IE is somewhat poorly defined. +In practice, this means that regulatory rulesets in a country IE are +often incomplete and might be untrustworthy. This removes the code +associated with interpreting those rulesets while preserving respect +for country "alpha2" codes also contained in the country IE. + +Signed-off-by: John W. Linville <linville@tuxdriver.com> +--- +This patch is compile-tested only! Please feel free to suggest that +I have left something out or missed some nuance of our regulatory +enforcement code... + + include/net/regulatory.h | 1 - + net/wireless/reg.c | 625 +--------------------------------------------- + 2 files changed, 12 insertions(+), 614 deletions(-) + +diff --git a/include/net/regulatory.h b/include/net/regulatory.h +index f873ee3..9e103a4 100644 +--- a/include/net/regulatory.h ++++ b/include/net/regulatory.h +@@ -54,7 +54,6 @@ struct regulatory_request { + enum nl80211_reg_initiator initiator; + char alpha2[2]; + bool intersect; +- u32 country_ie_checksum; + enum environment_cap country_ie_env; + struct list_head list; + }; +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 1ac2bdd..678d0bd 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -67,17 +67,9 @@ static struct platform_device *reg_pdev; + const struct ieee80211_regdomain *cfg80211_regdomain; + + /* +- * We use this as a place for the rd structure built from the +- * last parsed country IE to rest until CRDA gets back to us with +- * what it thinks should apply for the same country +- */ +-static const struct ieee80211_regdomain *country_ie_regdomain; +- +-/* + * Protects static reg.c components: + * - cfg80211_world_regdom + * - cfg80211_regdom +- * - country_ie_regdomain + * - last_request + */ + static DEFINE_MUTEX(reg_mutex); +@@ -275,25 +267,6 @@ static bool is_user_regdom_saved(void) + return true; + } + +-/** +- * country_ie_integrity_changes - tells us if the country IE has changed +- * @checksum: checksum of country IE of fields we are interested in +- * +- * If the country IE has not changed you can ignore it safely. This is +- * useful to determine if two devices are seeing two different country IEs +- * even on the same alpha2. Note that this will return false if no IE has +- * been set on the wireless core yet. +- */ +-static bool country_ie_integrity_changes(u32 checksum) +-{ +- /* If no IE has been set then the checksum doesn't change */ +- if (unlikely(!last_request->country_ie_checksum)) +- return false; +- if (unlikely(last_request->country_ie_checksum != checksum)) +- return true; +- return false; +-} +- + static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, + const struct ieee80211_regdomain *src_regd) + { +@@ -506,471 +479,6 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, + } + + /* +- * This is a work around for sanity checking ieee80211_channel_to_frequency()'s +- * work. ieee80211_channel_to_frequency() can for example currently provide a +- * 2 GHz channel when in fact a 5 GHz channel was desired. An example would be +- * an AP providing channel 8 on a country IE triplet when it sent this on the +- * 5 GHz band, that channel is designed to be channel 8 on 5 GHz, not a 2 GHz +- * channel. +- * +- * This can be removed once ieee80211_channel_to_frequency() takes in a band. +- */ +-static bool chan_in_band(int chan, enum ieee80211_band band) +-{ +- int center_freq = ieee80211_channel_to_frequency(chan); +- +- switch (band) { +- case IEEE80211_BAND_2GHZ: +- if (center_freq <= 2484) +- return true; +- return false; +- case IEEE80211_BAND_5GHZ: +- if (center_freq >= 5005) +- return true; +- return false; +- default: +- return false; +- } +-} +- +-/* +- * Some APs may send a country IE triplet for each channel they +- * support and while this is completely overkill and silly we still +- * need to support it. We avoid making a single rule for each channel +- * though and to help us with this we use this helper to find the +- * actual subband end channel. These type of country IE triplet +- * scenerios are handled then, all yielding two regulaotry rules from +- * parsing a country IE: +- * +- * [1] +- * [2] +- * [36] +- * [40] +- * +- * [1] +- * [2-4] +- * [5-12] +- * [36] +- * [40-44] +- * +- * [1-4] +- * [5-7] +- * [36-44] +- * [48-64] +- * +- * [36-36] +- * [40-40] +- * [44-44] +- * [48-48] +- * [52-52] +- * [56-56] +- * [60-60] +- * [64-64] +- * [100-100] +- * [104-104] +- * [108-108] +- * [112-112] +- * [116-116] +- * [120-120] +- * [124-124] +- * [128-128] +- * [132-132] +- * [136-136] +- * [140-140] +- * +- * Returns 0 if the IE has been found to be invalid in the middle +- * somewhere. +- */ +-static int max_subband_chan(enum ieee80211_band band, +- int orig_cur_chan, +- int orig_end_channel, +- s8 orig_max_power, +- u8 **country_ie, +- u8 *country_ie_len) +-{ +- u8 *triplets_start = *country_ie; +- u8 len_at_triplet = *country_ie_len; +- int end_subband_chan = orig_end_channel; +- +- /* +- * We'll deal with padding for the caller unless +- * its not immediate and we don't process any channels +- */ +- if (*country_ie_len == 1) { +- *country_ie += 1; +- *country_ie_len -= 1; +- return orig_end_channel; +- } +- +- /* Move to the next triplet and then start search */ +- *country_ie += 3; +- *country_ie_len -= 3; +- +- if (!chan_in_band(orig_cur_chan, band)) +- return 0; +- +- while (*country_ie_len >= 3) { +- int end_channel = 0; +- struct ieee80211_country_ie_triplet *triplet = +- (struct ieee80211_country_ie_triplet *) *country_ie; +- int cur_channel = 0, next_expected_chan; +- +- /* means last triplet is completely unrelated to this one */ +- if (triplet->ext.reg_extension_id >= +- IEEE80211_COUNTRY_EXTENSION_ID) { +- *country_ie -= 3; +- *country_ie_len += 3; +- break; +- } +- +- if (triplet->chans.first_channel == 0) { +- *country_ie += 1; +- *country_ie_len -= 1; +- if (*country_ie_len != 0) +- return 0; +- break; +- } +- +- if (triplet->chans.num_channels == 0) +- return 0; +- +- /* Monitonically increasing channel order */ +- if (triplet->chans.first_channel <= end_subband_chan) +- return 0; +- +- if (!chan_in_band(triplet->chans.first_channel, band)) +- return 0; +- +- /* 2 GHz */ +- if (triplet->chans.first_channel <= 14) { +- end_channel = triplet->chans.first_channel + +- triplet->chans.num_channels - 1; +- } +- else { +- end_channel = triplet->chans.first_channel + +- (4 * (triplet->chans.num_channels - 1)); +- } +- +- if (!chan_in_band(end_channel, band)) +- return 0; +- +- if (orig_max_power != triplet->chans.max_power) { +- *country_ie -= 3; +- *country_ie_len += 3; +- break; +- } +- +- cur_channel = triplet->chans.first_channel; +- +- /* The key is finding the right next expected channel */ +- if (band == IEEE80211_BAND_2GHZ) +- next_expected_chan = end_subband_chan + 1; +- else +- next_expected_chan = end_subband_chan + 4; +- +- if (cur_channel != next_expected_chan) { +- *country_ie -= 3; +- *country_ie_len += 3; +- break; +- } +- +- end_subband_chan = end_channel; +- +- /* Move to the next one */ +- *country_ie += 3; +- *country_ie_len -= 3; +- +- /* +- * Padding needs to be dealt with if we processed +- * some channels. +- */ +- if (*country_ie_len == 1) { +- *country_ie += 1; +- *country_ie_len -= 1; +- break; +- } +- +- /* If seen, the IE is invalid */ +- if (*country_ie_len == 2) +- return 0; +- } +- +- if (end_subband_chan == orig_end_channel) { +- *country_ie = triplets_start; +- *country_ie_len = len_at_triplet; +- return orig_end_channel; +- } +- +- return end_subband_chan; +-} +- +-/* +- * Converts a country IE to a regulatory domain. A regulatory domain +- * structure has a lot of information which the IE doesn't yet have, +- * so for the other values we use upper max values as we will intersect +- * with our userspace regulatory agent to get lower bounds. +- */ +-static struct ieee80211_regdomain *country_ie_2_rd( +- enum ieee80211_band band, +- u8 *country_ie, +- u8 country_ie_len, +- u32 *checksum) +-{ +- struct ieee80211_regdomain *rd = NULL; +- unsigned int i = 0; +- char alpha2[2]; +- u32 flags = 0; +- u32 num_rules = 0, size_of_regd = 0; +- u8 *triplets_start = NULL; +- u8 len_at_triplet = 0; +- /* the last channel we have registered in a subband (triplet) */ +- int last_sub_max_channel = 0; +- +- *checksum = 0xDEADBEEF; +- +- /* Country IE requirements */ +- BUG_ON(country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN || +- country_ie_len & 0x01); +- +- alpha2[0] = country_ie[0]; +- alpha2[1] = country_ie[1]; +- +- /* +- * Third octet can be: +- * 'I' - Indoor +- * 'O' - Outdoor +- * +- * anything else we assume is no restrictions +- */ +- if (country_ie[2] == 'I') +- flags = NL80211_RRF_NO_OUTDOOR; +- else if (country_ie[2] == 'O') +- flags = NL80211_RRF_NO_INDOOR; +- +- country_ie += 3; +- country_ie_len -= 3; +- +- triplets_start = country_ie; +- len_at_triplet = country_ie_len; +- +- *checksum ^= ((flags ^ alpha2[0] ^ alpha2[1]) << 8); +- +- /* +- * We need to build a reg rule for each triplet, but first we must +- * calculate the number of reg rules we will need. We will need one +- * for each channel subband +- */ +- while (country_ie_len >= 3) { +- int end_channel = 0; +- struct ieee80211_country_ie_triplet *triplet = +- (struct ieee80211_country_ie_triplet *) country_ie; +- int cur_sub_max_channel = 0, cur_channel = 0; +- +- if (triplet->ext.reg_extension_id >= +- IEEE80211_COUNTRY_EXTENSION_ID) { +- country_ie += 3; +- country_ie_len -= 3; +- continue; +- } +- +- /* +- * APs can add padding to make length divisible +- * by two, required by the spec. +- */ +- if (triplet->chans.first_channel == 0) { +- country_ie++; +- country_ie_len--; +- /* This is expected to be at the very end only */ +- if (country_ie_len != 0) +- return NULL; +- break; +- } +- +- if (triplet->chans.num_channels == 0) +- return NULL; +- +- if (!chan_in_band(triplet->chans.first_channel, band)) +- return NULL; +- +- /* 2 GHz */ +- if (band == IEEE80211_BAND_2GHZ) +- end_channel = triplet->chans.first_channel + +- triplet->chans.num_channels - 1; +- else +- /* +- * 5 GHz -- For example in country IEs if the first +- * channel given is 36 and the number of channels is 4 +- * then the individual channel numbers defined for the +- * 5 GHz PHY by these parameters are: 36, 40, 44, and 48 +- * and not 36, 37, 38, 39. +- * +- * See: http://tinyurl.com/11d-clarification +- */ +- end_channel = triplet->chans.first_channel + +- (4 * (triplet->chans.num_channels - 1)); +- +- cur_channel = triplet->chans.first_channel; +- +- /* +- * Enhancement for APs that send a triplet for every channel +- * or for whatever reason sends triplets with multiple channels +- * separated when in fact they should be together. +- */ +- end_channel = max_subband_chan(band, +- cur_channel, +- end_channel, +- triplet->chans.max_power, +- &country_ie, +- &country_ie_len); +- if (!end_channel) +- return NULL; +- +- if (!chan_in_band(end_channel, band)) +- return NULL; +- +- cur_sub_max_channel = end_channel; +- +- /* Basic sanity check */ +- if (cur_sub_max_channel < cur_channel) +- return NULL; +- +- /* +- * Do not allow overlapping channels. Also channels +- * passed in each subband must be monotonically +- * increasing +- */ +- if (last_sub_max_channel) { +- if (cur_channel <= last_sub_max_channel) +- return NULL; +- if (cur_sub_max_channel <= last_sub_max_channel) +- return NULL; +- } +- +- /* +- * When dot11RegulatoryClassesRequired is supported +- * we can throw ext triplets as part of this soup, +- * for now we don't care when those change as we +- * don't support them +- */ +- *checksum ^= ((cur_channel ^ cur_sub_max_channel) << 8) | +- ((cur_sub_max_channel ^ cur_sub_max_channel) << 16) | +- ((triplet->chans.max_power ^ cur_sub_max_channel) << 24); +- +- last_sub_max_channel = cur_sub_max_channel; +- +- num_rules++; +- +- if (country_ie_len >= 3) { +- country_ie += 3; +- country_ie_len -= 3; +- } +- +- /* +- * Note: this is not a IEEE requirement but +- * simply a memory requirement +- */ +- if (num_rules > NL80211_MAX_SUPP_REG_RULES) +- return NULL; +- } +- +- country_ie = triplets_start; +- country_ie_len = len_at_triplet; +- +- size_of_regd = sizeof(struct ieee80211_regdomain) + +- (num_rules * sizeof(struct ieee80211_reg_rule)); +- +- rd = kzalloc(size_of_regd, GFP_KERNEL); +- if (!rd) +- return NULL; +- +- rd->n_reg_rules = num_rules; +- rd->alpha2[0] = alpha2[0]; +- rd->alpha2[1] = alpha2[1]; +- +- /* This time around we fill in the rd */ +- while (country_ie_len >= 3) { +- int end_channel = 0; +- struct ieee80211_country_ie_triplet *triplet = +- (struct ieee80211_country_ie_triplet *) country_ie; +- struct ieee80211_reg_rule *reg_rule = NULL; +- struct ieee80211_freq_range *freq_range = NULL; +- struct ieee80211_power_rule *power_rule = NULL; +- +- /* +- * Must parse if dot11RegulatoryClassesRequired is true, +- * we don't support this yet +- */ +- if (triplet->ext.reg_extension_id >= +- IEEE80211_COUNTRY_EXTENSION_ID) { +- country_ie += 3; +- country_ie_len -= 3; +- continue; +- } +- +- if (triplet->chans.first_channel == 0) { +- country_ie++; +- country_ie_len--; +- break; +- } +- +- reg_rule = &rd->reg_rules[i]; +- freq_range = ®_rule->freq_range; +- power_rule = ®_rule->power_rule; +- +- reg_rule->flags = flags; +- +- /* 2 GHz */ +- if (band == IEEE80211_BAND_2GHZ) +- end_channel = triplet->chans.first_channel + +- triplet->chans.num_channels -1; +- else +- end_channel = triplet->chans.first_channel + +- (4 * (triplet->chans.num_channels - 1)); +- +- end_channel = max_subband_chan(band, +- triplet->chans.first_channel, +- end_channel, +- triplet->chans.max_power, +- &country_ie, +- &country_ie_len); +- +- /* +- * The +10 is since the regulatory domain expects +- * the actual band edge, not the center of freq for +- * its start and end freqs, assuming 20 MHz bandwidth on +- * the channels passed +- */ +- freq_range->start_freq_khz = +- MHZ_TO_KHZ(ieee80211_channel_to_frequency( +- triplet->chans.first_channel) - 10); +- freq_range->end_freq_khz = +- MHZ_TO_KHZ(ieee80211_channel_to_frequency( +- end_channel) + 10); +- +- /* +- * These are large arbitrary values we use to intersect later. +- * Increment this if we ever support >= 40 MHz channels +- * in IEEE 802.11 +- */ +- freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40); +- power_rule->max_antenna_gain = DBI_TO_MBI(100); +- power_rule->max_eirp = DBM_TO_MBM(triplet->chans.max_power); +- +- i++; +- +- if (country_ie_len >= 3) { +- country_ie += 3; +- country_ie_len -= 3; +- } +- +- BUG_ON(i > NL80211_MAX_SUPP_REG_RULES); +- } +- +- return rd; +-} +- +- +-/* + * Helper for regdom_intersect(), this does the real + * mathematical intersection fun + */ +@@ -1191,7 +699,6 @@ static int freq_reg_info_regd(struct wiphy *wiphy, + + return -EINVAL; + } +-EXPORT_SYMBOL(freq_reg_info); + + int freq_reg_info(struct wiphy *wiphy, + u32 center_freq, +@@ -1205,6 +712,7 @@ int freq_reg_info(struct wiphy *wiphy, + reg_rule, + NULL); + } ++EXPORT_SYMBOL(freq_reg_info); + + /* + * Note that right now we assume the desired channel bandwidth +@@ -1243,41 +751,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, + desired_bw_khz, + ®_rule); + +- if (r) { +- /* +- * This means no regulatory rule was found in the country IE +- * with a frequency range on the center_freq's band, since +- * IEEE-802.11 allows for a country IE to have a subset of the +- * regulatory information provided in a country we ignore +- * disabling the channel unless at least one reg rule was +- * found on the center_freq's band. For details see this +- * clarification: +- * +- * http://tinyurl.com/11d-clarification +- */ +- if (r == -ERANGE && +- last_request->initiator == +- NL80211_REGDOM_SET_BY_COUNTRY_IE) { +- REG_DBG_PRINT("cfg80211: Leaving channel %d MHz " +- "intact on %s - no rule found in band on " +- "Country IE\n", +- chan->center_freq, wiphy_name(wiphy)); +- } else { +- /* +- * In this case we know the country IE has at least one reg rule +- * for the band so we respect its band definitions +- */ +- if (last_request->initiator == +- NL80211_REGDOM_SET_BY_COUNTRY_IE) +- REG_DBG_PRINT("cfg80211: Disabling " +- "channel %d MHz on %s due to " +- "Country IE\n", +- chan->center_freq, wiphy_name(wiphy)); +- flags |= IEEE80211_CHAN_DISABLED; +- chan->flags = flags; +- } ++ if (r) + return; +- } + + power_rule = ®_rule->power_rule; + freq_range = ®_rule->freq_range; +@@ -2010,7 +1485,7 @@ EXPORT_SYMBOL(regulatory_hint); + + /* Caller must hold reg_mutex */ + static bool reg_same_country_ie_hint(struct wiphy *wiphy, +- u32 country_ie_checksum) ++ char *alpha2, enum environment_cap env) + { + struct wiphy *request_wiphy; + +@@ -2026,13 +1501,17 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy, + return false; + + if (likely(request_wiphy != wiphy)) +- return !country_ie_integrity_changes(country_ie_checksum); ++ return (last_request->alpha2[0] == alpha2[0] && ++ last_request->alpha2[1] == alpha2[1] && ++ last_request->country_ie_env == env); + /* + * We should not have let these through at this point, they + * should have been picked up earlier by the first alpha2 check + * on the device + */ +- if (WARN_ON(!country_ie_integrity_changes(country_ie_checksum))) ++ if (WARN_ON((last_request->alpha2[0] == alpha2[0] && ++ last_request->alpha2[1] == alpha2[1] && ++ last_request->country_ie_env == env ))) + return true; + return false; + } +@@ -2048,7 +1527,6 @@ void regulatory_hint_11d(struct wiphy *wiphy, + { + struct ieee80211_regdomain *rd = NULL; + char alpha2[2]; +- u32 checksum = 0; + enum environment_cap env = ENVIRON_ANY; + struct regulatory_request *request; + +@@ -2064,14 +1542,6 @@ void regulatory_hint_11d(struct wiphy *wiphy, + if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) + goto out; + +- /* +- * Pending country IE processing, this can happen after we +- * call CRDA and wait for a response if a beacon was received before +- * we were able to process the last regulatory_hint_11d() call +- */ +- if (country_ie_regdomain) +- goto out; +- + alpha2[0] = country_ie[0]; + alpha2[1] = country_ie[1]; + +@@ -2090,12 +1560,6 @@ void regulatory_hint_11d(struct wiphy *wiphy, + wiphy_idx_valid(last_request->wiphy_idx))) + goto out; + +- rd = country_ie_2_rd(band, country_ie, country_ie_len, &checksum); +- if (!rd) { +- REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n"); +- goto out; +- } +- + /* + * This will not happen right now but we leave it here for the + * the future when we want to add suspend/resume support and having +@@ -2105,24 +1569,17 @@ void regulatory_hint_11d(struct wiphy *wiphy, + * If we hit this before we add this support we want to be informed of + * it as it would indicate a mistake in the current design + */ +- if (WARN_ON(reg_same_country_ie_hint(wiphy, checksum))) ++ if (WARN_ON(reg_same_country_ie_hint(wiphy, alpha2, env))) + goto free_rd_out; + + request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); + if (!request) + goto free_rd_out; + +- /* +- * We keep this around for when CRDA comes back with a response so +- * we can intersect with that +- */ +- country_ie_regdomain = rd; +- + request->wiphy_idx = get_wiphy_idx(wiphy); +- request->alpha2[0] = rd->alpha2[0]; +- request->alpha2[1] = rd->alpha2[1]; ++ request->alpha2[0] = alpha2[0]; ++ request->alpha2[1] = alpha2[1]; + request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; +- request->country_ie_checksum = checksum; + request->country_ie_env = env; + + mutex_unlock(®_mutex); +@@ -2383,33 +1840,6 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd) + print_rd_rules(rd); + } + +-#ifdef CONFIG_CFG80211_REG_DEBUG +-static void reg_country_ie_process_debug( +- const struct ieee80211_regdomain *rd, +- const struct ieee80211_regdomain *country_ie_regdomain, +- const struct ieee80211_regdomain *intersected_rd) +-{ +- printk(KERN_DEBUG "cfg80211: Received country IE:\n"); +- print_regdomain_info(country_ie_regdomain); +- printk(KERN_DEBUG "cfg80211: CRDA thinks this should applied:\n"); +- print_regdomain_info(rd); +- if (intersected_rd) { +- printk(KERN_DEBUG "cfg80211: We intersect both of these " +- "and get:\n"); +- print_regdomain_info(intersected_rd); +- return; +- } +- printk(KERN_DEBUG "cfg80211: Intersection between both failed\n"); +-} +-#else +-static inline void reg_country_ie_process_debug( +- const struct ieee80211_regdomain *rd, +- const struct ieee80211_regdomain *country_ie_regdomain, +- const struct ieee80211_regdomain *intersected_rd) +-{ +-} +-#endif +- + /* Takes ownership of rd only if it doesn't fail */ + static int __set_regdom(const struct ieee80211_regdomain *rd) + { +@@ -2521,34 +1951,6 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) + return 0; + } + +- /* +- * Country IE requests are handled a bit differently, we intersect +- * the country IE rd with what CRDA believes that country should have +- */ +- +- /* +- * Userspace could have sent two replies with only +- * one kernel request. By the second reply we would have +- * already processed and consumed the country_ie_regdomain. +- */ +- if (!country_ie_regdomain) +- return -EALREADY; +- BUG_ON(rd == country_ie_regdomain); +- +- /* +- * Intersect what CRDA returned and our what we +- * had built from the Country IE received +- */ +- +- intersected_rd = regdom_intersect(rd, country_ie_regdomain); +- +- reg_country_ie_process_debug(rd, +- country_ie_regdomain, +- intersected_rd); +- +- kfree(country_ie_regdomain); +- country_ie_regdomain = NULL; +- + if (!intersected_rd) + return -EINVAL; + +@@ -2688,9 +2090,6 @@ void /* __init_or_exit */ regulatory_exit(void) + + reset_regdomains(); + +- kfree(country_ie_regdomain); +- country_ie_regdomain = NULL; +- + kfree(last_request); + + platform_device_unregister(reg_pdev); +-- +1.7.1.1 + + |