regd.c 13.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (c) 2008 Atheros Communications Inc.
 *
 * 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.
 */

#include <linux/kernel.h>
#include <linux/slab.h>
S
Sujith 已提交
19
#include "ath9k.h"
20 21
#include "regd_common.h"

22 23 24 25 26 27
/*
 * This is a set of common rules used by our world regulatory domains.
 * We have 12 world regulatory domains. To save space we consolidate
 * the regulatory domains in 5 structures by frequency and change
 * the flags on our reg_notifier() on a case by case basis.
 */
28

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
/* Only these channels all allow active scan on all world regulatory domains */
#define ATH9K_2GHZ_CH01_11	REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)

/* We enable active scan on these a case by case basis by regulatory domain */
#define ATH9K_2GHZ_CH12_13	REG_RULE(2467-10, 2472+10, 40, 0, 20,\
					NL80211_RRF_PASSIVE_SCAN)
#define ATH9K_2GHZ_CH14		REG_RULE(2484-10, 2484+10, 40, 0, 20,\
				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)

/* We allow IBSS on these on a case by case basis by regulatory domain */
#define ATH9K_5GHZ_5150_5350	REG_RULE(5150-10, 5350+10, 40, 0, 30,\
				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
#define ATH9K_5GHZ_5470_5850	REG_RULE(5470-10, 5850+10, 40, 0, 30,\
				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
#define ATH9K_5GHZ_5725_5850	REG_RULE(5725-10, 5850+10, 40, 0, 30,\
				NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)

#define ATH9K_2GHZ_ALL		ATH9K_2GHZ_CH01_11, \
				ATH9K_2GHZ_CH12_13, \
				ATH9K_2GHZ_CH14

#define ATH9K_5GHZ_ALL		ATH9K_5GHZ_5150_5350, \
				ATH9K_5GHZ_5470_5850
/* This one skips what we call "mid band" */
#define ATH9K_5GHZ_NO_MIDBAND	ATH9K_5GHZ_5150_5350, \
				ATH9K_5GHZ_5725_5850

/* Can be used for:
 * 0x60, 0x61, 0x62 */
static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = {
	.n_reg_rules = 5,
	.alpha2 =  "99",
	.reg_rules = {
		ATH9K_2GHZ_ALL,
		ATH9K_5GHZ_ALL,
	}
};

/* Can be used by 0x63 and 0x65 */
static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = {
	.n_reg_rules = 4,
	.alpha2 =  "99",
	.reg_rules = {
		ATH9K_2GHZ_CH01_11,
		ATH9K_2GHZ_CH12_13,
		ATH9K_5GHZ_NO_MIDBAND,
	}
};

/* Can be used by 0x64 only */
static const struct ieee80211_regdomain ath9k_world_regdom_64 = {
	.n_reg_rules = 3,
	.alpha2 =  "99",
	.reg_rules = {
		ATH9K_2GHZ_CH01_11,
		ATH9K_5GHZ_NO_MIDBAND,
	}
};

/* Can be used by 0x66 and 0x69 */
static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = {
	.n_reg_rules = 3,
	.alpha2 =  "99",
	.reg_rules = {
		ATH9K_2GHZ_CH01_11,
		ATH9K_5GHZ_ALL,
	}
};

/* Can be used by 0x67, 0x6A and 0x68 */
static const struct ieee80211_regdomain ath9k_world_regdom_67_68_6A = {
	.n_reg_rules = 4,
	.alpha2 =  "99",
	.reg_rules = {
		ATH9K_2GHZ_CH01_11,
		ATH9K_2GHZ_CH12_13,
		ATH9K_5GHZ_ALL,
	}
};
108

109 110 111 112 113 114
static inline bool is_wwr_sku(u16 regd)
{
	return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) ||
		(regd == WORLD);
}

115
static u16 ath9k_regd_get_eepromRD(struct ath_hw *ah)
116
{
117
	return ah->regulatory.current_rd & ~WORLDWIDE_ROAMING_FLAG;
118 119
}

120
bool ath9k_is_world_regd(struct ath_hw *ah)
121
{
122
	return is_wwr_sku(ath9k_regd_get_eepromRD(ah));
123 124
}

125
const struct ieee80211_regdomain *ath9k_default_world_regdomain(void)
126
{
127 128 129
	/* this is the most restrictive */
	return &ath9k_world_regdom_64;
}
130

