[go: nahoru, domu]

regd.c revision 88f6bfe1829d67bea37b060d53131b2b96ebc8ac
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <linux/kernel.h>
18#include <linux/slab.h>
19#include <net/cfg80211.h>
20#include <net/mac80211.h>
21#include "regd.h"
22#include "regd_common.h"
23
24/*
25 * This is a set of common rules used by our world regulatory domains.
26 * We have 12 world regulatory domains. To save space we consolidate
27 * the regulatory domains in 5 structures by frequency and change
28 * the flags on our reg_notifier() on a case by case basis.
29 */
30
31/* Only these channels all allow active scan on all world regulatory domains */
32#define ATH9K_2GHZ_CH01_11	REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
33
34/* We enable active scan on these a case by case basis by regulatory domain */
35#define ATH9K_2GHZ_CH12_13	REG_RULE(2467-10, 2472+10, 40, 0, 20,\
36					NL80211_RRF_PASSIVE_SCAN)
37#define ATH9K_2GHZ_CH14		REG_RULE(2484-10, 2484+10, 40, 0, 20,\
38				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
39
40/* We allow IBSS on these on a case by case basis by regulatory domain */
41#define ATH9K_5GHZ_5150_5350	REG_RULE(5150-10, 5350+10, 40, 0, 30,\
42				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
43#define ATH9K_5GHZ_5470_5850	REG_RULE(5470-10, 5850+10, 40, 0, 30,\
44				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
45#define ATH9K_5GHZ_5725_5850	REG_RULE(5725-10, 5850+10, 40, 0, 30,\
46				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
47
48#define ATH9K_2GHZ_ALL		ATH9K_2GHZ_CH01_11, \
49				ATH9K_2GHZ_CH12_13, \
50				ATH9K_2GHZ_CH14
51
52#define ATH9K_5GHZ_ALL		ATH9K_5GHZ_5150_5350, \
53				ATH9K_5GHZ_5470_5850
54/* This one skips what we call "mid band" */
55#define ATH9K_5GHZ_NO_MIDBAND	ATH9K_5GHZ_5150_5350, \
56				ATH9K_5GHZ_5725_5850
57
58/* Can be used for:
59 * 0x60, 0x61, 0x62 */
60static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
61	.n_reg_rules = 5,
62	.alpha2 =  "99",
63	.reg_rules = {
64		ATH9K_2GHZ_ALL,
65		ATH9K_5GHZ_ALL,
66	}
67};
68
69/* Can be used by 0x63 and 0x65 */
70static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
71	.n_reg_rules = 4,
72	.alpha2 =  "99",
73	.reg_rules = {
74		ATH9K_2GHZ_CH01_11,
75		ATH9K_2GHZ_CH12_13,
76		ATH9K_5GHZ_NO_MIDBAND,
77	}
78};
79
80/* Can be used by 0x64 only */
81static const struct ieee80211_regdomain ath_world_regdom_64 = {
82	.n_reg_rules = 3,
83	.alpha2 =  "99",
84	.reg_rules = {
85		ATH9K_2GHZ_CH01_11,
86		ATH9K_5GHZ_NO_MIDBAND,
87	}
88};
89
90/* Can be used by 0x66 and 0x69 */
91static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
92	.n_reg_rules = 3,
93	.alpha2 =  "99",
94	.reg_rules = {
95		ATH9K_2GHZ_CH01_11,
96		ATH9K_5GHZ_ALL,
97	}
98};
99
100/* Can be used by 0x67, 0x6A and 0x68 */
101static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = {
102	.n_reg_rules = 4,
103	.alpha2 =  "99",
104	.reg_rules = {
105		ATH9K_2GHZ_CH01_11,
106		ATH9K_2GHZ_CH12_13,
107		ATH9K_5GHZ_ALL,
108	}
109};
110
111static inline bool is_wwr_sku(u16 regd)
112{
113	return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
114		(regd == WORLD);
115}
116
117static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
118{
119	return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
120}
121
122bool ath_is_world_regd(struct ath_regulatory *reg)
123{
124	return is_wwr_sku(ath_regd_get_eepromRD(reg));
125}
126EXPORT_SYMBOL(ath_is_world_regd);
127
128static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
129{
130	/* this is the most restrictive */
131	return &ath_world_regdom_64;
132}
133
134static const struct
135ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
136{
137	switch (reg->regpair->regDmnEnum) {
138	case 0x60:
139	case 0x61:
140	case 0x62:
141		return &ath_world_regdom_60_61_62;
142	case 0x63:
143	case 0x65:
144		return &ath_world_regdom_63_65;
145	case 0x64:
146		return &ath_world_regdom_64;
147	case 0x66:
148	case 0x69:
149		return &ath_world_regdom_66_69;
150	case 0x67:
151	case 0x68:
152	case 0x6A:
153		return &ath_world_regdom_67_68_6A;
154	default:
155		WARN_ON(1);
156		return ath_default_world_regdomain();
157	}
158}
159
160/* Frequency is one where radar detection is required */
161static bool ath_is_radar_freq(u16 center_freq)
162{
163	return (center_freq >= 5260 && center_freq <= 5700);
164}
165
166/*
167 * N.B: These exception rules do not apply radar freqs.
168 *
169 * - We enable adhoc (or beaconing) if allowed by 11d
170 * - We enable active scan if the channel is allowed by 11d
171 * - If no country IE has been processed and a we determine we have
172 *   received a beacon on a channel we can enable active scan and
173 *   adhoc (or beaconing).
174 */
175static void
176ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
177			      enum nl80211_reg_initiator initiator)
178{
179	enum ieee80211_band band;
180	struct ieee80211_supported_band *sband;
181	const struct ieee80211_reg_rule *reg_rule;
182	struct ieee80211_channel *ch;
183	unsigned int i;
184	u32 bandwidth = 0;
185	int r;
186
187	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
188
189		if (!wiphy->bands[band])
190			continue;
191
192		sband = wiphy->bands[band];
193
194		for (i = 0; i < sband->n_channels; i++) {
195
196			ch = &sband->channels[i];
197
198			if (ath_is_radar_freq(ch->center_freq) ||
199			    (ch->flags & IEEE80211_CHAN_RADAR))
200				continue;
201
202			if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
203				r = freq_reg_info(wiphy,
204						  ch->center_freq,
205						  bandwidth,
206						  &reg_rule);
207				if (r)
208					continue;
209				/*
210				 * If 11d had a rule for this channel ensure
211				 * we enable adhoc/beaconing if it allows us to
212				 * use it. Note that we would have disabled it
213				 * by applying our static world regdomain by
214				 * default during init, prior to calling our
215				 * regulatory_hint().
216				 */
217				if (!(reg_rule->flags &
218				    NL80211_RRF_NO_IBSS))
219					ch->flags &=
220					  ~IEEE80211_CHAN_NO_IBSS;
221				if (!(reg_rule->flags &
222				    NL80211_RRF_PASSIVE_SCAN))
223					ch->flags &=
224					  ~IEEE80211_CHAN_PASSIVE_SCAN;
225			} else {
226				if (ch->beacon_found)
227					ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
228					  IEEE80211_CHAN_PASSIVE_SCAN);
229			}
230		}
231	}
232
233}
234
235/* Allows active scan scan on Ch 12 and 13 */
236static void
237ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
238				enum nl80211_reg_initiator initiator)
239{
240	struct ieee80211_supported_band *sband;
241	struct ieee80211_channel *ch;
242	const struct ieee80211_reg_rule *reg_rule;
243	u32 bandwidth = 0;
244	int r;
245
246	sband = wiphy->bands[IEEE80211_BAND_2GHZ];
247
248	/*
249	 * If no country IE has been received always enable active scan
250	 * on these channels. This is only done for specific regulatory SKUs
251	 */
252	if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
253		ch = &sband->channels[11]; /* CH 12 */
254		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
255			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
256		ch = &sband->channels[12]; /* CH 13 */
257		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
258			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
259		return;
260	}
261
262	/*
263	 * If a country IE has been recieved check its rule for this
264	 * channel first before enabling active scan. The passive scan
265	 * would have been enforced by the initial processing of our
266	 * custom regulatory domain.
267	 */
268
269	ch = &sband->channels[11]; /* CH 12 */
270	r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
271	if (!r) {
272		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
273			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
274				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
275	}
276
277	ch = &sband->channels[12]; /* CH 13 */
278	r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
279	if (!r) {
280		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
281			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
282				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
283	}
284}
285
286/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
287static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
288{
289	struct ieee80211_supported_band *sband;
290	struct ieee80211_channel *ch;
291	unsigned int i;
292
293	if (!wiphy->bands[IEEE80211_BAND_5GHZ])
294		return;
295
296	sband = wiphy->bands[IEEE80211_BAND_5GHZ];
297
298	for (i = 0; i < sband->n_channels; i++) {
299		ch = &sband->channels[i];
300		if (!ath_is_radar_freq(ch->center_freq))
301			continue;
302		/* We always enable radar detection/DFS on this
303		 * frequency range. Additionally we also apply on
304		 * this frequency range:
305		 * - If STA mode does not yet have DFS supports disable
306		 *   active scanning
307		 * - If adhoc mode does not support DFS yet then
308		 *   disable adhoc in the frequency.
309		 * - If AP mode does not yet support radar detection/DFS
310		 *   do not allow AP mode
311		 */
312		if (!(ch->flags & IEEE80211_CHAN_DISABLED))
313			ch->flags |= IEEE80211_CHAN_RADAR |
314				     IEEE80211_CHAN_NO_IBSS |
315				     IEEE80211_CHAN_PASSIVE_SCAN;
316	}
317}
318
319static void ath_reg_apply_world_flags(struct wiphy *wiphy,
320				      enum nl80211_reg_initiator initiator,
321				      struct ath_regulatory *reg)
322{
323	switch (reg->regpair->regDmnEnum) {
324	case 0x60:
325	case 0x63:
326	case 0x66:
327	case 0x67:
328		ath_reg_apply_beaconing_flags(wiphy, initiator);
329		break;
330	case 0x68:
331		ath_reg_apply_beaconing_flags(wiphy, initiator);
332		ath_reg_apply_active_scan_flags(wiphy, initiator);
333		break;
334	}
335	return;
336}
337
338int ath_reg_notifier_apply(struct wiphy *wiphy,
339			   struct regulatory_request *request,
340			   struct ath_regulatory *reg)
341{
342	/* We always apply this */
343	ath_reg_apply_radar_flags(wiphy);
344
345	switch (request->initiator) {
346	case NL80211_REGDOM_SET_BY_DRIVER:
347	case NL80211_REGDOM_SET_BY_CORE:
348	case NL80211_REGDOM_SET_BY_USER:
349		break;
350	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
351		if (ath_is_world_regd(reg))
352			ath_reg_apply_world_flags(wiphy, request->initiator,
353						  reg);
354		break;
355	}
356
357	return 0;
358}
359EXPORT_SYMBOL(ath_reg_notifier_apply);
360
361static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
362{
363	 u16 rd = ath_regd_get_eepromRD(reg);
364	int i;
365
366	if (rd & COUNTRY_ERD_FLAG) {
367		/* EEPROM value is a country code */
368		u16 cc = rd & ~COUNTRY_ERD_FLAG;
369		printk(KERN_DEBUG
370		       "ath: EEPROM indicates we should expect "
371			"a country code\n");
372		for (i = 0; i < ARRAY_SIZE(allCountries); i++)
373			if (allCountries[i].countryCode == cc)
374				return true;
375	} else {
376		/* EEPROM value is a regpair value */
377		if (rd != CTRY_DEFAULT)
378			printk(KERN_DEBUG "ath: EEPROM indicates we "
379			       "should expect a direct regpair map\n");
380		for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
381			if (regDomainPairs[i].regDmnEnum == rd)
382				return true;
383	}
384	printk(KERN_DEBUG
385		 "ath: invalid regulatory domain/country code 0x%x\n", rd);
386	return false;
387}
388
389/* EEPROM country code to regpair mapping */
390static struct country_code_to_enum_rd*
391ath_regd_find_country(u16 countryCode)
392{
393	int i;
394
395	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
396		if (allCountries[i].countryCode == countryCode)
397			return &allCountries[i];
398	}
399	return NULL;
400}
401
402/* EEPROM rd code to regpair mapping */
403static struct country_code_to_enum_rd*
404ath_regd_find_country_by_rd(int regdmn)
405{
406	int i;
407
408	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
409		if (allCountries[i].regDmnEnum == regdmn)
410			return &allCountries[i];
411	}
412	return NULL;
413}
414
415/* Returns the map of the EEPROM set RD to a country code */
416static u16 ath_regd_get_default_country(u16 rd)
417{
418	if (rd & COUNTRY_ERD_FLAG) {
419		struct country_code_to_enum_rd *country = NULL;
420		u16 cc = rd & ~COUNTRY_ERD_FLAG;
421
422		country = ath_regd_find_country(cc);
423		if (country != NULL)
424			return cc;
425	}
426
427	return CTRY_DEFAULT;
428}
429
430static struct reg_dmn_pair_mapping*
431ath_get_regpair(int regdmn)
432{
433	int i;
434
435	if (regdmn == NO_ENUMRD)
436		return NULL;
437	for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
438		if (regDomainPairs[i].regDmnEnum == regdmn)
439			return &regDomainPairs[i];
440	}
441	return NULL;
442}
443
444static int
445ath_regd_init_wiphy(struct ath_regulatory *reg,
446		    struct wiphy *wiphy,
447		    int (*reg_notifier)(struct wiphy *wiphy,
448					struct regulatory_request *request))
449{
450	const struct ieee80211_regdomain *regd;
451
452	wiphy->reg_notifier = reg_notifier;
453	wiphy->strict_regulatory = true;
454
455	if (ath_is_world_regd(reg)) {
456		/*
457		 * Anything applied here (prior to wiphy registration) gets
458		 * saved on the wiphy orig_* parameters
459		 */
460		regd = ath_world_regdomain(reg);
461		wiphy->custom_regulatory = true;
462		wiphy->strict_regulatory = false;
463	} else {
464		/*
465		 * This gets applied in the case of the absense of CRDA,
466		 * it's our own custom world regulatory domain, similar to
467		 * cfg80211's but we enable passive scanning.
468		 */
469		regd = ath_default_world_regdomain();
470	}
471	wiphy_apply_custom_regulatory(wiphy, regd);
472	ath_reg_apply_radar_flags(wiphy);
473	ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
474	return 0;
475}
476
477int
478ath_regd_init(struct ath_regulatory *reg,
479	      struct wiphy *wiphy,
480	      int (*reg_notifier)(struct wiphy *wiphy,
481				  struct regulatory_request *request))
482{
483	struct country_code_to_enum_rd *country = NULL;
484	u16 regdmn;
485
486	if (!reg)
487		return -EINVAL;
488
489	printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd);
490
491	if (!ath_regd_is_eeprom_valid(reg)) {
492		printk(KERN_ERR "ath: Invalid EEPROM contents\n");
493		return -EINVAL;
494	}
495
496	regdmn = ath_regd_get_eepromRD(reg);
497	reg->country_code = ath_regd_get_default_country(regdmn);
498
499	if (reg->country_code == CTRY_DEFAULT &&
500	    regdmn == CTRY_DEFAULT) {
501		printk(KERN_DEBUG "ath: EEPROM indicates default "
502		       "country code should be used\n");
503		reg->country_code = CTRY_UNITED_STATES;
504	}
505
506	if (reg->country_code == CTRY_DEFAULT) {
507		country = NULL;
508	} else {
509		printk(KERN_DEBUG "ath: doing EEPROM country->regdmn "
510		       "map search\n");
511		country = ath_regd_find_country(reg->country_code);
512		if (country == NULL) {
513			printk(KERN_DEBUG
514				"ath: no valid country maps found for "
515				"country code: 0x%0x\n",
516				reg->country_code);
517			return -EINVAL;
518		} else {
519			regdmn = country->regDmnEnum;
520			printk(KERN_DEBUG "ath: country maps to "
521			       "regdmn code: 0x%0x\n",
522			       regdmn);
523		}
524	}
525
526	reg->regpair = ath_get_regpair(regdmn);
527
528	if (!reg->regpair) {
529		printk(KERN_DEBUG "ath: "
530			"No regulatory domain pair found, cannot continue\n");
531		return -EINVAL;
532	}
533
534	if (!country)
535		country = ath_regd_find_country_by_rd(regdmn);
536
537	if (country) {
538		reg->alpha2[0] = country->isoName[0];
539		reg->alpha2[1] = country->isoName[1];
540	} else {
541		reg->alpha2[0] = '0';
542		reg->alpha2[1] = '0';
543	}
544
545	printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n",
546		reg->alpha2[0], reg->alpha2[1]);
547	printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n",
548		reg->regpair->regDmnEnum);
549
550	ath_regd_init_wiphy(reg, wiphy, reg_notifier);
551	return 0;
552}
553EXPORT_SYMBOL(ath_regd_init);
554
555u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
556			  enum ieee80211_band band)
557{
558	if (!reg->regpair ||
559	    (reg->country_code == CTRY_DEFAULT &&
560	     is_wwr_sku(ath_regd_get_eepromRD(reg)))) {
561		return SD_NO_CTL;
562	}
563
564	switch (band) {
565	case IEEE80211_BAND_2GHZ:
566		return reg->regpair->reg_2ghz_ctl;
567	case IEEE80211_BAND_5GHZ:
568		return reg->regpair->reg_5ghz_ctl;
569	default:
570		return NO_CTL;
571	}
572}
573EXPORT_SYMBOL(ath_regd_get_band_ctl);
574