xref: /openbmc/linux/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c (revision c95baf12f5077419db01313ab61c2aac007d40cd)
1  /*
2   * Copyright (c) 2010 Broadcom Corporation
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 ANY
11   * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13   * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14   * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15   */
16  
17  #include <linux/types.h>
18  #include <net/cfg80211.h>
19  #include <net/mac80211.h>
20  #include <net/regulatory.h>
21  
22  #include <defs.h>
23  #include "pub.h"
24  #include "phy/phy_hal.h"
25  #include "main.h"
26  #include "stf.h"
27  #include "channel.h"
28  #include "mac80211_if.h"
29  #include "debug.h"
30  
31  /* QDB() macro takes a dB value and converts to a quarter dB value */
32  #define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
33  
34  #define LOCALE_MIMO_IDX_bn		0
35  #define LOCALE_MIMO_IDX_11n		0
36  
37  /* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
38  #define BRCMS_MAXPWR_MIMO_TBL_SIZE	14
39  
40  /* maxpwr mapping to 5GHz band channels:
41   * maxpwr[0] - channels [34-48]
42   * maxpwr[1] - channels [52-60]
43   * maxpwr[2] - channels [62-64]
44   * maxpwr[3] - channels [100-140]
45   * maxpwr[4] - channels [149-165]
46   */
47  #define BAND_5G_PWR_LVLS	5	/* 5 power levels for 5G */
48  
49  #define LC(id)	LOCALE_MIMO_IDX_ ## id
50  
51  #define LOCALES(mimo2, mimo5) \
52  		{LC(mimo2), LC(mimo5)}
53  
54  /* macro to get 5 GHz channel group index for tx power */
55  #define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
56  				 (((c) < 62) ? 1 : \
57  				 (((c) < 100) ? 2 : \
58  				 (((c) < 149) ? 3 : 4))))
59  
60  #define BRCM_2GHZ_2412_2462	REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
61  #define BRCM_2GHZ_2467_2472	REG_RULE(2467-10, 2472+10, 20, 0, 19, \
62  					 NL80211_RRF_NO_IR)
63  
64  #define BRCM_5GHZ_5180_5240	REG_RULE(5180-10, 5240+10, 40, 0, 21, \
65  					 NL80211_RRF_NO_IR)
66  #define BRCM_5GHZ_5260_5320	REG_RULE(5260-10, 5320+10, 40, 0, 21, \
67  					 NL80211_RRF_DFS | \
68  					 NL80211_RRF_NO_IR)
69  #define BRCM_5GHZ_5500_5700	REG_RULE(5500-10, 5700+10, 40, 0, 21, \
70  					 NL80211_RRF_DFS | \
71  					 NL80211_RRF_NO_IR)
72  #define BRCM_5GHZ_5745_5825	REG_RULE(5745-10, 5825+10, 40, 0, 21, \
73  					 NL80211_RRF_NO_IR)
74  
75  static const struct ieee80211_regdomain brcms_regdom_x2 = {
76  	.n_reg_rules = 6,
77  	.alpha2 = "X2",
78  	.reg_rules = {
79  		BRCM_2GHZ_2412_2462,
80  		BRCM_2GHZ_2467_2472,
81  		BRCM_5GHZ_5180_5240,
82  		BRCM_5GHZ_5260_5320,
83  		BRCM_5GHZ_5500_5700,
84  		BRCM_5GHZ_5745_5825,
85  	}
86  };
87  
88   /* locale per-channel tx power limits for MIMO frames
89    * maxpwr arrays are index by channel for 2.4 GHz limits, and
90    * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
91    */
92  struct locale_mimo_info {
93  	/* tx 20 MHz power limits, qdBm units */
94  	s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
95  	/* tx 40 MHz power limits, qdBm units */
96  	s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
97  };
98  
99  /* Country names and abbreviations with locale defined from ISO 3166 */
100  struct country_info {
101  	const u8 locale_mimo_2G;	/* 2.4G mimo info */
102  	const u8 locale_mimo_5G;	/* 5G mimo info */
103  };
104  
105  struct brcms_regd {
106  	struct country_info country;
107  	const struct ieee80211_regdomain *regdomain;
108  };
109  
110  struct brcms_cm_info {
111  	struct brcms_pub *pub;
112  	struct brcms_c_info *wlc;
113  	const struct brcms_regd *world_regd;
114  };
115  
116  /*
117   * MIMO Locale Definitions - 2.4 GHz
118   */
119  static const struct locale_mimo_info locale_bn = {
120  	{QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
121  	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
122  	 QDB(13), QDB(13), QDB(13)},
123  	{0, 0, QDB(13), QDB(13), QDB(13),
124  	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
125  	 QDB(13), 0, 0},
126  };
127  
128  static const struct locale_mimo_info *g_mimo_2g_table[] = {
129  	&locale_bn
130  };
131  
132  /*
133   * MIMO Locale Definitions - 5 GHz
134   */
135  static const struct locale_mimo_info locale_11n = {
136  	{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
137  	{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
138  };
139  
140  static const struct locale_mimo_info *g_mimo_5g_table[] = {
141  	&locale_11n
142  };
143  
144  static const struct brcms_regd cntry_locales[] = {
145  	/* Worldwide RoW 2, must always be at index 0 */
146  	{
147  		.country = LOCALES(bn, 11n),
148  		.regdomain = &brcms_regdom_x2,
149  	},
150  };
151  
brcms_c_get_mimo_2g(u8 locale_idx)152  static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
153  {
154  	if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
155  		return NULL;
156  
157  	return g_mimo_2g_table[locale_idx];
158  }
159  
brcms_c_get_mimo_5g(u8 locale_idx)160  static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
161  {
162  	if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table))
163  		return NULL;
164  
165  	return g_mimo_5g_table[locale_idx];
166  }
167  
168  /*
169   * Indicates whether the country provided is valid to pass
170   * to cfg80211 or not.
171   *
172   * returns true if valid; false if not.
173   */
brcms_c_country_valid(const char * ccode)174  static bool brcms_c_country_valid(const char *ccode)
175  {
176  	/*
177  	 * only allow ascii alpha uppercase for the first 2
178  	 * chars.
179  	 */
180  	if (!((ccode[0] & 0x80) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
181  	      (ccode[1] & 0x80) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A))
182  		return false;
183  
184  	/*
185  	 * do not match ISO 3166-1 user assigned country codes
186  	 * that may be in the driver table
187  	 */
188  	if (!strcmp("AA", ccode) ||        /* AA */
189  	    !strcmp("ZZ", ccode) ||        /* ZZ */
190  	    ccode[0] == 'X' ||             /* XA - XZ */
191  	    (ccode[0] == 'Q' &&            /* QM - QZ */
192  	     (ccode[1] >= 'M' && ccode[1] <= 'Z')))
193  		return false;
194  
195  	if (!strcmp("NA", ccode))
196  		return false;
197  
198  	return true;
199  }
200  
brcms_world_regd(const char * regdom,int len)201  static const struct brcms_regd *brcms_world_regd(const char *regdom, int len)
202  {
203  	const struct brcms_regd *regd = NULL;
204  	int i;
205  
206  	for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) {
207  		if (!strncmp(regdom, cntry_locales[i].regdomain->alpha2, len)) {
208  			regd = &cntry_locales[i];
209  			break;
210  		}
211  	}
212  
213  	return regd;
214  }
215  
brcms_default_world_regd(void)216  static const struct brcms_regd *brcms_default_world_regd(void)
217  {
218  	return &cntry_locales[0];
219  }
220  
221  /* JP, J1 - J10 are Japan ccodes */
brcms_c_japan_ccode(const char * ccode)222  static bool brcms_c_japan_ccode(const char *ccode)
223  {
224  	return (ccode[0] == 'J' &&
225  		(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
226  }
227  
228  static void
brcms_c_channel_min_txpower_limits_with_local_constraint(struct brcms_cm_info * wlc_cm,struct txpwr_limits * txpwr,u8 local_constraint_qdbm)229  brcms_c_channel_min_txpower_limits_with_local_constraint(
230  		struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
231  		u8 local_constraint_qdbm)
232  {
233  	int j;
234  
235  	/* CCK Rates */
236  	for (j = 0; j < WL_TX_POWER_CCK_NUM; j++)
237  		txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
238  
239  	/* 20 MHz Legacy OFDM SISO */
240  	for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++)
241  		txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
242  
243  	/* 20 MHz Legacy OFDM CDD */
244  	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
245  		txpwr->ofdm_cdd[j] =
246  		    min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
247  
248  	/* 40 MHz Legacy OFDM SISO */
249  	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
250  		txpwr->ofdm_40_siso[j] =
251  		    min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
252  
253  	/* 40 MHz Legacy OFDM CDD */
254  	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
255  		txpwr->ofdm_40_cdd[j] =
256  		    min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
257  
258  	/* 20MHz MCS 0-7 SISO */
259  	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
260  		txpwr->mcs_20_siso[j] =
261  		    min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
262  
263  	/* 20MHz MCS 0-7 CDD */
264  	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
265  		txpwr->mcs_20_cdd[j] =
266  		    min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
267  
268  	/* 20MHz MCS 0-7 STBC */
269  	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
270  		txpwr->mcs_20_stbc[j] =
271  		    min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
272  
273  	/* 20MHz MCS 8-15 MIMO */
274  	for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
275  		txpwr->mcs_20_mimo[j] =
276  		    min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
277  
278  	/* 40MHz MCS 0-7 SISO */
279  	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
280  		txpwr->mcs_40_siso[j] =
281  		    min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
282  
283  	/* 40MHz MCS 0-7 CDD */
284  	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
285  		txpwr->mcs_40_cdd[j] =
286  		    min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
287  
288  	/* 40MHz MCS 0-7 STBC */
289  	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
290  		txpwr->mcs_40_stbc[j] =
291  		    min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
292  
293  	/* 40MHz MCS 8-15 MIMO */
294  	for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
295  		txpwr->mcs_40_mimo[j] =
296  		    min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
297  
298  	/* 40MHz MCS 32 */
299  	txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
300  
301  }
302  
303  /*
304   * set the driver's current country and regulatory information
305   * using a country code as the source. Look up built in country
306   * information found with the country code.
307   */
308  static void
brcms_c_set_country(struct brcms_cm_info * wlc_cm,const struct brcms_regd * regd)309  brcms_c_set_country(struct brcms_cm_info *wlc_cm,
310  		    const struct brcms_regd *regd)
311  {
312  	struct brcms_c_info *wlc = wlc_cm->wlc;
313  
314  	if ((wlc->pub->_n_enab & SUPPORT_11N) !=
315  	    wlc->protection->nmode_user)
316  		brcms_c_set_nmode(wlc);
317  
318  	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
319  	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
320  
321  	brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
322  
323  	return;
324  }
325  
brcms_c_channel_mgr_attach(struct brcms_c_info * wlc)326  struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
327  {
328  	struct brcms_cm_info *wlc_cm;
329  	struct brcms_pub *pub = wlc->pub;
330  	struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
331  	const char *ccode = sprom->alpha2;
332  	int ccode_len = sizeof(sprom->alpha2);
333  
334  	wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
335  	if (wlc_cm == NULL)
336  		return NULL;
337  	wlc_cm->pub = pub;
338  	wlc_cm->wlc = wlc;
339  	wlc->cmi = wlc_cm;
340  
341  	/* store the country code for passing up as a regulatory hint */
342  	wlc_cm->world_regd = brcms_world_regd(ccode, ccode_len);
343  	if (brcms_c_country_valid(ccode))
344  		strncpy(wlc->pub->srom_ccode, ccode, ccode_len);
345  
346  	/*
347  	 * If no custom world domain is found in the SROM, use the
348  	 * default "X2" domain.
349  	 */
350  	if (!wlc_cm->world_regd) {
351  		wlc_cm->world_regd = brcms_default_world_regd();
352  		ccode = wlc_cm->world_regd->regdomain->alpha2;
353  		ccode_len = BRCM_CNTRY_BUF_SZ - 1;
354  	}
355  
356  	/* save default country for exiting 11d regulatory mode */
357  	strncpy(wlc->country_default, ccode, ccode_len);
358  
359  	/* initialize autocountry_default to driver default */
360  	strncpy(wlc->autocountry_default, ccode, ccode_len);
361  
362  	brcms_c_set_country(wlc_cm, wlc_cm->world_regd);
363  
364  	return wlc_cm;
365  }
366  
brcms_c_channel_mgr_detach(struct brcms_cm_info * wlc_cm)367  void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
368  {
369  	kfree(wlc_cm);
370  }
371  
372  void
brcms_c_channel_set_chanspec(struct brcms_cm_info * wlc_cm,u16 chanspec,u8 local_constraint_qdbm)373  brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
374  			 u8 local_constraint_qdbm)
375  {
376  	struct brcms_c_info *wlc = wlc_cm->wlc;
377  	struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
378  	struct txpwr_limits txpwr;
379  
380  	brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
381  
382  	brcms_c_channel_min_txpower_limits_with_local_constraint(
383  		wlc_cm, &txpwr, local_constraint_qdbm
384  	);
385  
386  	/* set or restore gmode as required by regulatory */
387  	if (ch->flags & IEEE80211_CHAN_NO_OFDM)
388  		brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
389  	else
390  		brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
391  
392  	brcms_b_set_chanspec(wlc->hw, chanspec,
393  			      !!(ch->flags & IEEE80211_CHAN_NO_IR),
394  			      &txpwr);
395  }
396  
397  void
brcms_c_channel_reg_limits(struct brcms_cm_info * wlc_cm,u16 chanspec,struct txpwr_limits * txpwr)398  brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
399  		       struct txpwr_limits *txpwr)
400  {
401  	struct brcms_c_info *wlc = wlc_cm->wlc;
402  	struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
403  	uint i;
404  	uint chan;
405  	int maxpwr;
406  	int delta;
407  	const struct country_info *country;
408  	struct brcms_band *band;
409  	int conducted_max = BRCMS_TXPWR_MAX;
410  	const struct locale_mimo_info *li_mimo;
411  	int maxpwr20, maxpwr40;
412  	int maxpwr_idx;
413  	uint j;
414  
415  	memset(txpwr, 0, sizeof(struct txpwr_limits));
416  
417  	if (WARN_ON(!ch))
418  		return;
419  
420  	country = &wlc_cm->world_regd->country;
421  
422  	chan = CHSPEC_CHANNEL(chanspec);
423  	band = wlc->bandstate[chspec_bandunit(chanspec)];
424  	li_mimo = (band->bandtype == BRCM_BAND_5G) ?
425  	    brcms_c_get_mimo_5g(country->locale_mimo_5G) :
426  	    brcms_c_get_mimo_2g(country->locale_mimo_2G);
427  
428  	delta = band->antgain;
429  
430  	if (band->bandtype == BRCM_BAND_2G)
431  		conducted_max = QDB(22);
432  
433  	maxpwr = QDB(ch->max_power) - delta;
434  	maxpwr = max(maxpwr, 0);
435  	maxpwr = min(maxpwr, conducted_max);
436  
437  	/* CCK txpwr limits for 2.4G band */
438  	if (band->bandtype == BRCM_BAND_2G) {
439  		for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
440  			txpwr->cck[i] = (u8) maxpwr;
441  	}
442  
443  	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
444  		txpwr->ofdm[i] = (u8) maxpwr;
445  
446  		/*
447  		 * OFDM 40 MHz SISO has the same power as the corresponding
448  		 * MCS0-7 rate unless overriden by the locale specific code.
449  		 * We set this value to 0 as a flag (presumably 0 dBm isn't
450  		 * a possibility) and then copy the MCS0-7 value to the 40 MHz
451  		 * value if it wasn't explicitly set.
452  		 */
453  		txpwr->ofdm_40_siso[i] = 0;
454  
455  		txpwr->ofdm_cdd[i] = (u8) maxpwr;
456  
457  		txpwr->ofdm_40_cdd[i] = 0;
458  	}
459  
460  	delta = 0;
461  	if (band->antgain > QDB(6))
462  		delta = band->antgain - QDB(6);	/* Excess over 6 dB */
463  
464  	if (band->bandtype == BRCM_BAND_2G)
465  		maxpwr_idx = (chan - 1);
466  	else
467  		maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
468  
469  	maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
470  	maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
471  
472  	maxpwr20 = maxpwr20 - delta;
473  	maxpwr20 = max(maxpwr20, 0);
474  	maxpwr40 = maxpwr40 - delta;
475  	maxpwr40 = max(maxpwr40, 0);
476  
477  	/* Fill in the MCS 0-7 (SISO) rates */
478  	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
479  
480  		/*
481  		 * 20 MHz has the same power as the corresponding OFDM rate
482  		 * unless overriden by the locale specific code.
483  		 */
484  		txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
485  		txpwr->mcs_40_siso[i] = 0;
486  	}
487  
488  	/* Fill in the MCS 0-7 CDD rates */
489  	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
490  		txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
491  		txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
492  	}
493  
494  	/*
495  	 * These locales have SISO expressed in the
496  	 * table and override CDD later
497  	 */
498  	if (li_mimo == &locale_bn) {
499  		maxpwr20 = QDB(16);
500  		maxpwr40 = 0;
501  
502  		if (chan >= 3 && chan <= 11)
503  			maxpwr40 = QDB(16);
504  
505  		for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
506  			txpwr->mcs_20_siso[i] = (u8) maxpwr20;
507  			txpwr->mcs_40_siso[i] = (u8) maxpwr40;
508  		}
509  	}
510  
511  	/* Fill in the MCS 0-7 STBC rates */
512  	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
513  		txpwr->mcs_20_stbc[i] = 0;
514  		txpwr->mcs_40_stbc[i] = 0;
515  	}
516  
517  	/* Fill in the MCS 8-15 SDM rates */
518  	for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
519  		txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
520  		txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
521  	}
522  
523  	/* Fill in MCS32 */
524  	txpwr->mcs32 = (u8) maxpwr40;
525  
526  	for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
527  		if (txpwr->ofdm_40_cdd[i] == 0)
528  			txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
529  		if (i == 0) {
530  			i = i + 1;
531  			if (txpwr->ofdm_40_cdd[i] == 0)
532  				txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
533  		}
534  	}
535  
536  	/*
537  	 * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO
538  	 * value if it wasn't provided explicitly.
539  	 */
540  	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
541  		if (txpwr->mcs_40_siso[i] == 0)
542  			txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
543  	}
544  
545  	for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
546  		if (txpwr->ofdm_40_siso[i] == 0)
547  			txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
548  		if (i == 0) {
549  			i = i + 1;
550  			if (txpwr->ofdm_40_siso[i] == 0)
551  				txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
552  		}
553  	}
554  
555  	/*
556  	 * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding
557  	 * STBC values if they weren't provided explicitly.
558  	 */
559  	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
560  		if (txpwr->mcs_20_stbc[i] == 0)
561  			txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
562  
563  		if (txpwr->mcs_40_stbc[i] == 0)
564  			txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
565  	}
566  
567  	return;
568  }
569  
570  /*
571   * Verify the chanspec is using a legal set of parameters, i.e. that the
572   * chanspec specified a band, bw, ctl_sb and channel and that the
573   * combination could be legal given any set of circumstances.
574   * RETURNS: true is the chanspec is malformed, false if it looks good.
575   */
brcms_c_chspec_malformed(u16 chanspec)576  static bool brcms_c_chspec_malformed(u16 chanspec)
577  {
578  	/* must be 2G or 5G band */
579  	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
580  		return true;
581  	/* must be 20 or 40 bandwidth */
582  	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
583  		return true;
584  
585  	/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
586  	if (CHSPEC_IS20(chanspec)) {
587  		if (!CHSPEC_SB_NONE(chanspec))
588  			return true;
589  	} else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
590  		return true;
591  	}
592  
593  	return false;
594  }
595  
596  /*
597   * Validate the chanspec for this locale, for 40MHZ we need to also
598   * check that the sidebands are valid 20MZH channels in this locale
599   * and they are also a legal HT combination
600   */
601  static bool
brcms_c_valid_chanspec_ext(struct brcms_cm_info * wlc_cm,u16 chspec)602  brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec)
603  {
604  	struct brcms_c_info *wlc = wlc_cm->wlc;
605  	u8 channel = CHSPEC_CHANNEL(chspec);
606  
607  	/* check the chanspec */
608  	if (brcms_c_chspec_malformed(chspec)) {
609  		brcms_err(wlc->hw->d11core, "wl%d: malformed chanspec 0x%x\n",
610  			  wlc->pub->unit, chspec);
611  		return false;
612  	}
613  
614  	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
615  	    chspec_bandunit(chspec))
616  		return false;
617  
618  	return true;
619  }
620  
brcms_c_valid_chanspec_db(struct brcms_cm_info * wlc_cm,u16 chspec)621  bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
622  {
623  	return brcms_c_valid_chanspec_ext(wlc_cm, chspec);
624  }
625  
brcms_is_radar_freq(u16 center_freq)626  static bool brcms_is_radar_freq(u16 center_freq)
627  {
628  	return center_freq >= 5260 && center_freq <= 5700;
629  }
630  
brcms_reg_apply_radar_flags(struct wiphy * wiphy)631  static void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
632  {
633  	struct ieee80211_supported_band *sband;
634  	struct ieee80211_channel *ch;
635  	int i;
636  
637  	sband = wiphy->bands[NL80211_BAND_5GHZ];
638  	if (!sband)
639  		return;
640  
641  	for (i = 0; i < sband->n_channels; i++) {
642  		ch = &sband->channels[i];
643  
644  		if (!brcms_is_radar_freq(ch->center_freq))
645  			continue;
646  
647  		/*
648  		 * All channels in this range should be passive and have
649  		 * DFS enabled.
650  		 */
651  		if (!(ch->flags & IEEE80211_CHAN_DISABLED))
652  			ch->flags |= IEEE80211_CHAN_RADAR |
653  				     IEEE80211_CHAN_NO_IR;
654  	}
655  }
656  
657  static void
brcms_reg_apply_beaconing_flags(struct wiphy * wiphy,enum nl80211_reg_initiator initiator)658  brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
659  				enum nl80211_reg_initiator initiator)
660  {
661  	struct ieee80211_supported_band *sband;
662  	struct ieee80211_channel *ch;
663  	const struct ieee80211_reg_rule *rule;
664  	int band, i;
665  
666  	for (band = 0; band < NUM_NL80211_BANDS; band++) {
667  		sband = wiphy->bands[band];
668  		if (!sband)
669  			continue;
670  
671  		for (i = 0; i < sband->n_channels; i++) {
672  			ch = &sband->channels[i];
673  
674  			if (ch->flags &
675  			    (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR))
676  				continue;
677  
678  			if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
679  				rule = freq_reg_info(wiphy,
680  						     MHZ_TO_KHZ(ch->center_freq));
681  				if (IS_ERR(rule))
682  					continue;
683  
684  				if (!(rule->flags & NL80211_RRF_NO_IR))
685  					ch->flags &= ~IEEE80211_CHAN_NO_IR;
686  			} else if (ch->beacon_found) {
687  				ch->flags &= ~IEEE80211_CHAN_NO_IR;
688  			}
689  		}
690  	}
691  }
692  
brcms_reg_notifier(struct wiphy * wiphy,struct regulatory_request * request)693  static void brcms_reg_notifier(struct wiphy *wiphy,
694  			       struct regulatory_request *request)
695  {
696  	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
697  	struct brcms_info *wl = hw->priv;
698  	struct brcms_c_info *wlc = wl->wlc;
699  	struct ieee80211_supported_band *sband;
700  	struct ieee80211_channel *ch;
701  	int band, i;
702  	bool ch_found = false;
703  
704  	brcms_reg_apply_radar_flags(wiphy);
705  
706  	if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
707  		brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
708  
709  	/* Disable radio if all channels disallowed by regulatory */
710  	for (band = 0; !ch_found && band < NUM_NL80211_BANDS; band++) {
711  		sband = wiphy->bands[band];
712  		if (!sband)
713  			continue;
714  
715  		for (i = 0; !ch_found && i < sband->n_channels; i++) {
716  			ch = &sband->channels[i];
717  
718  			if (!(ch->flags & IEEE80211_CHAN_DISABLED))
719  				ch_found = true;
720  		}
721  	}
722  
723  	if (ch_found) {
724  		mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
725  	} else {
726  		mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
727  		brcms_err(wlc->hw->d11core,
728  			  "wl%d: %s: no valid channel for \"%s\"\n",
729  			  wlc->pub->unit, __func__, request->alpha2);
730  	}
731  
732  	if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
733  		wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
734  					brcms_c_japan_ccode(request->alpha2));
735  }
736  
brcms_c_regd_init(struct brcms_c_info * wlc)737  void brcms_c_regd_init(struct brcms_c_info *wlc)
738  {
739  	struct wiphy *wiphy = wlc->wiphy;
740  	const struct brcms_regd *regd = wlc->cmi->world_regd;
741  	struct ieee80211_supported_band *sband;
742  	struct ieee80211_channel *ch;
743  	struct brcms_chanvec sup_chan;
744  	struct brcms_band *band;
745  	int band_idx, i;
746  
747  	/* Disable any channels not supported by the phy */
748  	for (band_idx = 0; band_idx < wlc->pub->_nbands; band_idx++) {
749  		band = wlc->bandstate[band_idx];
750  
751  		wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
752  					      &sup_chan);
753  
754  		if (band_idx == BAND_2G_INDEX)
755  			sband = wiphy->bands[NL80211_BAND_2GHZ];
756  		else
757  			sband = wiphy->bands[NL80211_BAND_5GHZ];
758  
759  		for (i = 0; i < sband->n_channels; i++) {
760  			ch = &sband->channels[i];
761  			if (!isset(sup_chan.vec, ch->hw_value))
762  				ch->flags |= IEEE80211_CHAN_DISABLED;
763  		}
764  	}
765  
766  	wlc->wiphy->reg_notifier = brcms_reg_notifier;
767  	wlc->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
768  					REGULATORY_STRICT_REG;
769  	wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
770  	brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
771  }
772