131
const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah)
132
{
133
	switch (ah->regulatory.regpair->regDmnEnum) {
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
	case 0x60:
	case 0x61:
	case 0x62:
		return &ath9k_world_regdom_60_61_62;
	case 0x63:
	case 0x65:
		return &ath9k_world_regdom_63_65;
	case 0x64:
		return &ath9k_world_regdom_64;
	case 0x66:
	case 0x69:
		return &ath9k_world_regdom_66_69;
	case 0x67:
	case 0x68:
	case 0x6A:
		return &ath9k_world_regdom_67_68_6A;
	default:
		WARN_ON(1);
		return ath9k_default_world_regdomain();
153 154 155
	}
}

156 157 158 159 160 161
/* Frequency is one where radar detection is required */
static bool ath9k_is_radar_freq(u16 center_freq)
{
	return (center_freq >= 5260 && center_freq <= 5700);
}

162
/*
163 164 165 166 167 168 169
 * N.B: These exception rules do not apply radar freqs.
 *
 * - We enable adhoc (or beaconing) if allowed by 11d
 * - We enable active scan if the channel is allowed by 11d
 * - If no country IE has been processed and a we determine we have
 *   received a beacon on a channel we can enable active scan and
 *   adhoc (or beaconing).
170
 */
171
static void ath9k_reg_apply_beaconing_flags(struct wiphy *wiphy,
172
					     enum reg_set_by setby)
173
{
174
	enum ieee80211_band band;
175 176 177 178 179 180 181
	struct ieee80211_supported_band *sband;
	const struct ieee80211_reg_rule *reg_rule;
	struct ieee80211_channel *ch;
	unsigned int i;
	u32 bandwidth = 0;
	int r;

182
	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
183

184
		if (!wiphy->bands[band])
185
			continue;
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223

		sband = wiphy->bands[band];

		for (i = 0; i < sband->n_channels; i++) {

			ch = &sband->channels[i];

			if (ath9k_is_radar_freq(ch->center_freq) ||
			    (ch->flags & IEEE80211_CHAN_RADAR))
				continue;

			if (setby == REGDOM_SET_BY_COUNTRY_IE) {
				r = freq_reg_info(wiphy, ch->center_freq,
					&bandwidth, &reg_rule);
				if (r)
					continue;
				/*
				 * If 11d had a rule for this channel ensure
				 * we enable adhoc/beaconing if it allows us to
				 * use it. Note that we would have disabled it
				 * by applying our static world regdomain by
				 * default during init, prior to calling our
				 * regulatory_hint().
				 */
				if (!(reg_rule->flags &
				    NL80211_RRF_NO_IBSS))
					ch->flags &=
					  ~IEEE80211_CHAN_NO_IBSS;
				if (!(reg_rule->flags &
				    NL80211_RRF_PASSIVE_SCAN))
					ch->flags &=
					  ~IEEE80211_CHAN_PASSIVE_SCAN;
			} else {
				if (ch->beacon_found)
					ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
					  IEEE80211_CHAN_PASSIVE_SCAN);
			}
		}
224
	}
225

226 227
}

228 229 230
/* Allows active scan scan on Ch 12 and 13 */
static void ath9k_reg_apply_active_scan_flags(struct wiphy *wiphy,
					      enum reg_set_by setby)
231
{
232 233 234 235 236 237 238 239
	struct ieee80211_supported_band *sband;
	struct ieee80211_channel *ch;
	const struct ieee80211_reg_rule *reg_rule;
	u32 bandwidth = 0;
	int r;

	sband = wiphy->bands[IEEE80211_BAND_2GHZ];

240 241 242 243
	/*
	 * If no country IE has been received always enable active scan
	 * on these channels. This is only done for specific regulatory SKUs
	 */
244 245 246 247 248 249 250 251 252
	if (setby != REGDOM_SET_BY_COUNTRY_IE) {
		ch = &sband->channels[11]; /* CH 12 */
		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
		ch = &sband->channels[12]; /* CH 13 */
		if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
			ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
		return;
	}
253

254 255
	/*
	 * If a country IE has been recieved check its rule for this
256
	 * channel first before enabling active scan. The passive scan
257 258 259
	 * would have been enforced by the initial processing of our
	 * custom regulatory domain.
	 */
260

261 262 263 264 265 266
	ch = &sband->channels[11]; /* CH 12 */
	r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, &reg_rule);
	if (!r) {
		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
267 268
	}

