[go: nahoru, domu]

channel.c revision cf03c5dac83609f09d9f0e9fa3c09d86daed614d
15b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
25b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * Copyright (c) 2010 Broadcom Corporation
35b435de0d786869c95d1962121af0d7df2542009Arend van Spriel *
45b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * Permission to use, copy, modify, and/or distribute this software for any
55b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * purpose with or without fee is hereby granted, provided that the above
65b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * copyright notice and this permission notice appear in all copies.
75b435de0d786869c95d1962121af0d7df2542009Arend van Spriel *
85b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
95b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
105b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
125b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
145b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
155b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
165b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
175b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#include <linux/types.h>
18cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee#include <net/cfg80211.h>
195b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#include <net/mac80211.h>
20cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee#include <net/regulatory.h>
215b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
225b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#include <defs.h>
235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#include "pub.h"
245b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#include "phy/phy_hal.h"
255b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#include "main.h"
265b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#include "stf.h"
275b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#include "channel.h"
28cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee#include "mac80211_if.h"
295b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
305b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* QDB() macro takes a dB value and converts to a quarter dB value */
315b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_01_11	 (1<<0)
345b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_12_13	 (1<<1)
355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_14		 (1<<2)
365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_LOW_JP1   (1<<3)	/* 34-48, step 2 */
375b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_LOW_JP2   (1<<4)	/* 34-46, step 4 */
385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_LOW1      (1<<5)	/* 36-48, step 4 */
395b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_LOW2      (1<<6)	/* 52 */
405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_LOW3      (1<<7)	/* 56-64, step 4 */
415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_MID1      (1<<8)	/* 100-116, step 4 */
425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_MID2	 (1<<9)	/* 120-124, step 4 */
435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_MID3      (1<<10)	/* 128 */
445b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_HIGH1     (1<<11)	/* 132-140, step 4 */
455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_HIGH2     (1<<12)	/* 149-161, step 4 */
465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_HIGH3     (1<<13)	/* 165 */
475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_52_140_ALL  (1<<14)
485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_SET_5G_HIGH4     (1<<15)	/* 184-216 */
495b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_36_64	(LOCALE_SET_5G_LOW1 | \
515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				 LOCALE_SET_5G_LOW2 | \
525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				 LOCALE_SET_5G_LOW3)
535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_52_64	(LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_100_124	(LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_100_140	(LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \
565b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				  LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_149_165	(LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_184_216	LOCALE_SET_5G_HIGH4
595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_CHAN_01_14	(LOCALE_CHAN_01_11 | \
615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				 LOCALE_CHAN_12_13 | \
625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				 LOCALE_CHAN_14)
635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_RESTRICTED_NONE		  0
655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define  LOCALE_RESTRICTED_SET_2G_SHORT   1
665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define LOCALE_2G_IDX_i			0
685b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define LOCALE_5G_IDX_11		0
695b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define LOCALE_MIMO_IDX_bn		0
705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define LOCALE_MIMO_IDX_11n		0
715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define BRCMS_MAXPWR_TBL_SIZE		6
745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define BRCMS_MAXPWR_MIMO_TBL_SIZE	14
765b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
775b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* power level in group of 2.4GHz band channels:
785b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[0] - CCK  channels [1]
795b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[1] - CCK  channels [2-10]
805b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[2] - CCK  channels [11-14]
815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[3] - OFDM channels [1]
825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[4] - OFDM channels [2-10]
835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[5] - OFDM channels [11-14]
845b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* maxpwr mapping to 5GHz band channels:
875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[0] - channels [34-48]
885b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[1] - channels [52-60]
895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[2] - channels [62-64]
905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[3] - channels [100-140]
915b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * maxpwr[4] - channels [149-165]
925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
935b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define BAND_5G_PWR_LVLS	5	/* 5 power levels for 5G */
945b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
955b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define LC(id)	LOCALE_MIMO_IDX_ ## id
965b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
975b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define LC_2G(id)	LOCALE_2G_IDX_ ## id
985b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
995b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define LC_5G(id)	LOCALE_5G_IDX_ ## id
1005b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
1015b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define LOCALES(band2, band5, mimo2, mimo5) \
1025b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		{LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
1035b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
1045b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* macro to get 2.4 GHz channel group index for tx power */
1055b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))
1065b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))
1075b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
1085b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* macro to get 5 GHz channel group index for tx power */
1095b435de0d786869c95d1962121af0d7df2542009Arend van Spriel#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
1105b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				 (((c) < 62) ? 1 : \
1115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				 (((c) < 100) ? 2 : \
1125b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				 (((c) < 149) ? 3 : 4))))
1135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
114cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee#define BRCM_2GHZ_2412_2462	REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
115cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee#define BRCM_2GHZ_2467_2472	REG_RULE(2467-10, 2472+10, 20, 0, 19, \
116cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_PASSIVE_SCAN | \
117cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_NO_IBSS)
118cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
119cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee#define BRCM_5GHZ_5180_5240	REG_RULE(5180-10, 5240+10, 40, 0, 21, \
120cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_PASSIVE_SCAN | \
121cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_NO_IBSS)
122cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee#define BRCM_5GHZ_5260_5320	REG_RULE(5260-10, 5320+10, 40, 0, 21, \
123cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_PASSIVE_SCAN | \
124cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_DFS | \
125cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_NO_IBSS)
126cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee#define BRCM_5GHZ_5500_5700	REG_RULE(5500-10, 5700+10, 40, 0, 21, \
127cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_PASSIVE_SCAN | \
128cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_DFS | \
129cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_NO_IBSS)
130cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee#define BRCM_5GHZ_5745_5825	REG_RULE(5745-10, 5825+10, 40, 0, 21, \
131cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_PASSIVE_SCAN | \
132cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					 NL80211_RRF_NO_IBSS)
133cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
134cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheestatic const struct ieee80211_regdomain brcms_regdom_x2 = {
135cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	.n_reg_rules = 7,
136cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	.alpha2 = "X2",
137cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	.reg_rules = {
138cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		BRCM_2GHZ_2412_2462,
139cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		BRCM_2GHZ_2467_2472,
140cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		BRCM_5GHZ_5180_5240,
141cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		BRCM_5GHZ_5260_5320,
142cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		BRCM_5GHZ_5500_5700,
143cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		BRCM_5GHZ_5745_5825,
144cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	}
145cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee};
146cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1475b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstruct brcms_cm_band {
1485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* struct locale_info flags */
1495b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	u8 locale_flags;
1505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* List of valid channels in the country */
1515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_chanvec valid_channels;
1525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* List of restricted use channels */
1535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const struct brcms_chanvec *restricted_channels;
1545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
1555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
1565b435de0d786869c95d1962121af0d7df2542009Arend van Spriel /* locale per-channel tx power limits for MIMO frames
1575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel  * maxpwr arrays are index by channel for 2.4 GHz limits, and
1585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel  * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
1595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel  */
1605b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstruct locale_mimo_info {
1615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* tx 20 MHz power limits, qdBm units */
1625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
1635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* tx 40 MHz power limits, qdBm units */
1645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
1655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	u8 flags;
1665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
1675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
1685b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* Country names and abbreviations with locale defined from ISO 3166 */
1695b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstruct country_info {
1705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const u8 locale_2G;	/* 2.4G band locale */
1715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const u8 locale_5G;	/* 5G band locale */
1725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const u8 locale_mimo_2G;	/* 2.4G mimo info */
1735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const u8 locale_mimo_5G;	/* 5G mimo info */
1745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
1755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
176cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheestruct brcms_regd {
177cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct country_info country;
178cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	const struct ieee80211_regdomain *regdomain;
179cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee};
180cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1815b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstruct brcms_cm_info {
1825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_pub *pub;
1835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc;
184cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	const struct brcms_regd *world_regd;
1855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* per-band state (one per phy/radio) */
1865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_cm_band bandstate[MAXBANDS];
1875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* quiet channels currently for radar sensitivity or 11h support */
1885b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* channels on which we cannot transmit */
1895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_chanvec quiet_channels;
1905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
1915b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
1925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* locale channel and power info. */
1935b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstruct locale_info {
1945b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	u32 valid_channels;
1955b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* List of channels used only if APs are detected */
1965b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	u8 restricted_channels;
1975b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* Max tx pwr in qdBm for each sub-band */
1985b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
1995b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	u8 flags;
2005b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2015b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2025b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
2035b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2045b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
2055b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * Some common channel sets
2065b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
2075b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2085b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* No channels */
2095b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec chanvec_none = {
2105b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2125b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2145b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2155b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2165b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
2175b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * Restricted channel sets
2185b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
2195b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2205b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* Channels 12, 13 */
2215b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec restricted_set_2g_short = {
2225b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2245b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2255b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2265b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2275b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2285b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* global memory to provide working buffer for expanded locale */
2295b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2305b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec *g_table_restricted_chan[] = {
2315b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&chanvec_none,		/* restricted_set_none */
2325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&restricted_set_2g_short,
2335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2345b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2355b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_2g_01_11 = {
2365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2375b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2395b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2425b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_2g_12_13 = {
2435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2445b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2495b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_2g_14 = {
2505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2565b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_LOW_JP1 = {
2575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
2585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2635b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_LOW_JP2 = {
2645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
2655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2685b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2695b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2705b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_LOW1 = {
2715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
2725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2765b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2775b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_LOW2 = {
2785b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
2795b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2805b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2845b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_LOW3 = {
2855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
2865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2885b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2915b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_MID1 = {
2925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2935b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
2945b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2955b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
2965b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
2975b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
2985b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_MID2 = {
2995b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3005b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
3015b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3025b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
3035b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
3045b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3055b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_MID3 = {
3065b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3075b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3085b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3095b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
3105b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
3115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3125b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_HIGH1 = {
3135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3145b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3155b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3165b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
3175b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
3185b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3195b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_HIGH2 = {
3205b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3215b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3225b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
3235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
3245b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
3255b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3265b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_HIGH3 = {
3275b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3285b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3295b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
3305b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
3315b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
3325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3335b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_52_140_ALL = {
3345b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
3355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
3365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
3375b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00}
3385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
3395b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3405b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec locale_5g_HIGH4 = {
3415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
3445b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 0x11, 0x11, 0x11, 0x11}
3455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
3465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3475b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct brcms_chanvec *g_table_locale_base[] = {
3485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_2g_01_11,
3495b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_2g_12_13,
3505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_2g_14,
3515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_LOW_JP1,
3525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_LOW_JP2,
3535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_LOW1,
3545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_LOW2,
3555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_LOW3,
3565b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_MID1,
3575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_MID2,
3585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_MID3,
3595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_HIGH1,
3605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_HIGH2,
3615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_HIGH3,
3625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_52_140_ALL,
3635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_5g_HIGH4
3645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
3655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3665b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic void brcms_c_locale_add_channels(struct brcms_chanvec *target,
3675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				    const struct brcms_chanvec *channels)
3685b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
3695b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	u8 i;
3705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < sizeof(struct brcms_chanvec); i++)
3715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		target->vec[i] |= channels->vec[i];
3725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
3735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3745b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic void brcms_c_locale_get_channels(const struct locale_info *locale,
3755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				    struct brcms_chanvec *channels)
3765b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
3775b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	u8 i;
3785b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3795b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	memset(channels, 0, sizeof(struct brcms_chanvec));
3805b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
3825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (locale->valid_channels & (1 << i))
3835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			brcms_c_locale_add_channels(channels,
3845b435de0d786869c95d1962121af0d7df2542009Arend van Spriel						g_table_locale_base[i]);
3855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
3865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
3875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3885b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
3895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * Locale Definitions - 2.4 GHz
3905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
3915b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_info locale_i = {	/* locale i. channel 1 - 13 */
3925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
3935b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	LOCALE_RESTRICTED_SET_2G_SHORT,
3945b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{QDB(19), QDB(19), QDB(19),
3955b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 QDB(19), QDB(19), QDB(19)},
3965b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	BRCMS_EIRP
3975b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
3985b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
3995b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
4005b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * Locale Definitions - 5 GHz
4015b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
4025b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_info locale_11 = {
4035b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
4045b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
4055b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	LOCALE_RESTRICTED_NONE,
4065b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)},
4075b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	BRCMS_EIRP | BRCMS_DFS_EU
4085b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
4095b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4105b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_info *g_locale_2g_table[] = {
4115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_i
4125b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
4135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4145b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_info *g_locale_5g_table[] = {
4155b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_11
4165b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
4175b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4185b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
4195b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * MIMO Locale Definitions - 2.4 GHz
4205b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
4215b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_mimo_info locale_bn = {
4225b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
4235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
4245b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 QDB(13), QDB(13), QDB(13)},
4255b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{0, 0, QDB(13), QDB(13), QDB(13),
4265b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
4275b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 QDB(13), 0, 0},
4285b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	0
4295b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
4305b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4315b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_mimo_info *g_mimo_2g_table[] = {
4325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_bn
4335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
4345b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
4365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * MIMO Locale Definitions - 5 GHz
4375b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
4385b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_mimo_info locale_11n = {
4395b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
4405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
4415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	0
4425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
4435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4445b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_mimo_info *g_mimo_5g_table[] = {
4455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	&locale_11n
4465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
4475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
448cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheestatic const struct brcms_regd cntry_locales[] = {
449cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	/* Worldwide RoW 2, must always be at index 0 */
4505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	{
451cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		.country = LOCALES(i, 11, bn, 11n),
452cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		.regdomain = &brcms_regdom_x2,
453cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	},
4545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel};
4555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4565b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
4575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
4585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (locale_idx >= ARRAY_SIZE(g_locale_2g_table))
4595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		return NULL; /* error condition */
4605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return g_locale_2g_table[locale_idx];
4625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
4635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4645b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx)
4655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
4665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (locale_idx >= ARRAY_SIZE(g_locale_5g_table))
4675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		return NULL; /* error condition */
4685b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4695b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return g_locale_5g_table[locale_idx];
4705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
4715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4725b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
4735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
4745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
4755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		return NULL;
4765b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4775b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return g_mimo_2g_table[locale_idx];
4785b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
4795b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4805b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
4815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
4825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table))
4835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		return NULL;
4845b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
4855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return g_mimo_5g_table[locale_idx];
4865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
4875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
48894a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel/*
48994a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel * Indicates whether the country provided is valid to pass
49094a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel * to cfg80211 or not.
49194a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel *
49294a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel * returns true if valid; false if not.
49394a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel */
49494a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Sprielstatic bool brcms_c_country_valid(const char *ccode)
49594a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel{
49694a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	/*
49794a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	 * only allow ascii alpha uppercase for the first 2
49894a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	 * chars.
49994a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	 */
50094a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	if (!((0x80 & ccode[0]) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
50194a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	      (0x80 & ccode[1]) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A &&
50294a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	      ccode[2] == '\0'))
50394a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel		return false;
50494a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel
50594a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	/*
50694a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	 * do not match ISO 3166-1 user assigned country codes
50794a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	 * that may be in the driver table
50894a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	 */
50994a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	if (!strcmp("AA", ccode) ||        /* AA */
51094a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	    !strcmp("ZZ", ccode) ||        /* ZZ */
51194a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	    ccode[0] == 'X' ||             /* XA - XZ */
51294a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	    (ccode[0] == 'Q' &&            /* QM - QZ */
51394a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	     (ccode[1] >= 'M' && ccode[1] <= 'Z')))
51494a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel		return false;
51594a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel
51694a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	if (!strcmp("NA", ccode))
51794a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel		return false;
51894a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel
51994a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel	return true;
52094a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel}
52194a2ca311cf4154c566cf5c49b88c13cd4cdce73Arend van Spriel
522cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheestatic const struct brcms_regd *brcms_world_regd(const char *regdom, int len)
5235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
524cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	const struct brcms_regd *regd = NULL;
525cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	int i;
5265b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
527cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) {
528cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		if (!strncmp(regdom, cntry_locales[i].regdomain->alpha2, len)) {
529cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			regd = &cntry_locales[i];
530cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			break;
531cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		}
5325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
5335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
534cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	return regd;
5355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
5365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
537cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheestatic const struct brcms_regd *brcms_default_world_regd(void)
5385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
539cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	return &cntry_locales[0];
5405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
5415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
5435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * reset the quiet channels vector to the union
5445b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * of the restricted and radar channel sets
5455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
5465b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm)
5475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
5485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc = wlc_cm->wlc;
5495b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	uint i, j;
5505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_band *band;
5515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const struct brcms_chanvec *chanvec;
5525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec));
5545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	band = wlc->band;
5565b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < wlc->pub->_nbands;
5575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
5585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		/* initialize quiet channels for restricted channels */
5605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
5615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		for (j = 0; j < sizeof(struct brcms_chanvec); j++)
5625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
5635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
5655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
5665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* Is the channel valid for the current locale and current band? */
5685b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val)
5695b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
5705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc = wlc_cm->wlc;
5715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return ((val < MAXCHANNEL) &&
5735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
5745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		      val));
5755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
5765b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5775b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* Is the channel valid for the current locale and specified band? */
5785b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
5795b435de0d786869c95d1962121af0d7df2542009Arend van Spriel					    uint bandunit, uint val)
5805b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
5815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return ((val < MAXCHANNEL)
5825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		&& isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
5835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
5845b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* Is the channel valid for the current locale? (but don't consider channels not
5865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel *   available due to bandlocking)
5875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
5885b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val)
5895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
5905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc = wlc_cm->wlc;
5915b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return brcms_c_valid_channel20(wlc->cmi, val) ||
5935b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		(!wlc->bandlocked
5945b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 && brcms_c_valid_channel20_in_band(wlc->cmi,
5955b435de0d786869c95d1962121af0d7df2542009Arend van Spriel						    OTHERBANDUNIT(wlc), val));
5965b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
5975b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
5985b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* JP, J1 - J10 are Japan ccodes */
5995b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic bool brcms_c_japan_ccode(const char *ccode)
6005b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
6015b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return (ccode[0] == 'J' &&
6025b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
6035b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
6045b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6055b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic void
6065b435de0d786869c95d1962121af0d7df2542009Arend van Sprielbrcms_c_channel_min_txpower_limits_with_local_constraint(
6075b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
6085b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		u8 local_constraint_qdbm)
6095b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
6105b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	int j;
6115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6125b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* CCK Rates */
6135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < WL_TX_POWER_CCK_NUM; j++)
6145b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
6155b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6165b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 20 MHz Legacy OFDM SISO */
6175b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++)
6185b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
6195b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6205b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 20 MHz Legacy OFDM CDD */
6215b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
6225b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->ofdm_cdd[j] =
6235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
6245b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6255b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 40 MHz Legacy OFDM SISO */
6265b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
6275b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->ofdm_40_siso[j] =
6285b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
6295b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6305b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 40 MHz Legacy OFDM CDD */
6315b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
6325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->ofdm_40_cdd[j] =
6335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
6345b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 20MHz MCS 0-7 SISO */
6365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
6375b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_20_siso[j] =
6385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
6395b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 20MHz MCS 0-7 CDD */
6415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
6425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_20_cdd[j] =
6435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
6445b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 20MHz MCS 0-7 STBC */
6465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
6475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_20_stbc[j] =
6485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
6495b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 20MHz MCS 8-15 MIMO */
6515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
6525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_20_mimo[j] =
6535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
6545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 40MHz MCS 0-7 SISO */
6565b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
6575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_40_siso[j] =
6585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
6595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 40MHz MCS 0-7 CDD */
6615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
6625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_40_cdd[j] =
6635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
6645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 40MHz MCS 0-7 STBC */
6665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
6675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_40_stbc[j] =
6685b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
6695b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 40MHz MCS 8-15 MIMO */
6715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
6725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_40_mimo[j] =
6735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
6745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* 40MHz MCS 32 */
6765b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
6775b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6785b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
6795b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6805b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/* Update the radio state (enable/disable) and tx power targets
6815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * based on a new set of channel/regulatory information
6825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
6835b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
6845b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
6855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc = wlc_cm->wlc;
6865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	uint chan;
6875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6885b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* search for the existence of any valid channel */
6895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (chan = 0; chan < MAXCHANNEL; chan++) {
6905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (brcms_c_valid_channel20_db(wlc->cmi, chan))
6915b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			break;
6925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
6935b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (chan == MAXCHANNEL)
6945b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		chan = INVCHANNEL;
6955b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
6965b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/*
6975b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 * based on the channel search above, set or
6985b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 * clear WL_RADIO_COUNTRY_DISABLE.
6995b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 */
7005b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (chan == INVCHANNEL) {
7015b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		/*
7025b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * country/locale with no valid channels, set
7035b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * the radio disable bit
7045b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 */
7055b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
7065b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
7075b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			  "nbands %d bandlocked %d\n", wlc->pub->unit,
708cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			  __func__, wlc_cm->world_regd->regdomain->alpha2,
709cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			  wlc->pub->_nbands, wlc->bandlocked);
7105b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	} else if (mboolisset(wlc->pub->radio_disabled,
7115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			      WL_RADIO_COUNTRY_DISABLE)) {
7125b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		/*
7135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * country/locale with valid channel, clear
7145b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * the radio disable bit
7155b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 */
7165b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
7175b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
7185b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
7195b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7205b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic int
7215b435de0d786869c95d1962121af0d7df2542009Arend van Sprielbrcms_c_channels_init(struct brcms_cm_info *wlc_cm,
7225b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		      const struct country_info *country)
7235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
7245b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc = wlc_cm->wlc;
7255b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	uint i, j;
7265b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_band *band;
7275b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const struct locale_info *li;
7285b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_chanvec sup_chan;
7295b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const struct locale_mimo_info *li_mimo;
7305b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7315b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	band = wlc->band;
7325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < wlc->pub->_nbands;
7335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
7345b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		li = (band->bandtype == BRCM_BAND_5G) ?
7365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    brcms_c_get_locale_5g(country->locale_5G) :
7375b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    brcms_c_get_locale_2g(country->locale_2G);
7385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
7395b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		li_mimo = (band->bandtype == BRCM_BAND_5G) ?
7405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    brcms_c_get_mimo_5g(country->locale_mimo_5G) :
7415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    brcms_c_get_mimo_2g(country->locale_mimo_2G);
7425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		/* merge the mimo non-mimo locale flags */
7445b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		wlc_cm->bandstate[band->bandunit].locale_flags |=
7455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    li_mimo->flags;
7465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		wlc_cm->bandstate[band->bandunit].restricted_channels =
7485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		    g_table_restricted_chan[li->restricted_channels];
7495b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		/*
7515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * set the channel availability, masking out the channels
7525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * that may not be supported on this phy.
7535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 */
7545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
7555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel					      &sup_chan);
7565b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		brcms_c_locale_get_channels(li,
7575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel					&wlc_cm->bandstate[band->bandunit].
7585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel					valid_channels);
7595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		for (j = 0; j < sizeof(struct brcms_chanvec); j++)
7605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			wlc_cm->bandstate[band->bandunit].valid_channels.
7615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			    vec[j] &= sup_chan.vec[j];
7625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
7635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	brcms_c_quiet_channels_reset(wlc_cm);
7655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	brcms_c_channels_commit(wlc_cm);
7665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return 0;
7685b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
7695b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
7715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * set the driver's current country and regulatory information
7725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * using a country code as the source. Look up built in country
7735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * information found with the country code.
7745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
7755b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic void
776cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheebrcms_c_set_country(struct brcms_cm_info *wlc_cm,
777cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		    const struct brcms_regd *regd)
7785b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
779cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	const struct country_info *country = &regd->country;
7805b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const struct locale_info *locale;
7815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc = wlc_cm->wlc;
7825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if ((wlc->pub->_n_enab & SUPPORT_11N) !=
7845b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	    wlc->protection->nmode_user)
7855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		brcms_c_set_nmode(wlc);
7865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
7885b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
7895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* set or restore gmode as required by regulatory */
7905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	locale = brcms_c_get_locale_2g(country->locale_2G);
7915b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (locale && (locale->flags & BRCMS_NO_OFDM))
7925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
7935b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	else
7945b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
7955b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7965b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	brcms_c_channels_init(wlc_cm, country);
7975b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
7985b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return;
7995b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
8005b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8015b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstruct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
8025b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
8035b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_cm_info *wlc_cm;
8045b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_pub *pub = wlc->pub;
805898d3c3b2462cd439edb575f43b732425693aff0Hauke Mehrtens	struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
806cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	const char *ccode = sprom->alpha2;
807cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	int ccode_len = sizeof(sprom->alpha2);
8085b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8095b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
8105b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
8125b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (wlc_cm == NULL)
8135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		return NULL;
8145b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	wlc_cm->pub = pub;
8155b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	wlc_cm->wlc = wlc;
8165b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	wlc->cmi = wlc_cm;
8175b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8185b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* store the country code for passing up as a regulatory hint */
819cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	wlc_cm->world_regd = brcms_world_regd(ccode, ccode_len);
820cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	if (brcms_c_country_valid(ccode))
821cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		strncpy(wlc->pub->srom_ccode, ccode, ccode_len);
822cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
823cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	/*
824cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	 * If no custom world domain is found in the SROM, use the
825cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	 * default "X2" domain.
826cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	 */
827cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	if (!wlc_cm->world_regd) {
828cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		wlc_cm->world_regd = brcms_default_world_regd();
829cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		ccode = wlc_cm->world_regd->regdomain->alpha2;
830cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		ccode_len = BRCM_CNTRY_BUF_SZ - 1;
831cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	}
8325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* save default country for exiting 11d regulatory mode */
834cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	strncpy(wlc->country_default, ccode, ccode_len);
8355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* initialize autocountry_default to driver default */
837cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	strncpy(wlc->autocountry_default, ccode, ccode_len);
8385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
839cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	brcms_c_set_country(wlc_cm, wlc_cm->world_regd);
8405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return wlc_cm;
8425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
8435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8445b435de0d786869c95d1962121af0d7df2542009Arend van Sprielvoid brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
8455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
8465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	kfree(wlc_cm);
8475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
8485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8495b435de0d786869c95d1962121af0d7df2542009Arend van Sprielu8
8505b435de0d786869c95d1962121af0d7df2542009Arend van Sprielbrcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
8515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				     uint bandunit)
8525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
8535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return wlc_cm->bandstate[bandunit].locale_flags;
8545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
8555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8565b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic bool
8575b435de0d786869c95d1962121af0d7df2542009Arend van Sprielbrcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec)
8585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
8595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) &&
8605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		CHSPEC_IS40(chspec) ?
8615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		(isset(wlc_cm->quiet_channels.vec,
8625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		       lower_20_sb(CHSPEC_CHANNEL(chspec))) ||
8635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 isset(wlc_cm->quiet_channels.vec,
8645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		       upper_20_sb(CHSPEC_CHANNEL(chspec)))) :
8655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec));
8665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
8675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8685b435de0d786869c95d1962121af0d7df2542009Arend van Sprielvoid
8695b435de0d786869c95d1962121af0d7df2542009Arend van Sprielbrcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
8705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			 u8 local_constraint_qdbm)
8715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
8725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc = wlc_cm->wlc;
8735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct txpwr_limits txpwr;
8745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
8765b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8775b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	brcms_c_channel_min_txpower_limits_with_local_constraint(
8785b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		wlc_cm, &txpwr, local_constraint_qdbm
8795b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	);
8805b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	brcms_b_set_chanspec(wlc->hw, chanspec,
8825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			      (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0),
8835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			      &txpwr);
8845b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
8855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
8865b435de0d786869c95d1962121af0d7df2542009Arend van Sprielvoid
8875b435de0d786869c95d1962121af0d7df2542009Arend van Sprielbrcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
8885b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		       struct txpwr_limits *txpwr)
8895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
8905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc = wlc_cm->wlc;
8915b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	uint i;
8925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	uint chan;
8935b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	int maxpwr;
8945b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	int delta;
8955b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const struct country_info *country;
8965b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_band *band;
8975b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const struct locale_info *li;
8985b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	int conducted_max = BRCMS_TXPWR_MAX;
8995b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	int conducted_ofdm_max = BRCMS_TXPWR_MAX;
9005b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	const struct locale_mimo_info *li_mimo;
9015b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	int maxpwr20, maxpwr40;
9025b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	int maxpwr_idx;
9035b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	uint j;
9045b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9055b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	memset(txpwr, 0, sizeof(struct txpwr_limits));
9065b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
907cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	country = &wlc_cm->world_regd->country;
9085b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9095b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	chan = CHSPEC_CHANNEL(chanspec);
9105b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	band = wlc->bandstate[chspec_bandunit(chanspec)];
9115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	li = (band->bandtype == BRCM_BAND_5G) ?
9125b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	    brcms_c_get_locale_5g(country->locale_5G) :
9135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	    brcms_c_get_locale_2g(country->locale_2G);
9145b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9155b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	li_mimo = (band->bandtype == BRCM_BAND_5G) ?
9165b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	    brcms_c_get_mimo_5g(country->locale_mimo_5G) :
9175b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	    brcms_c_get_mimo_2g(country->locale_mimo_2G);
9185b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9195b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (li->flags & BRCMS_EIRP) {
9205b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		delta = band->antgain;
9215b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	} else {
9225b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		delta = 0;
9235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (band->antgain > QDB(6))
9245b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
9255b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
9265b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9275b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (li == &locale_i) {
9285b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		conducted_max = QDB(22);
9295b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		conducted_ofdm_max = QDB(22);
9305b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
9315b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* CCK txpwr limits for 2.4G band */
9335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (band->bandtype == BRCM_BAND_2G) {
9345b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
9355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		maxpwr = maxpwr - delta;
9375b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		maxpwr = max(maxpwr, 0);
9385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		maxpwr = min(maxpwr, conducted_max);
9395b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
9415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			txpwr->cck[i] = (u8) maxpwr;
9425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
9435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9445b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* OFDM txpwr limits for 2.4G or 5G bands */
9455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (band->bandtype == BRCM_BAND_2G)
9465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
9475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	else
9485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
9495b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	maxpwr = maxpwr - delta;
9515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	maxpwr = max(maxpwr, 0);
9525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	maxpwr = min(maxpwr, conducted_ofdm_max);
9535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* Keep OFDM lmit below CCK limit */
9555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (band->bandtype == BRCM_BAND_2G)
9565b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
9575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
9595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->ofdm[i] = (u8) maxpwr;
9605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
9625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		/*
9635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * OFDM 40 MHz SISO has the same power as the corresponding
9645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * MCS0-7 rate unless overriden by the locale specific code.
9655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * We set this value to 0 as a flag (presumably 0 dBm isn't
9665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * a possibility) and then copy the MCS0-7 value to the 40 MHz
9675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * value if it wasn't explicitly set.
9685b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 */
9695b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->ofdm_40_siso[i] = 0;
9705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->ofdm_cdd[i] = (u8) maxpwr;
9725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->ofdm_40_cdd[i] = 0;
9745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
9755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9765b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* MIMO/HT specific limits */
9775b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (li_mimo->flags & BRCMS_EIRP) {
9785b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		delta = band->antgain;
9795b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	} else {
9805b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		delta = 0;
9815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (band->antgain > QDB(6))
9825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
9835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
9845b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (band->bandtype == BRCM_BAND_2G)
9865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		maxpwr_idx = (chan - 1);
9875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	else
9885b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
9895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
9915b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
9925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9935b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	maxpwr20 = maxpwr20 - delta;
9945b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	maxpwr20 = max(maxpwr20, 0);
9955b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	maxpwr40 = maxpwr40 - delta;
9965b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	maxpwr40 = max(maxpwr40, 0);
9975b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
9985b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* Fill in the MCS 0-7 (SISO) rates */
9995b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
10005b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10015b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		/*
10025b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * 20 MHz has the same power as the corresponding OFDM rate
10035b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 * unless overriden by the locale specific code.
10045b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		 */
10055b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
10065b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_40_siso[i] = 0;
10075b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
10085b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10095b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* Fill in the MCS 0-7 CDD rates */
10105b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
10115b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
10125b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
10135b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
10145b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10155b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/*
10165b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 * These locales have SISO expressed in the
10175b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 * table and override CDD later
10185b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 */
10195b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (li_mimo == &locale_bn) {
10205b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (li_mimo == &locale_bn) {
10215b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			maxpwr20 = QDB(16);
10225b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			maxpwr40 = 0;
10235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10245b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			if (chan >= 3 && chan <= 11)
10255b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				maxpwr40 = QDB(16);
10265b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		}
10275b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10285b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
10295b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			txpwr->mcs_20_siso[i] = (u8) maxpwr20;
10305b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			txpwr->mcs_40_siso[i] = (u8) maxpwr40;
10315b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		}
10325b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
10335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10345b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* Fill in the MCS 0-7 STBC rates */
10355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
10365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_20_stbc[i] = 0;
10375b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_40_stbc[i] = 0;
10385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
10395b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* Fill in the MCS 8-15 SDM rates */
10415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
10425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
10435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
10445b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
10455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* Fill in MCS32 */
10475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	txpwr->mcs32 = (u8) maxpwr40;
10485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10495b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
10505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (txpwr->ofdm_40_cdd[i] == 0)
10515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
10525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (i == 0) {
10535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			i = i + 1;
10545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			if (txpwr->ofdm_40_cdd[i] == 0)
10555b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
10565b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		}
10575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
10585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10595b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/*
10605b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO
10615b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 * value if it wasn't provided explicitly.
10625b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 */
10635b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
10645b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (txpwr->mcs_40_siso[i] == 0)
10655b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
10665b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
10675b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10685b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
10695b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (txpwr->ofdm_40_siso[i] == 0)
10705b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
10715b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (i == 0) {
10725b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			i = i + 1;
10735b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			if (txpwr->ofdm_40_siso[i] == 0)
10745b435de0d786869c95d1962121af0d7df2542009Arend van Spriel				txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
10755b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		}
10765b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
10775b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10785b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/*
10795b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding
10805b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 * STBC values if they weren't provided explicitly.
10815b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	 */
10825b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
10835b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (txpwr->mcs_20_stbc[i] == 0)
10845b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
10855b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10865b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (txpwr->mcs_40_stbc[i] == 0)
10875b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
10885b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
10895b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10905b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return;
10915b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
10925b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
10935b435de0d786869c95d1962121af0d7df2542009Arend van Spriel/*
10943de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers * Verify the chanspec is using a legal set of parameters, i.e. that the
10953de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers * chanspec specified a band, bw, ctl_sb and channel and that the
10963de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers * combination could be legal given any set of circumstances.
10973de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers * RETURNS: true is the chanspec is malformed, false if it looks good.
10983de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers */
10993de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukersstatic bool brcms_c_chspec_malformed(u16 chanspec)
11003de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers{
11013de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	/* must be 2G or 5G band */
11023de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
11033de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers		return true;
11043de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	/* must be 20 or 40 bandwidth */
11053de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
11063de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers		return true;
11073de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers
11083de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
11093de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	if (CHSPEC_IS20(chanspec)) {
11103de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers		if (!CHSPEC_SB_NONE(chanspec))
11113de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers			return true;
11123de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	} else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
11133de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers		return true;
11143de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	}
11153de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers
11163de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	return false;
11173de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers}
11183de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers
11193de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers/*
11205b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * Validate the chanspec for this locale, for 40MHZ we need to also
11215b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * check that the sidebands are valid 20MZH channels in this locale
11225b435de0d786869c95d1962121af0d7df2542009Arend van Spriel * and they are also a legal HT combination
11235b435de0d786869c95d1962121af0d7df2542009Arend van Spriel */
11245b435de0d786869c95d1962121af0d7df2542009Arend van Sprielstatic bool
11255b435de0d786869c95d1962121af0d7df2542009Arend van Sprielbrcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
11265b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			   bool dualband)
11275b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
11285b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	struct brcms_c_info *wlc = wlc_cm->wlc;
11295b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	u8 channel = CHSPEC_CHANNEL(chspec);
11305b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
11315b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* check the chanspec */
11323de67818e7e7ef95c8f7eac665dd29454c07b48bAlwin Beukers	if (brcms_c_chspec_malformed(chspec)) {
11335b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		wiphy_err(wlc->wiphy, "wl%d: malformed chanspec 0x%x\n",
11345b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			wlc->pub->unit, chspec);
11355b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		return false;
11365b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
11375b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
11385b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
11395b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	    chspec_bandunit(chspec))
11405b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		return false;
11415b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
11425b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	/* Check a 20Mhz channel */
11435b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	if (CHSPEC_IS20(chspec)) {
11445b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		if (dualband)
11455b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi,
11465b435de0d786869c95d1962121af0d7df2542009Arend van Spriel							  channel);
11475b435de0d786869c95d1962121af0d7df2542009Arend van Spriel		else
11485b435de0d786869c95d1962121af0d7df2542009Arend van Spriel			return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
11495b435de0d786869c95d1962121af0d7df2542009Arend van Spriel						       channel);
11505b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	}
11515b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
11525b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return false;
11535b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
11545b435de0d786869c95d1962121af0d7df2542009Arend van Spriel
11555b435de0d786869c95d1962121af0d7df2542009Arend van Sprielbool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
11565b435de0d786869c95d1962121af0d7df2542009Arend van Spriel{
11575b435de0d786869c95d1962121af0d7df2542009Arend van Spriel	return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true);
11585b435de0d786869c95d1962121af0d7df2542009Arend van Spriel}
1159cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1160cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheestatic bool brcms_is_radar_freq(u16 center_freq)
1161cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee{
1162cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	return center_freq >= 5260 && center_freq <= 5700;
1163cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee}
1164cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1165cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheestatic void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
1166cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee{
1167cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct ieee80211_supported_band *sband;
1168cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct ieee80211_channel *ch;
1169cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	int i;
1170cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1171cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	sband = wiphy->bands[IEEE80211_BAND_5GHZ];
1172cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	if (!sband)
1173cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		return;
1174cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1175cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	for (i = 0; i < sband->n_channels; i++) {
1176cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		ch = &sband->channels[i];
1177cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1178cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		if (!brcms_is_radar_freq(ch->center_freq))
1179cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			continue;
1180cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1181cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		/*
1182cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		 * All channels in this range should be passive and have
1183cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		 * DFS enabled.
1184cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		 */
1185cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		if (!(ch->flags & IEEE80211_CHAN_DISABLED))
1186cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			ch->flags |= IEEE80211_CHAN_RADAR |
1187cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				     IEEE80211_CHAN_NO_IBSS |
1188cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				     IEEE80211_CHAN_PASSIVE_SCAN;
1189cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	}
1190cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee}
1191cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1192cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheestatic void
1193cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheebrcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
1194cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				enum nl80211_reg_initiator initiator)
1195cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee{
1196cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct ieee80211_supported_band *sband;
1197cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct ieee80211_channel *ch;
1198cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	const struct ieee80211_reg_rule *rule;
1199cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	int band, i, ret;
1200cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1201cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1202cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		sband = wiphy->bands[band];
1203cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		if (!sband)
1204cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			continue;
1205cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1206cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		for (i = 0; i < sband->n_channels; i++) {
1207cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			ch = &sband->channels[i];
1208cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1209cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			if (ch->flags &
1210cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			    (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR))
1211cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				continue;
1212cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1213cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
1214cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				ret = freq_reg_info(wiphy, ch->center_freq,
1215cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee						    0, &rule);
1216cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				if (ret)
1217cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					continue;
1218cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1219cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				if (!(rule->flags & NL80211_RRF_NO_IBSS))
1220cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
1221cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				if (!(rule->flags & NL80211_RRF_PASSIVE_SCAN))
1222cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					ch->flags &=
1223cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee						~IEEE80211_CHAN_PASSIVE_SCAN;
1224cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			} else if (ch->beacon_found) {
1225cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
1226cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					       IEEE80211_CHAN_PASSIVE_SCAN);
1227cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			}
1228cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		}
1229cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	}
1230cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee}
1231cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1232cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheestatic int brcms_reg_notifier(struct wiphy *wiphy,
1233cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			      struct regulatory_request *request)
1234cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee{
1235cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
1236cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct brcms_info *wl = hw->priv;
1237cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct brcms_c_info *wlc = wl->wlc;
1238cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1239cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	brcms_reg_apply_radar_flags(wiphy);
1240cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1241cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
1242cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
1243cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1244cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
1245cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
1246cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					brcms_c_japan_ccode(request->alpha2));
1247cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1248cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	return 0;
1249cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee}
1250cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1251cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forsheevoid brcms_c_regd_init(struct brcms_c_info *wlc)
1252cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee{
1253cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct wiphy *wiphy = wlc->wiphy;
1254cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	const struct brcms_regd *regd = wlc->cmi->world_regd;
1255cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct ieee80211_supported_band *sband;
1256cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct ieee80211_channel *ch;
1257cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct brcms_chanvec sup_chan;
1258cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	struct brcms_band *band;
1259cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	int band_idx, i;
1260cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1261cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	/* Disable any channels not supported by the phy */
1262cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	for (band_idx = 0; band_idx < IEEE80211_NUM_BANDS; band_idx++) {
1263cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		if (band_idx == IEEE80211_BAND_2GHZ)
1264cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			band = wlc->bandstate[BAND_2G_INDEX];
1265cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		else
1266cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			band = wlc->bandstate[BAND_5G_INDEX];
1267cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
1268cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee					      &sup_chan);
1269cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1270cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		sband = wiphy->bands[band_idx];
1271cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		for (i = 0; i < sband->n_channels; i++) {
1272cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			ch = &sband->channels[i];
1273cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			if (!isset(sup_chan.vec, ch->hw_value))
1274cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee				ch->flags |= IEEE80211_CHAN_DISABLED;
1275cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee		}
1276cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	}
1277cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee
1278cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	wlc->wiphy->reg_notifier = brcms_reg_notifier;
1279cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
1280cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee			     WIPHY_FLAG_STRICT_REGULATORY;
1281cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
1282cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee	brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
1283cf03c5dac83609f09d9f0e9fa3c09d86daed614dSeth Forshee}
1284