269 270 271 272 273 274
	ch = &sband->channels[12]; /* CH 13 */
	r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, &reg_rule);
	if (!r) {
		if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
				ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
275 276 277
	}
}

278 279
/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
void ath9k_reg_apply_radar_flags(struct wiphy *wiphy)
280
{
281 282 283
	struct ieee80211_supported_band *sband;
	struct ieee80211_channel *ch;
	unsigned int i;
284

285 286
	if (!wiphy->bands[IEEE80211_BAND_5GHZ])
		return;
287

288
	sband = wiphy->bands[IEEE80211_BAND_5GHZ];
289

290 291
	for (i = 0; i < sband->n_channels; i++) {
		ch = &sband->channels[i];
292
		if (!ath9k_is_radar_freq(ch->center_freq))
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
			continue;
		/* We always enable radar detection/DFS on this
		 * frequency range. Additionally we also apply on
		 * this frequency range:
		 * - If STA mode does not yet have DFS supports disable
		 *   active scanning
		 * - If adhoc mode does not support DFS yet then
		 *   disable adhoc in the frequency.
		 * - If AP mode does not yet support radar detection/DFS
		 *   do not allow AP mode
		 */
		if (!(ch->flags & IEEE80211_CHAN_DISABLED))
			ch->flags |= IEEE80211_CHAN_RADAR |
				     IEEE80211_CHAN_NO_IBSS |
				     IEEE80211_CHAN_PASSIVE_SCAN;
	}
}
310

311 312 313 314
void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby)
{
	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
	struct ath_softc *sc = hw->priv;
315
	struct ath_hw *ah = sc->sc_ah;
316

317
	switch (ah->regulatory.regpair->regDmnEnum) {
318 319 320 321
	case 0x60:
	case 0x63:
	case 0x66:
	case 0x67:
322
		ath9k_reg_apply_beaconing_flags(wiphy, setby);
323 324
		break;
	case 0x68:
325
		ath9k_reg_apply_beaconing_flags(wiphy, setby);
326 327 328 329 330
		ath9k_reg_apply_active_scan_flags(wiphy, setby);
		break;
	}
	return;
}
331

332 333 334 335
int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
{
	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
	struct ath_softc *sc = hw->priv;
336

337 338
	/* We always apply this */
	ath9k_reg_apply_radar_flags(wiphy);
339

340 341 342 343 344 345 346 347 348 349 350
	switch (request->initiator) {
	case REGDOM_SET_BY_DRIVER:
	case REGDOM_SET_BY_INIT:
	case REGDOM_SET_BY_CORE:
	case REGDOM_SET_BY_USER:
		break;
	case REGDOM_SET_BY_COUNTRY_IE:
		if (ath9k_is_world_regd(sc->sc_ah))
			ath9k_reg_apply_world_flags(wiphy, request->initiator);
		break;
	}
351

352
	return 0;
353 354
}

355
bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah)
356
{
357 358
	u16 rd = ath9k_regd_get_eepromRD(ah);
	int i;
359

360 361 362 363 364 365 366 367 368 369 370
	if (rd & COUNTRY_ERD_FLAG) {
		/* EEPROM value is a country code */
		u16 cc = rd & ~COUNTRY_ERD_FLAG;
		for (i = 0; i < ARRAY_SIZE(allCountries); i++)
			if (allCountries[i].countryCode == cc)
				return true;
	} else {
		/* EEPROM value is a regpair value */
		for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++)
			if (regDomainPairs[i].regDmnEnum == rd)
				return true;
371
	}
372 373
	DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
		 "invalid regulatory domain/country code 0x%x\n", rd);
374 375 376
	return false;
}

377
/* EEPROM country code to regpair mapping */
378 379 380 381 382 383 384 385 386 387 388 389
static struct country_code_to_enum_rd*
ath9k_regd_find_country(u16 countryCode)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
		if (allCountries[i].countryCode == countryCode)
			return &allCountries[i];
	}
	return NULL;
}

390 391 392 393 394 395 396 397 398 399 400 401 402 403
/* EEPROM rd code to regpair mapping */
static struct country_code_to_enum_rd*
ath9k_regd_find_country_by_rd(int regdmn)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
		if (allCountries[i].regDmnEnum == regdmn)
			return &allCountries[i];
	}
	return NULL;
}

/* Returns the map of the EEPROM set RD to a country code */
404
static u16 ath9k_regd_get_default_country(u16 rd)
405 406 407 408 409 410 411 412 413 414 415 416 417
{
	if (rd & COUNTRY_ERD_FLAG) {
		struct country_code_to_enum_rd *country = NULL;
		u16 cc = rd & ~COUNTRY_ERD_FLAG;

		country = ath9k_regd_find_country(cc);
		if (country != NULL)
			return cc;
	}

	return CTRY_DEFAULT;
}

418 419
static struct reg_dmn_pair_mapping*
ath9k_get_regpair(int regdmn)
420 421 422
{
	int i;

423 424
	if (regdmn == NO_ENUMRD)
		return NULL;
425
	for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
426 427
		if (regDomainPairs[i].regDmnEnum == regdmn)
			return &regDomainPairs[i];
428
	}
429
	return NULL;
430 431
}

432
int ath9k_regd_init(struct ath_hw *ah)
433 434
{
	struct country_code_to_enum_rd *country = NULL;
435
	u16 regdmn;
436 437 438

	if (!ath9k_regd_is_eeprom_valid(ah)) {
		DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
S
Sujith 已提交
439
			"Invalid EEPROM contents\n");
440
		return -EINVAL;
441 442
	}

443 444
	regdmn = ath9k_regd_get_eepromRD(ah);
	ah->regulatory.country_code = ath9k_regd_get_default_country(regdmn);
445

446
	if (ah->regulatory.country_code == CTRY_DEFAULT &&
447
	    regdmn == CTRY_DEFAULT)
448
		ah->regulatory.country_code = CTRY_UNITED_STATES;
449

450
	if (ah->regulatory.country_code == CTRY_DEFAULT) {
451 452
		country = NULL;
	} else {
453
		country = ath9k_regd_find_country(ah->regulatory.country_code);
454 455 456
		if (country == NULL) {
			DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
				"Country is NULL!!!!, cc= %d\n",
457
				ah->regulatory.country_code);
458 459
			return -EINVAL;
		} else
460 461 462
			regdmn = country->regDmnEnum;
	}

463
	ah->regulatory.regpair = ath9k_get_regpair(regdmn);
464

465
	if (!ah->regulatory.regpair) {
466 467 468
		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
			"No regulatory domain pair found, cannot continue\n");
		return -EINVAL;
469 470
	}

471 472
	if (!country)
		country = ath9k_regd_find_country_by_rd(regdmn);
473

474
	if (country) {
475 476
		ah->regulatory.alpha2[0] = country->isoName[0];
		ah->regulatory.alpha2[1] = country->isoName[1];
477
	} else {
478 479
		ah->regulatory.alpha2[0] = '0';
		ah->regulatory.alpha2[1] = '0';
480 481 482
	}

	DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
483
		"Country alpha2 being used: %c%c\n"
484 485 486
		"Regulatory.Regpair detected: 0x%0x\n",
		ah->regulatory.alpha2[0], ah->regulatory.alpha2[1],
		ah->regulatory.regpair->regDmnEnum);
487

488
	return 0;
489 490
}

491
u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan)
492 493 494
{
	u32 ctl = NO_CTL;

495
	if (!ah->regulatory.regpair ||
496 497
	    (ah->regulatory.country_code == CTRY_DEFAULT &&
	     is_wwr_sku(ath9k_regd_get_eepromRD(ah)))) {
498 499 500 501 502 503
		if (IS_CHAN_B(chan))
			ctl = SD_NO_CTL | CTL_11B;
		else if (IS_CHAN_G(chan))
			ctl = SD_NO_CTL | CTL_11G;
		else
			ctl = SD_NO_CTL | CTL_11A;
504
		return ctl;
505 506
	}

507
	if (IS_CHAN_B(chan))
508
		ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11B;
509
	else if (IS_CHAN_G(chan))
510
		ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11G;
511
	else
512
		ctl = ah->regulatory.regpair->reg_5ghz_ctl | CTL_11A;
513

514
	return ctl;
515
}