xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_cfp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /**
2  * @file mlan_cfp.c
3  *
4  *  @brief This file contains WLAN client mode channel, frequency and power
5  *  related code
6  *
7  *
8  *  Copyright 2009-2022 NXP
9  *
10  *  This software file (the File) is distributed by NXP
11  *  under the terms of the GNU General Public License Version 2, June 1991
12  *  (the License).  You may use, redistribute and/or modify the File in
13  *  accordance with the terms and conditions of the License, a copy of which
14  *  is available by writing to the Free Software Foundation, Inc.,
15  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
16  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
17  *
18  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
19  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
20  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
21  *  this warranty disclaimer.
22  *
23  */
24 
25 /*************************************************************
26  * Change Log:
27  *	04/16/2009: initial version
28  ************************************************************/
29 
30 #include "mlan.h"
31 #include "mlan_util.h"
32 #include "mlan_fw.h"
33 #include "mlan_join.h"
34 #include "mlan_main.h"
35 
36 /********************************************************
37  *			Local Variables
38  ********************************************************/
39 
40 /** 100mW */
41 #define WLAN_TX_PWR_DEFAULT 20
42 /** 100mW */
43 #define WLAN_TX_PWR_00_DEFAULT 20
44 /** 100mW */
45 #define WLAN_TX_PWR_US_DEFAULT 20
46 /** 100mW */
47 #define WLAN_TX_PWR_JP_BG_DEFAULT 20
48 /** 200mW */
49 #define WLAN_TX_PWR_JP_A_DEFAULT 23
50 /** 100mW */
51 #define WLAN_TX_PWR_EMEA_DEFAULT 20
52 /** 2000mW */
53 #define WLAN_TX_PWR_CN_2000MW 33
54 /** 200mW */
55 #define WLAN_TX_PWR_200MW 23
56 /** 1000mW */
57 #define WLAN_TX_PWR_1000MW 30
58 /** 250mW */
59 #define WLAN_TX_PWR_250MW 24
60 
61 /** Region code mapping */
62 typedef struct _country_code_mapping {
63 	/** Region */
64 	t_u8 country_code[COUNTRY_CODE_LEN];
65 	/** Code for B/G CFP table */
66 	t_u8 cfp_code_bg;
67 	/** Code for A CFP table */
68 	t_u8 cfp_code_a;
69 } country_code_mapping_t;
70 
71 #define EU_CFP_CODE_BG 0x30
72 #define EU_CFP_CODE_A 0x30
73 
74 /** Region code mapping table */
75 static country_code_mapping_t country_code_mapping[] = {
76 	{"WW", 0x00, 0x00}, /* World       */
77 	{"US", 0x10, 0x10}, /* US FCC      */
78 	{"CA", 0x10, 0x20}, /* IC Canada   */
79 	{"SG", 0x10, 0x10}, /* Singapore   */
80 	{"EU", 0x30, 0x30}, /* ETSI        */
81 	{"AU", 0x30, 0x30}, /* Australia   */
82 	{"KR", 0x30, 0x30}, /* Republic Of Korea */
83 	{"JP", 0xFF, 0x40}, /* Japan       */
84 	{"CN", 0x30, 0x50}, /* China       */
85 	{"BR", 0x01, 0x09}, /* Brazil      */
86 	{"RU", 0x30, 0x0f}, /* Russia      */
87 	{"IN", 0x10, 0x06}, /* India       */
88 	{"MY", 0x30, 0x06}, /* Malaysia    */
89 	{"NZ", 0x30, 0x30}, /* New Zeland  */
90 	{"MX", 0x10, 0x07}, /* Mexico */
91 };
92 
93 /** Country code for ETSI */
94 static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
95 	"AL", "AD", "AT", "AU", "BE", "BA", "BG", "HR", "CY", "CZ", "DK", "EE",
96 	"FI", "FR", "MK", "DE", "GR", "HU", "IS", "IE", "IT", "LV", "LI", "LT",
97 	"LU", "MT", "MD", "MC", "ME", "NL", "NO", "PL", "RO", "SM", "RS", "SI",
98 	"SK", "ES", "SE", "CH", "TR", "UA", "UK", "GB", "NZ", "DZ", "AO", "AM",
99 	"AW", "BH", "BD", "BT", "BO", "BQ", "BW", "VG", "BF", "BI", "KH", "CL",
100 	"KM", "CG", "CD", "CW", "EG", "FO", "GF", "PF", "GE", "GI", "GP", "HK",
101 	"IN", "ID", "IM", "IL", "JE", "KE", "XK", "KW", "LA", "LR", "MW", "MV",
102 	"MQ", "MR", "YT", "MA", "MZ", "MM", "NA", "NC", "NE", "NG", "OM", "PS",
103 	"PT", "QA", "RW", "RE", "BL", "MF", "VC", "SA", "SC", "ZA", "SZ", "SY",
104 	"TZ", "TG", "TN", "AE", "VA", "EH", "YE", "ZM", "ZW"};
105 
106 /**
107  * The structure for Channel-Frequency-Power table
108  */
109 typedef struct _cfp_table {
110 	/** Region or Code */
111 	t_u8 code;
112 	/** Frequency/Power */
113 	chan_freq_power_t *cfp;
114 	/** No of CFP flag */
115 	int cfp_no;
116 } cfp_table_t;
117 
118 /* Format { Channel, Frequency (MHz), MaxTxPower } */
119 /** Band : 'B/G', Region: World Wide Safe */
120 static chan_freq_power_t channel_freq_power_00_BG[] = {
121 	{1, 2412, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
122 	{2, 2417, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
123 	{3, 2422, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
124 	{4, 2427, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
125 	{5, 2432, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
126 	{6, 2437, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
127 	{7, 2442, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
128 	{8, 2447, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
129 	{9, 2452, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
130 	{10, 2457, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
131 	{11, 2462, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
132 	{12, 2467, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x1d, 0, 0}},
133 	{13, 2472, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x1d, 0, 0}}};
134 /* Format { Channel, Frequency (MHz), MaxTxPower } */
135 /** Band: 'B/G', Region: USA FCC/Canada IC */
136 static chan_freq_power_t channel_freq_power_US_BG[] = {
137 	{1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
138 	{2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
139 	{3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
140 	{4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
141 	{5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
142 	{6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
143 	{7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
144 	{8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
145 	{9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
146 	{10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
147 	{11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}}};
148 
149 /** Band: 'B/G', Region: Europe ETSI/China */
150 static chan_freq_power_t channel_freq_power_EU_BG[] = {
151 	{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
152 	{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
153 	{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
154 	{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
155 	{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
156 	{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
157 	{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
158 	{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
159 	{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
160 	{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
161 	{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
162 	{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
163 	{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}}};
164 
165 /** Band: 'B/G', Region: Japan */
166 static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
167 	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
168 	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
169 	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
170 	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
171 	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
172 	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
173 	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
174 	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
175 	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
176 	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
177 	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
178 	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
179 	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}}};
180 
181 /** Band: 'B/G', Region: Japan */
182 static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
183 	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1d, 0, 0}}};
184 
185 /** Band: 'B/G', Region: Japan */
186 static chan_freq_power_t channel_freq_power_JPNFE_BG[] = {
187 	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
188 	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
189 	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
190 	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
191 	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
192 	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
193 	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
194 	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
195 	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
196 	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
197 	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
198 	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE, {0x1d, 0, 0}},
199 	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE, {0x1d, 0, 0}}};
200 
201 /** Band : 'B/G', Region: Brazil */
202 static chan_freq_power_t channel_freq_power_BR_BG[] = {
203 	{1, 2412, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
204 	{2, 2417, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
205 	{3, 2422, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
206 	{4, 2427, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
207 	{5, 2432, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
208 	{6, 2437, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
209 	{7, 2442, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
210 	{8, 2447, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
211 	{9, 2452, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
212 	{10, 2457, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
213 	{11, 2462, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
214 	{12, 2467, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
215 	{13, 2472, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}}};
216 
217 /** Band : 'B/G', Region: Special */
218 static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
219 	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
220 	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
221 	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
222 	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
223 	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
224 	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
225 	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
226 	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
227 	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
228 	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
229 	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
230 	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
231 	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
232 	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}}};
233 
234 /**
235  * The 2.4GHz CFP tables
236  */
237 static cfp_table_t cfp_table_BG[] = {
238 	{
239 		0x01, /* Brazil */
240 		channel_freq_power_BR_BG,
241 		NELEMENTS(channel_freq_power_BR_BG),
242 	},
243 	{
244 		0x00, /* World FCC */
245 		channel_freq_power_00_BG,
246 		NELEMENTS(channel_freq_power_00_BG),
247 	},
248 	{
249 		0x10, /* US FCC */
250 		channel_freq_power_US_BG,
251 		NELEMENTS(channel_freq_power_US_BG),
252 	},
253 	{
254 		0x20, /* CANADA IC */
255 		channel_freq_power_US_BG,
256 		NELEMENTS(channel_freq_power_US_BG),
257 	},
258 	{
259 		0x30, /* EU */
260 		channel_freq_power_EU_BG,
261 		NELEMENTS(channel_freq_power_EU_BG),
262 	},
263 	{
264 		0x40, /* JAPAN */
265 		channel_freq_power_JPN40_BG,
266 		NELEMENTS(channel_freq_power_JPN40_BG),
267 	},
268 	{
269 		0x41, /* JAPAN */
270 		channel_freq_power_JPN41_BG,
271 		NELEMENTS(channel_freq_power_JPN41_BG),
272 	},
273 	{
274 		0x50, /* China */
275 		channel_freq_power_EU_BG,
276 		NELEMENTS(channel_freq_power_EU_BG),
277 	},
278 	{
279 		0xfe, /* JAPAN */
280 		channel_freq_power_JPNFE_BG,
281 		NELEMENTS(channel_freq_power_JPNFE_BG),
282 	},
283 	{
284 		0xff, /* Special */
285 		channel_freq_power_SPECIAL_BG,
286 		NELEMENTS(channel_freq_power_SPECIAL_BG),
287 	},
288 	/* Add new region here */
289 };
290 
291 /** Number of the CFP tables for 2.4GHz */
292 #define MLAN_CFP_TABLE_SIZE_BG (NELEMENTS(cfp_table_BG))
293 
294 /* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
295 /** Band: 'A', Region: World Wide Safe */
296 static chan_freq_power_t channel_freq_power_00_A[] = {
297 	{36, 5180, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
298 	{40, 5200, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
299 	{44, 5220, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
300 	{48, 5240, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
301 	{52, 5260, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
302 	{56, 5280, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
303 	{60, 5300, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
304 	{64, 5320, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
305 	{100, 5500, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
306 	{104, 5520, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
307 	{108, 5540, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
308 	{112, 5560, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
309 	{116, 5580, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
310 	{120, 5600, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
311 	{124, 5620, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
312 	{128, 5640, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
313 	{132, 5660, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
314 	{136, 5680, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
315 	{140, 5700, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
316 	{144, 5720, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
317 	{149, 5745, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
318 	{153, 5765, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
319 	{157, 5785, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
320 	{161, 5805, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
321 	{165, 5825, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}}};
322 /* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
323 /** Band: 'A', Region: USA FCC */
324 static chan_freq_power_t channel_freq_power_A[] = {
325 	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
326 	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
327 	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
328 	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
329 	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
330 	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
331 	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
332 	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
333 	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
334 	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
335 	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
336 	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
337 	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
338 	{120, 5600, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
339 	{124, 5620, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
340 	{128, 5640, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
341 	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
342 	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
343 	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
344 	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
345 	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
346 	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
347 	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
348 	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
349 	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
350 	{169, 5845, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
351 	{173, 5865, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
352 	{177, 5885, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}}};
353 
354 /** Band: 'A', Region: Canada IC */
355 static chan_freq_power_t channel_freq_power_CAN_A[] = {
356 	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
357 	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
358 	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
359 	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
360 	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
361 	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
362 	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
363 	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
364 	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
365 	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
366 	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
367 	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
368 	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
369 	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
370 	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
371 	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
372 	{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
373 	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
374 	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
375 	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
376 	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
377 	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}}};
378 
379 /** Band: 'A', Region: Europe ETSI */
380 static chan_freq_power_t channel_freq_power_EU_A[] = {
381 	{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
382 	{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
383 	{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
384 	{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
385 	{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
386 	{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
387 	{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
388 	{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
389 	{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
390 	{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
391 	{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
392 	{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
393 	{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
394 	{120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
395 	{124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
396 	{128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
397 	{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
398 	{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
399 	{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
400 	{149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
401 	{153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
402 	{157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
403 	{161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
404 	{165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}}};
405 
406 /** Band: 'A', Region: Japan */
407 static chan_freq_power_t channel_freq_power_JPN_A[] = {
408 	{36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
409 	{40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
410 	{44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
411 	{48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
412 	{52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
413 	{56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
414 	{60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
415 	{64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
416 	{100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
417 	{104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
418 	{108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
419 	{112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
420 	{116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
421 	{120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
422 	{124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
423 	{128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
424 	{132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
425 	{136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
426 	{140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
427 	{144, 5720, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}}};
428 
429 /** Band: 'A', Region: China */
430 static chan_freq_power_t channel_freq_power_CN_A[] = {
431 	{36, 5180, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
432 	{40, 5200, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
433 	{44, 5220, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
434 	{48, 5240, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
435 	{52, 5260, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
436 	{56, 5280, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
437 	{60, 5300, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
438 	{64, 5320, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
439 	{149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
440 	{153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
441 	{157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
442 	{161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
443 	{165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}}};
444 
445 /** Band: 'A', NULL */
446 static chan_freq_power_t channel_freq_power_NULL_A[] = {};
447 
448 /** Band: 'A', Region: Spain/Austria/Brazil */
449 static chan_freq_power_t channel_freq_power_SPN2_A[] = {
450 	{36, 5180, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
451 	{40, 5200, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
452 	{44, 5220, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
453 	{48, 5240, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
454 	{52, 5260, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
455 	{56, 5280, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
456 	{60, 5300, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
457 	{64, 5320, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}}};
458 
459 /** Band: 'A', Region: Brazil */
460 static chan_freq_power_t channel_freq_power_BR1_A[] = {
461 	{100, 5500, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
462 	{104, 5520, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
463 	{108, 5540, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
464 	{112, 5560, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
465 	{116, 5580, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
466 	{120, 5600, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
467 	{124, 5620, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
468 	{128, 5640, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
469 	{132, 5660, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
470 	{136, 5680, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
471 	{140, 5700, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}}};
472 
473 /** Band: 'A', Region: Brazil */
474 static chan_freq_power_t channel_freq_power_BR2_A[] = {
475 	{149, 5745, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
476 	{153, 5765, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
477 	{157, 5785, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
478 	{161, 5805, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
479 	{165, 5825, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}}};
480 
481 /** Band: 'A', Region: Russia */
482 static chan_freq_power_t channel_freq_power_RU_A[] = {
483 	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
484 	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
485 	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
486 	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
487 	{52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
488 	{56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
489 	{60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
490 	{64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
491 	{132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
492 	{136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
493 	{140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
494 	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
495 	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
496 	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
497 	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
498 
499 /** Band: 'A', Region: Mexico */
500 static chan_freq_power_t channel_freq_power_MX_A[] = {
501 	{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
502 	{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
503 	{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
504 	{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
505 	{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
506 	{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
507 	{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
508 	{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
509 	{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
510 	{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
511 	{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
512 	{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
513 	{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
514 	{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
515 	{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
516 	{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
517 	{149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
518 	{153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
519 	{157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
520 	{161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
521 	{165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}}};
522 
523 /** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
524 static chan_freq_power_t channel_freq_power_low_band[] = {
525 	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
526 	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
527 	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
528 	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
529 
530 /** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
531 static chan_freq_power_t channel_freq_power_lower_middle_band[] = {
532 	{52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
533 	{56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
534 	{60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
535 	{64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}}};
536 
537 /** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
538 static chan_freq_power_t channel_freq_power_upper_middle_band[] = {
539 	{100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
540 	{104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
541 	{108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
542 	{112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
543 	{116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
544 	{120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
545 	{124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
546 	{128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
547 	{132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
548 	{136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
549 	{140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}}};
550 
551 /** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
552 static chan_freq_power_t channel_freq_power_high_band[] = {
553 	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
554 	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
555 	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
556 	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
557 	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
558 
559 /** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
560  *  High band (5725-5850 MHz) channels
561  */
562 static chan_freq_power_t channel_freq_power_low_high_band[] = {
563 	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
564 	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
565 	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
566 	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
567 	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
568 	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
569 	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
570 	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
571 	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
572 
573 /** Band: 'A', Code: 6, Low band (5150-5250 MHz) and
574  *  mid low (5260-5320) and High band (5725-5850 MHz) channels
575  */
576 static chan_freq_power_t channel_freq_power_low_middle_high_band[] = {
577 	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
578 	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
579 	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
580 	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
581 	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
582 	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
583 	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
584 	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
585 	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
586 	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
587 	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
588 	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
589 	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
590 
591 /**
592  * The 5GHz CFP tables
593  */
594 static cfp_table_t cfp_table_A[] = {
595 	{0x1, /* Low band (5150-5250 MHz) channels */
596 	 channel_freq_power_low_band, NELEMENTS(channel_freq_power_low_band)},
597 	{0x2, /* Lower middle band (5250-5350 MHz) channels */
598 	 channel_freq_power_lower_middle_band,
599 	 NELEMENTS(channel_freq_power_lower_middle_band)},
600 	{0x3, /* Upper middle band (5470-5725 MHz) channels */
601 	 channel_freq_power_upper_middle_band,
602 	 NELEMENTS(channel_freq_power_upper_middle_band)},
603 	{0x4, /* High band (5725-5850 MHz) channels */
604 	 channel_freq_power_high_band, NELEMENTS(channel_freq_power_high_band)},
605 	{0x5, /* Low band (5150-5250 MHz) and
606 	       * High band (5725-5850 MHz) channels
607 	       */
608 	 channel_freq_power_low_high_band,
609 	 NELEMENTS(channel_freq_power_low_high_band)},
610 	{0x6, /* Low band (5150-5250 MHz)
611 	       * Mid band (5260-5320) and
612 	       * High band (5725-5850 MHz) channels
613 	       */
614 	 channel_freq_power_low_middle_high_band,
615 	 NELEMENTS(channel_freq_power_low_middle_high_band)},
616 	{
617 		0x07, /* Mexico */
618 		channel_freq_power_MX_A,
619 		NELEMENTS(channel_freq_power_MX_A),
620 	},
621 
622 	{
623 		0x09, /* SPAIN/Austria/Brazil */
624 		channel_freq_power_SPN2_A,
625 		NELEMENTS(channel_freq_power_SPN2_A),
626 	},
627 	{
628 		0x0c, /* Brazil */
629 		channel_freq_power_BR1_A,
630 		NELEMENTS(channel_freq_power_BR1_A),
631 	},
632 	{
633 		0x0e, /* Brazil */
634 		channel_freq_power_BR2_A,
635 		NELEMENTS(channel_freq_power_BR2_A),
636 	},
637 	{
638 		0x0f, /* Russia */
639 		channel_freq_power_RU_A,
640 		NELEMENTS(channel_freq_power_RU_A),
641 	},
642 	{
643 		0x00, /* World */
644 		channel_freq_power_00_A,
645 		NELEMENTS(channel_freq_power_00_A),
646 	},
647 	{
648 		0x10, /* US FCC */
649 		channel_freq_power_A,
650 		NELEMENTS(channel_freq_power_A),
651 	},
652 	{
653 		0x20, /* CANADA IC */
654 		channel_freq_power_CAN_A,
655 		NELEMENTS(channel_freq_power_CAN_A),
656 	},
657 	{
658 		0x30, /* EU */
659 		channel_freq_power_EU_A,
660 		NELEMENTS(channel_freq_power_EU_A),
661 	},
662 	{
663 		0x40, /* JAPAN */
664 		channel_freq_power_JPN_A,
665 		NELEMENTS(channel_freq_power_JPN_A),
666 	},
667 	{
668 		0x41, /* JAPAN */
669 		channel_freq_power_JPN_A,
670 		NELEMENTS(channel_freq_power_JPN_A),
671 	},
672 	{
673 		0x50, /* China */
674 		channel_freq_power_CN_A,
675 		NELEMENTS(channel_freq_power_CN_A),
676 	},
677 	{
678 		0xfe, /* JAPAN */
679 		channel_freq_power_NULL_A,
680 		NELEMENTS(channel_freq_power_NULL_A),
681 	},
682 	{
683 		0xff, /* Special */
684 		channel_freq_power_JPN_A,
685 		NELEMENTS(channel_freq_power_JPN_A),
686 	},
687 	/* Add new region here */
688 };
689 /** Number of the CFP tables for 5GHz */
690 #define MLAN_CFP_TABLE_SIZE_A (NELEMENTS(cfp_table_A))
691 
692 enum { RATEID_DBPSK1Mbps, //(0)
693        RATEID_DQPSK2Mbps, //(1)
694        RATEID_CCK5_5Mbps, //(2)
695        RATEID_CCK11Mbps, //(3)
696        RATEID_CCK22Mbps, //(4)
697        RATEID_OFDM6Mbps, //(5)
698        RATEID_OFDM9Mbps, //(6)
699        RATEID_OFDM12Mbps, //(7)
700        RATEID_OFDM18Mbps, //(8)
701        RATEID_OFDM24Mbps, //(9)
702        RATEID_OFDM36Mbps, //(10)
703        RATEID_OFDM48Mbps, //(11)
704        RATEID_OFDM54Mbps, //(12)
705        RATEID_OFDM72Mbps, //(13)
706 };
707 
708 static const t_u8 rateUnit_500Kbps[] = {
709 	(10 / 5), /* 1Mbps */
710 	(20 / 5), /* 2Mbps */
711 
712 	(55 / 5), /* 5.5Mbps */
713 	(110 / 5), /* 11Mbps */
714 	(10 / 5), /* 22Mbps, intentionally set to 1Mbps
715 		   * because it's not available
716 		   */
717 
718 	(60 / 5), /* 6Mbps */
719 	(90 / 5), /* 9Mbps */
720 	(120 / 5), /* 12Mbps */
721 	(180 / 5), /* 18Mbps */
722 	(240 / 5), /* 24Mbps */
723 	(360 / 5), /* 36Mbps */
724 	(480 / 5), /* 48Mbps */
725 	(540 / 5), /* 54Mbps */
726 	(60 / 5), /* 72Mbps, intentionally set to 6Mbps
727 		   * because it's not available
728 		   */
729 };
730 
731 typedef struct _rate_map {
732 	/** Rate, in 0.5Mbps */
733 	t_u32 rate;
734 	/** Mrvl rate id, refer to RATEID_XXX in FW */
735 	t_u32 id;
736 	/** nss: 0-nss1, 1-nss2 */
737 	t_u8 nss;
738 } rate_map;
739 
740 /** If user configure to 1x1 or we found peer device only support 1x1,
741  * then we need skip the nss1 part when map to Mrvl rate.
742  */
743 static const rate_map rate_map_table_2x2[] = {
744 	/* LG <--> Mrvl rate idx */
745 	{2, 0, 0}, // RATEID_DBPSK1Mbps
746 	{4, 1, 0}, // RATEID_DQPSK2Mbps
747 	{11, 2, 0}, // RATEID_CCK5_5Mbps
748 	{22, 3, 0}, // RATEID_CCK11Mbps
749 	{44, 4, 0}, // RATEID_CCK22Mbps
750 	{12, 5, 0}, // RATEID_OFDM6Mbps
751 	{18, 6, 0}, // RATEID_OFDM9Mbps
752 	{24, 7, 0}, // RATEID_OFDM12Mbps
753 	{36, 8, 0}, // RATEID_OFDM18Mbps
754 	{48, 9, 0}, // RATEID_OFDM24Mbps
755 	{72, 10, 0}, // RATEID_OFDM36Mbps
756 	{96, 11, 0}, // RATEID_OFDM48Mbps
757 	{108, 12, 0}, // RATEID_OFDM54Mbps
758 	{144, 13, 0}, // RATEID_OFDM72Mbps
759 
760 	/* HT bw20 <--> Mrvl rate idx - nss2 */
761 	{26, 22, 1}, // RATEID_MCS8_13Mbps
762 	{52, 23, 1}, // RATEID_MCS9_26Mbps
763 	{78, 24, 1}, // RATEID_MCS10_39Mbps
764 	{104, 25, 1}, // RATEID_MCS11_52Mbps
765 	{156, 26, 1}, // RATEID_MCS12_78Mbps
766 	{208, 27, 1}, // RATEID_MCS13_104Mbps
767 	{234, 28, 1}, // RATEID_MCS14_117Mbps
768 	{260, 29, 1}, // RATEID_MCS15_130Mbps
769 	/* HT bw20 <--> Mrvl rate idx - nss1 */
770 	{13, 14, 0}, // RATEID_MCS0_6d5Mbps
771 	{26, 15, 0}, // RATEID_MCS1_13Mbps
772 	{39, 16, 0}, // RATEID_MCS2_19d5Mbps
773 	{52, 17, 0}, // RATEID_MCS3_26Mbps
774 	{78, 18, 0}, // RATEID_MCS4_39Mbps
775 	{104, 19, 0}, // RATEID_MCS5_52Mbps
776 	{117, 20, 0}, // RATEID_MCS6_58d5Mbps
777 	{130, 21, 0}, // RATEID_MCS7_65Mbps
778 
779 	/* HT bw40<--> Mrvl rate idx - nss2 */
780 	{54, 39, 1}, // RATEID_MCS8BW40_27Mbps
781 	{108, 40, 1}, // RATEID_MCS9BW40_54Mbps
782 	{162, 41, 1}, // RATEID_MCS10BW40_81Mbps
783 	{216, 42, 1}, // RATEID_MCS11BW40_108Mbps
784 	{324, 43, 1}, // RATEID_MCS12BW40_162Mbps
785 	{432, 44, 1}, // RATEID_MCS13BW40_216Mbps
786 	{486, 45, 1}, // RATEID_MCS14BW40_243Mbps
787 	{540, 46, 1}, // RATEID_MCS15BW40_270Mbps
788 	/* HT bw40<--> Mrvl rate idx - nss1 */
789 	{12, 30, 0}, // RATEID_MCS32BW40_6Mbps
790 	{27, 31, 0}, // RATEID_MCS0BW40_13d5Mbps
791 	{54, 32, 0}, // RATEID_MCS1BW40_27Mbps
792 	{81, 33, 0}, // RATEID_MCS2BW40_40d5Mbps
793 	{108, 34, 0}, // RATEID_MCS3BW40_54Mbps
794 	{162, 35, 0}, // RATEID_MCS4BW40_81Mbps
795 	{216, 36, 0}, // RATEID_MCS5BW40_108Mbps
796 	{243, 37, 0}, // RATEID_MCS6BW40_121d5Mbps
797 	{270, 38, 0}, // RATEID_MCS7BW40_135Mbps
798 
799 	/* VHT bw20<--> Mrvl rate idx - nss2 */
800 	{26, 57, 1}, // RATEID_VHT_MCS0_2SS_BW20   13    Mbps
801 	{52, 58, 1}, // RATEID_VHT_MCS1_2SS_BW20   26    Mbps
802 	{78, 59, 1}, // RATEID_VHT_MCS2_2SS_BW20   39    Mbps
803 	{104, 60, 1}, // RATEID_VHT_MCS3_2SS_BW20   52    Mbps
804 	{156, 61, 1}, // RATEID_VHT_MCS4_2SS_BW20   78    Mbps
805 	{208, 62, 1}, // RATEID_VHT_MCS5_2SS_BW20   104   Mbps
806 	{234, 63, 1}, // RATEID_VHT_MCS6_2SS_BW20   117   Mbps
807 	{260, 64, 1}, // RATEID_VHT_MCS7_2SS_BW20   130   Mbps
808 	{312, 65, 1}, // RATEID_VHT_MCS8_2SS_BW20   156   Mbps
809 	{0, 66, 1}, // RATEID_VHT_MCS9_2SS_BW20   173.3 Mbps(INVALID)
810 	/* VHT bw20<--> Mrvl rate idx - nss1 */
811 	{13, 47, 0}, // RATEID_VHT_MCS0_1SS_BW20   6.5  Mbps
812 	{26, 48, 0}, // RATEID_VHT_MCS1_1SS_BW20   13   Mbps
813 	{39, 49, 0}, // RATEID_VHT_MCS2_1SS_BW20   19.5 Mbps
814 	{52, 50, 0}, // RATEID_VHT_MCS3_1SS_BW20   26   Mbps
815 	{78, 51, 0}, // RATEID_VHT_MCS4_1SS_BW20   39   Mbps
816 	{104, 52, 0}, // RATEID_VHT_MCS5_1SS_BW20   52   Mbps
817 	{117, 53, 0}, // RATEID_VHT_MCS6_1SS_BW20   58.5 Mbps
818 	{130, 54, 0}, // RATEID_VHT_MCS7_1SS_BW20   65   Mbps
819 	{156, 55, 0}, // RATEID_VHT_MCS8_1SS_BW20   78   Mbps
820 	{0, 56, 0}, // RATEID_VHT_MCS9_1SS_BW20   86.7 Mbps(INVALID)
821 
822 	/* VHT bw40<--> Mrvl rate idx - nss2 */
823 	{54, 77, 1}, // RATEID_VHT_MCS0_2SS_BW40   27  Mbps
824 	{108, 78, 1}, // RATEID_VHT_MCS1_2SS_BW40   54  Mbps
825 	{162, 79, 1}, // RATEID_VHT_MCS2_2SS_BW40   81  Mbps
826 	{216, 80, 1}, // RATEID_VHT_MCS3_2SS_BW40   108 Mbps
827 	{324, 81, 1}, // RATEID_VHT_MCS4_2SS_BW40   162 Mbps
828 	{432, 82, 1}, // RATEID_VHT_MCS5_2SS_BW40   216 Mbps
829 	{486, 83, 1}, // RATEID_VHT_MCS6_2SS_BW40   243 Mbps
830 	{540, 84, 1}, // RATEID_VHT_MCS7_2SS_BW40   270 Mbps
831 	{648, 85, 1}, // RATEID_VHT_MCS8_2SS_BW40   324 Mbps
832 	{720, 86, 1}, // RATEID_VHT_MCS9_2SS_BW40   360 Mbps
833 	/* VHT bw40<--> Mrvl rate idx - nss1 */
834 	{27, 67, 0}, // RATEID_VHT_MCS0_1SS_BW40   13.5  Mbps
835 	{54, 68, 0}, // RATEID_VHT_MCS1_1SS_BW40   27    Mbps
836 	{81, 69, 0}, // RATEID_VHT_MCS2_1SS_BW40   40.5  Mbps
837 	{108, 70, 0}, // RATEID_VHT_MCS3_1SS_BW40   54    Mbps
838 	{162, 71, 0}, // RATEID_VHT_MCS4_1SS_BW40   81    Mbps
839 	{216, 72, 0}, // RATEID_VHT_MCS5_1SS_BW40   108   Mbps
840 	{243, 73, 0}, // RATEID_VHT_MCS6_1SS_BW40   121.5 Mbps
841 	{270, 74, 0}, // RATEID_VHT_MCS7_1SS_BW40   135   Mbps
842 	{324, 75, 0}, // RATEID_VHT_MCS8_1SS_BW40   162   Mbps
843 	{360, 76, 0}, // RATEID_VHT_MCS9_1SS_BW40   180   Mbps
844 
845 	/* VHT bw80<--> Mrvl rate idx - nss2 */
846 	{117, 97, 1}, // RATEID_VHT_MCS0_2SS_BW80   58.5  Mbps
847 	{234, 98, 1}, // RATEID_VHT_MCS1_2SS_BW80   117   Mbps
848 	{350, 99, 1}, // RATEID_VHT_MCS2_2SS_BW80   175   Mbps
849 	{468, 100, 1}, // RATEID_VHT_MCS3_2SS_BW80   234   Mbps
850 	{702, 101, 1}, // RATEID_VHT_MCS4_2SS_BW80   351   Mbps
851 	{936, 102, 1}, // RATEID_VHT_MCS5_2SS_BW80   468   Mbps
852 	{1053, 103, 1}, // RATEID_VHT_MCS6_2SS_BW80   526.5 Mbps
853 	{1170, 104, 1}, // RATEID_VHT_MCS7_2SS_BW80   585   Mbps
854 	{1404, 105, 1}, // RATEID_VHT_MCS8_2SS_BW80   702   Mbps
855 	{1560, 106, 1}, // RATEID_VHT_MCS9_2SS_BW80   780   Mbps
856 	/* VHT bw80<--> Mrvl rate idx - nss1 */
857 	{58, 87, 0}, // RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3x2 could
858 		     // correspond to 58
859 	{59, 87, 0}, // RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3*2 could
860 		     // correspond to 59 too
861 	{117, 88, 0}, // RATEID_VHT_MCS1_1SS_BW80   58.5  Mbps
862 	{175, 89, 0}, // RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could
863 		      // correspond to 175
864 	{176, 89, 0}, // RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could
865 		      // correspond to 176 too
866 	{234, 90, 0}, // RATEID_VHT_MCS3_1SS_BW80   117   Mbps
867 	{351, 91, 0}, // RATEID_VHT_MCS4_1SS_BW80   175.5 Mbps
868 	{468, 92, 0}, // RATEID_VHT_MCS5_1SS_BW80   234   Mbps
869 	{526, 93, 0}, // RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could
870 		      // correspond to 526
871 	{527, 93, 0}, // RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could
872 		      // correspond to 527 too
873 	{585, 94, 0}, // RATEID_VHT_MCS7_1SS_BW80   292.5 Mbps
874 	{702, 95, 0}, // RATEID_VHT_MCS8_1SS_BW80   351   Mbps
875 	{780, 96, 0}, // RATEID_VHT_MCS9_1SS_BW80   390   Mbps
876 };
877 
878 /** rate_map_table_1x1 is based on rate_map_table_2x2 and remove nss2 part.
879  * For the chip who only support 1x1, Mrvl rate idx define is different with 2x2
880  * in FW We need redefine a bitrate to Mrvl rate idx table for 1x1 chip.
881  */
882 static const rate_map rate_map_table_1x1[] = {
883 	/* LG <--> Mrvl rate idx */
884 	{2, 0, 0}, // RATEID_DBPSK1Mbps
885 	{4, 1, 0}, // RATEID_DQPSK2Mbps
886 	{11, 2, 0}, // RATEID_CCK5_5Mbps
887 	{22, 3, 0}, // RATEID_CCK11Mbps
888 	{44, 4, 0}, // RATEID_CCK22Mbps
889 	{12, 5, 0}, // RATEID_OFDM6Mbps
890 	{18, 6, 0}, // RATEID_OFDM9Mbps
891 	{24, 7, 0}, // RATEID_OFDM12Mbps
892 	{36, 8, 0}, // RATEID_OFDM18Mbps
893 	{48, 9, 0}, // RATEID_OFDM24Mbps
894 	{72, 10, 0}, // RATEID_OFDM36Mbps
895 	{96, 11, 0}, // RATEID_OFDM48Mbps
896 	{108, 12, 0}, // RATEID_OFDM54Mbps
897 	{144, 13, 0}, // RATEID_OFDM72Mbps
898 
899 	/* HT bw20 <--> Mrvl rate idx */
900 	{13, 14, 0}, // RATEID_MCS0_6d5Mbps
901 	{26, 15, 0}, // RATEID_MCS1_13Mbps
902 	{39, 16, 0}, // RATEID_MCS2_19d5Mbps
903 	{52, 17, 0}, // RATEID_MCS3_26Mbps
904 	{78, 18, 0}, // RATEID_MCS4_39Mbps
905 	{104, 19, 0}, // RATEID_MCS5_52Mbps
906 	{117, 20, 0}, // RATEID_MCS6_58d5Mbps
907 	{130, 21, 0}, // RATEID_MCS7_65Mbps
908 
909 	/* HT bw40<--> Mrvl rate idx */
910 	{12, 22, 0}, // RATEID_MCS32BW40_6Mbps,   for 1x1 start from 22
911 	{27, 23, 0}, // RATEID_MCS0BW40_13d5Mbps
912 	{54, 24, 0}, // RATEID_MCS1BW40_27Mbps
913 	{81, 25, 0}, // RATEID_MCS2BW40_40d5Mbps
914 	{108, 26, 0}, // RATEID_MCS3BW40_54Mbps
915 	{162, 27, 0}, // RATEID_MCS4BW40_81Mbps
916 	{216, 28, 0}, // RATEID_MCS5BW40_108Mbps
917 	{243, 29, 0}, // RATEID_MCS6BW40_121d5Mbps
918 	{270, 30, 0}, // RATEID_MCS7BW40_135Mbps
919 
920 	/* VHT bw20<--> Mrvl rate idx */
921 	{13, 31, 0}, // RATEID_VHT_MCS0_1SS_BW20   6.5  Mbps
922 	{26, 32, 0}, // RATEID_VHT_MCS1_1SS_BW20   13   Mbps
923 	{39, 33, 0}, // RATEID_VHT_MCS2_1SS_BW20   19.5 Mbps
924 	{52, 34, 0}, // RATEID_VHT_MCS3_1SS_BW20   26   Mbps
925 	{78, 35, 0}, // RATEID_VHT_MCS4_1SS_BW20   39   Mbps
926 	{104, 36, 0}, // RATEID_VHT_MCS5_1SS_BW20   52   Mbps
927 	{117, 37, 0}, // RATEID_VHT_MCS6_1SS_BW20   58.5 Mbps
928 	{130, 38, 0}, // RATEID_VHT_MCS7_1SS_BW20   65   Mbps
929 	{156, 39, 0}, // RATEID_VHT_MCS8_1SS_BW20   78   Mbps
930 	{0, 40, 0}, // RATEID_VHT_MCS9_1SS_BW20   86.7 Mbps(INVALID)
931 
932 	/* VHT bw40<--> Mrvl rate idx */
933 	{27, 41, 0}, // RATEID_VHT_MCS0_1SS_BW40   13.5  Mbps
934 	{54, 42, 0}, // RATEID_VHT_MCS1_1SS_BW40   27    Mbps
935 	{81, 43, 0}, // RATEID_VHT_MCS2_1SS_BW40   40.5  Mbps
936 	{108, 44, 0}, // RATEID_VHT_MCS3_1SS_BW40   54    Mbps
937 	{162, 45, 0}, // RATEID_VHT_MCS4_1SS_BW40   81    Mbps
938 	{216, 46, 0}, // RATEID_VHT_MCS5_1SS_BW40   108   Mbps
939 	{243, 47, 0}, // RATEID_VHT_MCS6_1SS_BW40   121.5 Mbps
940 	{270, 48, 0}, // RATEID_VHT_MCS7_1SS_BW40   135   Mbps
941 	{324, 49, 0}, // RATEID_VHT_MCS8_1SS_BW40   162   Mbps
942 	{360, 50, 0}, // RATEID_VHT_MCS9_1SS_BW40   180   Mbps
943 
944 	/* VHT bw80<--> Mrvl rate idx */
945 	{58, 51, 0}, // RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3x2 could
946 		     // correspond to 58
947 	{59, 51, 0}, // RATEID_VHT_MCS0_1SS_BW80   29.3  Mbps,  29.3x2 could
948 		     // correspond to 59 too
949 	{117, 52, 0}, // RATEID_VHT_MCS1_1SS_BW80   58.5  Mbps
950 	{175, 53, 0}, // RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could
951 		      // correspond to 175
952 	{176, 53, 0}, // RATEID_VHT_MCS2_1SS_BW80   87.8  Mbps,  87.8x2 could
953 		      // correspond to 176 too
954 	{234, 54, 0}, // RATEID_VHT_MCS3_1SS_BW80   117   Mbps
955 	{351, 55, 0}, // RATEID_VHT_MCS4_1SS_BW80   175.5 Mbps
956 	{468, 56, 0}, // RATEID_VHT_MCS5_1SS_BW80   234   Mbps
957 	{526, 57, 0}, // RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could
958 		      // correspond to 526
959 	{527, 57, 0}, // RATEID_VHT_MCS6_1SS_BW80   263.3 Mbps,  263.3x2 could
960 		      // correspond to 527 too
961 	{585, 58, 0}, // RATEID_VHT_MCS7_1SS_BW80   292.5 Mbps
962 	{702, 59, 0}, // RATEID_VHT_MCS8_1SS_BW80   351   Mbps
963 	{780, 60, 0}, // RATEID_VHT_MCS9_1SS_BW80   390   Mbps
964 };
965 
966 /********************************************************
967  *			Global Variables
968  ********************************************************/
969 /**
970  * The table to keep region code
971  */
972 
973 t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = {0x00, 0x10, 0x20, 0x30, 0x40,
974 						   0x41, 0x50, 0xfe, 0xff};
975 
976 /** The table to keep CFP code for A */
977 t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = {0x1, 0x2, 0x3, 0x4, 0x5};
978 
979 /**
980  * The rates supported for ad-hoc B mode
981  */
982 t_u8 AdhocRates_B[B_SUPPORTED_RATES] = {0x82, 0x84, 0x8b, 0x96, 0};
983 
984 /**
985  * The rates supported for ad-hoc G mode
986  */
987 t_u8 AdhocRates_G[G_SUPPORTED_RATES] = {0x8c, 0x12, 0x98, 0x24, 0xb0,
988 					0x48, 0x60, 0x6c, 0x00};
989 
990 /**
991  * The rates supported for ad-hoc BG mode
992  */
993 t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = {0x82, 0x84, 0x8b, 0x96, 0x0c,
994 					  0x12, 0x18, 0x24, 0x30, 0x48,
995 					  0x60, 0x6c, 0x00};
996 
997 /**
998  * The rates supported in A mode for ad-hoc
999  */
1000 t_u8 AdhocRates_A[A_SUPPORTED_RATES] = {0x8c, 0x12, 0x98, 0x24, 0xb0,
1001 					0x48, 0x60, 0x6c, 0x00};
1002 
1003 /**
1004  * The rates supported in A mode (used for BAND_A)
1005  */
1006 t_u8 SupportedRates_A[A_SUPPORTED_RATES] = {0x0c, 0x12, 0x18, 0x24, 0xb0,
1007 					    0x48, 0x60, 0x6c, 0x00};
1008 
1009 /**
1010  * The rates supported by the card
1011  */
1012 static t_u16 WlanDataRates[WLAN_SUPPORTED_RATES_EXT] = {
1013 	0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, 0x24,  0x30, 0x48,
1014 	0x60, 0x6C, 0x90, 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68,  0x75, 0x82,
1015 	0x0C, 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00};
1016 
1017 /**
1018  * The rates supported in B mode
1019  */
1020 t_u8 SupportedRates_B[B_SUPPORTED_RATES] = {0x02, 0x04, 0x0b, 0x16, 0x00};
1021 
1022 /**
1023  * The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
1024  */
1025 t_u8 SupportedRates_G[G_SUPPORTED_RATES] = {0x0c, 0x12, 0x18, 0x24, 0x30,
1026 					    0x48, 0x60, 0x6c, 0x00};
1027 
1028 /**
1029  * The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
1030  */
1031 t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = {0x02, 0x04, 0x0b, 0x0c, 0x12,
1032 					      0x16, 0x18, 0x24, 0x30, 0x48,
1033 					      0x60, 0x6c, 0x00};
1034 
1035 /**
1036  * The rates supported in N mode
1037  */
1038 t_u8 SupportedRates_N[N_SUPPORTED_RATES] = {0x02, 0x04, 0};
1039 
1040 #define MCS_NUM_AX 12
1041 // for MCS0/MCS1/MCS3/MCS4 have 4 additional DCM=1 value
1042 // note: the value in the table is 2 multiplier of the actual rate
1043 static t_u16 ax_mcs_rate_nss1[12][MCS_NUM_AX + 4] = {
1044 	{0x90, 0x48, 0x120, 0x90, 0x1B0, 0x240, 0x120, 0x360, 0x1B0, 0x481,
1045 	 0x511, 0x5A1, 0x6C1, 0x781, 0x871, 0x962}, /*SG 160M*/
1046 	{0x88, 0x44, 0x110, 0x88, 0x198, 0x220, 0x110, 0x330, 0x198, 0x440,
1047 	 0x4C9, 0x551, 0x661, 0x716, 0x7F9, 0x8DC}, /*MG 160M*/
1048 	{0x7A, 0x3D, 0xF5, 0x7A, 0x16F, 0x1EA, 0xF5, 0x2DF, 0x16F, 0x3D4, 0x44E,
1049 	 0x4C9, 0x5BE, 0x661, 0x72D, 0x7F9}, /*LG 160M*/
1050 	{0x48, 0x24, 0x90, 0x48, 0xD8, 0x120, 0x90, 0x1B0, 0xD8, 0x240, 0x288,
1051 	 0x2D0, 0x360, 0x3C0, 0x438, 0x4B0}, /*SG 80M*/
1052 	{0x44, 0x22, 0x88, 0x44, 0xCC, 0x110, 0x88, 0x198, 0xCC, 0x220, 0x264,
1053 	 0x2A8, 0x330, 0x38B, 0x3FC, 0x46E}, /*MG 80M*/
1054 	{0x3D, 0x1E, 0x7A, 0x3D, 0xB7, 0xF5, 0x7A, 0x16F, 0xB7, 0x1EA, 0x227,
1055 	 0x264, 0x2DF, 0x330, 0x396, 0x3FC}, /*LG 80M*/
1056 	{0x22, 0x11, 0x44, 0x22, 0x67, 0x89, 0x44, 0xCE, 0x67, 0x113, 0x135,
1057 	 0x158, 0x19D, 0x1CA, 0x204, 0x23D}, /*SG 40M*/
1058 	{0x20, 0x10, 0x41, 0x20, 0x61, 0x82, 0x41, 0xC3, 0x61, 0x104, 0x124,
1059 	 0x145, 0x186, 0x1B1, 0x1E7, 0x21D}, /*MG 40M*/
1060 	{0x1D, 0xE, 0x3A, 0x1D, 0x57, 0x75, 0x3A, 0xAF, 0x57, 0xEA, 0x107,
1061 	 0x124, 0x15F, 0x186, 0x1B6, 0x1E7}, /*LG 40M*/
1062 	{0x11, 0x8, 0x22, 0x11, 0x33, 0x44, 0x22, 0x67, 0x33, 0x89, 0x9A, 0xAC,
1063 	 0xCE, 0xE5, 0x102, 0x11E}, /*SG 20M*/
1064 	{0x10, 0x8, 0x20, 0x10, 0x30, 0x41, 0x20, 0x61, 0x30, 0x82, 0x92, 0xA2,
1065 	 0xC3, 0xD8, 0xF3, 0x10E}, /*MG 20M*/
1066 	{0xE, 0x7, 0x1D, 0xE, 0x2B, 0x3A, 0x1D, 0x57, 0x2B, 0x75, 0x83, 0x92,
1067 	 0xAF, 0xC3, 0xDB, 0xF3} /*LG 20M*/
1068 };
1069 
1070 #if 0
1071 // note: the value in the table is 2 multiplier of the actual rate
1072 t_u16 ax_tone_ru_rate_nss1[9][MCS_NUM_AX + 4] = {
1073 	{0x8, 0x4, 0xF, 0x8, 0x17, 0x1E, 0xF, 0x2D, 0x17, 0x3C, 0x44, 0x4B,
1074 	 0x5A, 0x64, 0x71, 0x7D}, /*SG 106-tone*/
1075 	{0x7, 0x4, 0xF, 0x7, 0x16, 0x1D, 0xF, 0x2B, 0x16, 0x39, 0x40, 0x47,
1076 	 0x55, 0x5F, 0x6B, 0x76}, /*MG 106-tone*/
1077 	{0x7, 0x3, 0xD, 0x6, 0x14, 0x1A, 0xD, 0x27, 0x14, 0x33, 0x3A, 0x40,
1078 	 0x4D, 0x55, 0x60, 0x6B}, /*LG 106-tone*/
1079 	{0x4, 0x2, 0x7, 0x4, 0xB, 0xF, 0x7, 0x16, 0xB, 0x1D, 0x20, 0x22, 0x2B,
1080 	 0x2F, 0x35, 0x3B}, /*SG 52-tone*/
1081 	{0x4, 0x2, 0x7, 0x4, 0xA, 0xE, 0x7, 0x14, 0xA, 0x1B, 0x1E, 0x22, 0x28,
1082 	 0x2D, 0x32, 0x38}, /*MG 52-tone*/
1083 	{0x3, 0x2, 0x6, 0x3, 0x9, 0xC, 0x6, 0x12, 0x9, 0x18, 0x1B, 0x1E, 0x24,
1084 	 0x28, 0x2D, 0x32}, /*LG 52-tone*/
1085 	{0x2, 0x1, 0x4, 0x2, 0x6, 0x7, 0x4, 0xB, 0x5, 0xE, 0x10, 0x12, 0x15,
1086 	 0x18, 0x1A, 0x1D}, /*SG 26-tone*/
1087 	{0x2, 0x1, 0x4, 0x2, 0x5, 0x6, 0x4, 0xA, 0x5, 0xD, 0xF, 0x11, 0x14,
1088 	 0x16, 0x19, 0x1C}, /*MG 26-tone*/
1089 	{0x2, 0x1, 0x3, 0x2, 0x5, 0x6, 0x3, 0x9, 0x4, 0xC, 0xE, 0xF, 0x12, 0x14,
1090 	 0x17, 0x19} /*LG 26-tone*/
1091 };
1092 #endif
1093 
1094 // note: the value in the table is 2 multiplier of the actual rate
1095 static t_u16 ax_mcs_rate_nss2[12][MCS_NUM_AX + 4] = {
1096 	{0x120, 0x90, 0x240, 0x120, 0x360, 0x481, 0x240, 0x61C, 0x360, 0x901,
1097 	 0xA22, 0xB42, 0xD82, 0xF03, 0x10E3, 0x12C3}, /*SG 160M*/
1098 	{0x110, 0x88, 0x220, 0x110, 0x330, 0x440, 0x220, 0x661, 0x330, 0x881,
1099 	 0x992, 0xAA2, 0xCAC, 0xE2D, 0xFF3, 0x11B9}, /*MG 160M*/
1100 	{0xF5, 0x7A, 0x1EA, 0xF5, 0x2DF, 0x3D4, 0x1EA, 0x5BE, 0x2DF, 0x7A8,
1101 	 0x1134, 0x992, 0xB7C, 0xCC2, 0xE5B, 0xFF3}, /*LG 160M*/
1102 	{0x90, 0x48, 0x120, 0x90, 0x1B0, 0x240, 0x120, 0x360, 0x1B0, 0x481,
1103 	 0x511, 0x5A1, 0x6C1, 0x781, 0x871, 0x962}, /*SG 80M*/
1104 	{0x88, 0x44, 0x110, 0x88, 0x198, 0x220, 0x110, 0x330, 0x198, 0x440,
1105 	 0x4C9, 0x551, 0x661, 0x716, 0x7F9, 0x8DC}, /*MG 80M*/
1106 	{0x7A, 0x3D, 0xF5, 0x7A, 0x16F, 0x1EA, 0xF5, 0x2DF, 0x16F, 0x3D4, 0x44E,
1107 	 0x4C9, 0x5BE, 0x661, 0x72D, 0x7F9}, /*LG 80M*/
1108 	{0x44, 0x22, 0x89, 0x44, 0xCE, 0x113, 0x89, 0x19D, 0xCE, 0x226, 0x26B,
1109 	 0x2B0, 0x339, 0x395, 0x408, 0x47B}, /*SG 40M*/
1110 	{0x41, 0x20, 0x82, 0x41, 0xC3, 0x104, 0x82, 0x186, 0xC3, 0x208, 0x249,
1111 	 0x28A, 0x30C, 0x362, 0x3CE, 0x43B}, /*MG 40M*/
1112 	{0x3A, 0x1D, 0x75, 0x3A, 0xAF, 0xEA, 0x75, 0x15F, 0xAF, 0x1D4, 0x20E,
1113 	 0x249, 0x2BE, 0x30C, 0x36D, 0x3CF}, /*LG 40M*/
1114 	{0x22, 0x11, 0x44, 0x22, 0x67, 0x89, 0x44, 0xCE, 0x67, 0x113, 0x135,
1115 	 0x158, 0x19D, 0x1CA, 0x204, 0x23D}, /*SG 20M*/
1116 	{0x20, 0x10, 0x41, 0x20, 0x61, 0x82, 0x41, 0xC3, 0x61, 0x104, 0x124,
1117 	 0x145, 0x186, 0x1B1, 0x1E7, 0x21D}, /*MG 20M*/
1118 	{0x1D, 0xE, 0x3A, 0x1D, 0x57, 0x75, 0x3A, 0xAF, 0x57, 0xEA, 0x107,
1119 	 0x124, 0x15F, 0x186, 0x1B6, 0x1E7} /*LG 20M*/
1120 };
1121 
1122 #if 0
1123 // note: the value in the table is 2 multiplier of the actual rate
1124 t_u16 ax_tone_ru_rate_nss2[9][MCS_NUM_AX + 4] = {
1125 	{0xF, 0x8, 0x1E, 0xF, 0x2D, 0x3C, 0x1E, 0x5A, 0x2D, 0x78, 0x87, 0x96,
1126 	 0xB4, 0xC8, 0xE1, 0xFA}, /*SG 106-tone*/
1127 	{0xE, 0x7, 0x1D, 0xE, 0x2B, 0x39, 0x1D, 0x55, 0x2B, 0x72, 0x80, 0x8E,
1128 	 0xAA, 0xBD, 0xD5, 0xED}, /*MG 106-tone*/
1129 	{0xD, 0x7, 0x1A, 0xD, 0x27, 0x33, 0x1A, 0x4D, 0x27, 0x66, 0x73, 0x80,
1130 	 0x99, 0xAA, 0xC0, 0xD5}, /*LG 106-tone*/
1131 	{0x7, 0x4, 0xF, 0x7, 0x16, 0x1D, 0xF, 0x2A, 0x16, 0x39, 0x40, 0x47,
1132 	 0x55, 0x5F, 0x6A, 0x76}, /*SG 52-tone*/
1133 	{0x7, 0x4, 0xE, 0x7, 0x14, 0x1B, 0xE, 0x28, 0x14, 0x36, 0x3C, 0x43,
1134 	 0x50, 0x59, 0x64, 0x70}, /*MG 52-tone*/
1135 	{0x6, 0x3, 0xC, 0x6, 0x12, 0x18, 0xC, 0x24, 0x12, 0x30, 0x36, 0x3C,
1136 	 0x48, 0x50, 0x5A, 0x64}, /*LG 52-tone*/
1137 	{0x4, 0x2, 0x7, 0x4, 0xB, 0xF, 0x7, 0x16, 0xB, 0x1D, 0x20, 0x22, 0x2B,
1138 	 0x2F, 0x35, 0x3B}, /*SG 26-tone*/
1139 	{0x4, 0x2, 0x7, 0x4, 0xA, 0xE, 0x7, 0x14, 0xA, 0x1B, 0x1E, 0x22, 0x28,
1140 	 0x2D, 0x32, 0x38}, /*MG 26-tone*/
1141 	{0x3, 0x2, 0x6, 0x3, 0x9, 0xC, 0x6, 0x12, 0x9, 0x18, 0x1B, 0x1E, 0x24,
1142 	 0x28, 0x2D, 0x32} /*LG 26-tone*/
1143 };
1144 #endif
1145 
1146 /********************************************************
1147  *			Local Functions
1148  ********************************************************/
1149 /**
1150  *  @brief Find a character in a string.
1151  *
1152  *  @param pmadapter    A pointer to mlan_adapter structure
1153  *  @param s            A pointer to string
1154  *  @param c            Character to be located
1155  *  @param n            The length of string
1156  *
1157  *  @return        A pointer to the first occurrence of c in string, or MNULL if
1158  * c is not found.
1159  */
wlan_memchr(pmlan_adapter pmadapter,void * s,int c,int n)1160 static void *wlan_memchr(pmlan_adapter pmadapter, void *s, int c, int n)
1161 {
1162 	const t_u8 *p = (t_u8 *)s;
1163 
1164 	ENTER();
1165 
1166 	while (n--) {
1167 		if ((t_u8)c == *p++) {
1168 			LEAVE();
1169 			return (void *)(p - 1);
1170 		}
1171 	}
1172 
1173 	LEAVE();
1174 	return MNULL;
1175 }
1176 
1177 /**
1178  *  @brief This function finds the CFP in
1179  *          cfp_table_BG/A based on region/code and band parameter.
1180  *
1181  *  @param pmadapter  A pointer to mlan_adapter structure
1182  *  @param region     The region code
1183  *  @param band       The band
1184  *  @param cfp_no     A pointer to CFP number
1185  *
1186  *  @return           A pointer to CFP
1187  */
wlan_get_region_cfp_table(pmlan_adapter pmadapter,t_u8 region,t_u16 band,int * cfp_no)1188 static chan_freq_power_t *wlan_get_region_cfp_table(pmlan_adapter pmadapter,
1189 						    t_u8 region, t_u16 band,
1190 						    int *cfp_no)
1191 {
1192 	t_u32 i;
1193 	t_u8 cfp_bg, cfp_a;
1194 
1195 	ENTER();
1196 
1197 	cfp_bg = cfp_a = region;
1198 	if (!region) {
1199 		/* Invalid region code, use CFP code */
1200 		cfp_bg = pmadapter->cfp_code_bg;
1201 		cfp_a = pmadapter->cfp_code_a;
1202 	}
1203 
1204 	if (band & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
1205 		/* Return the FW cfp table for requested region code, if
1206 		 * available. If region is not forced and the requested region
1207 		 * code is different, simply return the corresponding
1208 		 * pre-defined table.
1209 		 */
1210 		if (pmadapter->otp_region && pmadapter->cfp_otp_bg) {
1211 			if (pmadapter->otp_region->force_reg ||
1212 			    (cfp_bg ==
1213 			     (t_u8)pmadapter->otp_region->region_code)) {
1214 				*cfp_no = pmadapter->tx_power_table_bg_rows;
1215 				LEAVE();
1216 				return pmadapter->cfp_otp_bg;
1217 			}
1218 		}
1219 		for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
1220 			PRINTM(MINFO, "cfp_table_BG[%d].code=%d\n", i,
1221 			       cfp_table_BG[i].code);
1222 			/* Check if region/code matches for BG bands */
1223 			if (cfp_table_BG[i].code == cfp_bg) {
1224 				/* Select by band */
1225 				*cfp_no = cfp_table_BG[i].cfp_no;
1226 				LEAVE();
1227 				return cfp_table_BG[i].cfp;
1228 			}
1229 		}
1230 	}
1231 	if (band & (BAND_A | BAND_AN | BAND_AAC)) {
1232 		/* Return the FW cfp table for requested region code */
1233 		if (pmadapter->otp_region && pmadapter->cfp_otp_a) {
1234 			if (pmadapter->otp_region->force_reg ||
1235 			    (cfp_a ==
1236 			     (t_u8)pmadapter->otp_region->region_code)) {
1237 				*cfp_no = pmadapter->tx_power_table_a_rows;
1238 				LEAVE();
1239 				return pmadapter->cfp_otp_a;
1240 			}
1241 		}
1242 		for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
1243 			PRINTM(MINFO, "cfp_table_A[%d].code=%d\n", i,
1244 			       cfp_table_A[i].code);
1245 			/* Check if region/code matches for A bands */
1246 			if (cfp_table_A[i].code == cfp_a) {
1247 				/* Select by band */
1248 				*cfp_no = cfp_table_A[i].cfp_no;
1249 				LEAVE();
1250 				return cfp_table_A[i].cfp;
1251 			}
1252 		}
1253 	}
1254 	if (!region)
1255 		PRINTM(MERROR, "Error Band[0x%x] or code[BG:%#x, A:%#x]\n",
1256 		       band, cfp_bg, cfp_a);
1257 	else
1258 		PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band,
1259 		       region);
1260 
1261 	LEAVE();
1262 	return MNULL;
1263 }
1264 
1265 /**
1266  *  @brief This function copies dynamic CFP elements from one table to another.
1267  *         Only copy elements where channel numbers match.
1268  *
1269  *  @param pmadapter   A pointer to mlan_adapter structure
1270  *  @param cfp         Destination table
1271  *  @param num_cfp     Number of elements in dest table
1272  *  @param cfp_src     Source table
1273  *  @param num_cfp_src Number of elements in source table
1274  */
wlan_cfp_copy_dynamic(pmlan_adapter pmadapter,chan_freq_power_t * cfp,t_u8 num_cfp,chan_freq_power_t * cfp_src,t_u8 num_cfp_src)1275 static t_void wlan_cfp_copy_dynamic(pmlan_adapter pmadapter,
1276 				    chan_freq_power_t *cfp, t_u8 num_cfp,
1277 				    chan_freq_power_t *cfp_src,
1278 				    t_u8 num_cfp_src)
1279 {
1280 	int i, j;
1281 
1282 	ENTER();
1283 
1284 	if (cfp == cfp_src) {
1285 		LEAVE();
1286 		return;
1287 	}
1288 
1289 	/* first clear dest dynamic blacklisted entries */
1290 	/* do not clear the flags */
1291 	for (i = 0; i < num_cfp; i++) {
1292 		cfp[i].dynamic.blacklist = MFALSE;
1293 		cfp[i].dynamic.dfs_state = DFS_USABLE;
1294 	}
1295 
1296 	/* copy dynamic blacklisted entries from source where channels match */
1297 	if (cfp_src) {
1298 		for (i = 0; i < num_cfp; i++)
1299 			for (j = 0; j < num_cfp_src; j++)
1300 				if (cfp[i].channel == cfp_src[j].channel) {
1301 					cfp[i].dynamic.blacklist =
1302 						cfp_src[j].dynamic.blacklist;
1303 					cfp[i].dynamic.dfs_state =
1304 						cfp_src[j].dynamic.dfs_state;
1305 					break;
1306 				}
1307 	}
1308 
1309 	LEAVE();
1310 }
1311 
1312 /********************************************************
1313  *			Global Functions
1314  ********************************************************/
1315 /**
1316  *  @brief This function converts region string to integer code
1317  *
1318  *  @param pmadapter        A pointer to mlan_adapter structure
1319  *  @param country_code     Country string
1320  *  @param cfp_bg           Pointer to buffer
1321  *  @param cfp_a            Pointer to buffer
1322  *
1323  *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1324  */
wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,t_u8 * country_code,t_u8 * cfp_bg,t_u8 * cfp_a)1325 mlan_status wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,
1326 					       t_u8 *country_code, t_u8 *cfp_bg,
1327 					       t_u8 *cfp_a)
1328 {
1329 	t_u8 i;
1330 
1331 	ENTER();
1332 
1333 	if (pmadapter->otp_region) {
1334 		if (!memcmp(pmadapter, pmadapter->otp_region->country_code,
1335 			    country_code, COUNTRY_CODE_LEN - 1)) {
1336 			if (pmadapter->cfp_otp_bg)
1337 				*cfp_bg = pmadapter->otp_region->region_code;
1338 			if (pmadapter->cfp_otp_a)
1339 				*cfp_a = pmadapter->otp_region->region_code;
1340 			LEAVE();
1341 			return MLAN_STATUS_SUCCESS;
1342 		}
1343 	}
1344 	/* Look for code in mapping table */
1345 	for (i = 0; i < NELEMENTS(country_code_mapping); i++) {
1346 		if (!memcmp(pmadapter, country_code_mapping[i].country_code,
1347 			    country_code, COUNTRY_CODE_LEN - 1)) {
1348 			*cfp_bg = country_code_mapping[i].cfp_code_bg;
1349 			*cfp_a = country_code_mapping[i].cfp_code_a;
1350 			LEAVE();
1351 			return MLAN_STATUS_SUCCESS;
1352 		}
1353 	}
1354 
1355 	/* If still not found, look for code in EU country code table */
1356 	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
1357 		if (!memcmp(pmadapter, eu_country_code_table[i], country_code,
1358 			    COUNTRY_CODE_LEN - 1)) {
1359 			*cfp_bg = EU_CFP_CODE_BG;
1360 			*cfp_a = EU_CFP_CODE_A;
1361 			LEAVE();
1362 			return MLAN_STATUS_SUCCESS;
1363 		}
1364 	}
1365 
1366 	LEAVE();
1367 	return MLAN_STATUS_FAILURE;
1368 }
1369 
1370 /**
1371  *  @brief This function finds if given country code is in EU table
1372  *
1373  *  @param pmadapter        A pointer to mlan_adapter structure
1374  *  @param country_code     Country string
1375  *
1376  *  @return                 MTRUE or MFALSE
1377  */
wlan_is_etsi_country(pmlan_adapter pmadapter,t_u8 * country_code)1378 t_bool wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
1379 {
1380 	t_u8 i;
1381 
1382 	ENTER();
1383 
1384 	/* Look for code in EU country code table */
1385 	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
1386 		if (!memcmp(pmadapter, eu_country_code_table[i], country_code,
1387 			    COUNTRY_CODE_LEN - 1)) {
1388 			LEAVE();
1389 			return MTRUE;
1390 		}
1391 	}
1392 
1393 	LEAVE();
1394 	return MFALSE;
1395 }
1396 
1397 /**
1398  *   @brief This function adjust the antenna index
1399  *
1400  *   V16_FW_API: Bit0: ant A, Bit 1:ant B, Bit0 & Bit 1: A+B
1401  *   8887: case1: 0 - 2.4G ant A,  1- 2.4G antB, 2-- 5G ant C
1402  *   case2: 0 - 2.4G ant A,  1- 2.4G antB, 0x80- 5G antA, 0x81-5G ant B
1403  *   @param priv	A pointer to mlan_private structure
1404  *   @param prx_pd	A pointer to the RxPD structure
1405  *
1406  *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1407  */
wlan_adjust_antenna(pmlan_private priv,RxPD * prx_pd)1408 t_u8 wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd)
1409 {
1410 	t_u8 antenna = prx_pd->antenna;
1411 #if defined(SD8887) || defined(SD8987)
1412 	t_u32 rx_channel = (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
1413 #endif
1414 	if (prx_pd->antenna == 0xff)
1415 		return 0;
1416 	if (priv->adapter->pcard_info->v16_fw_api) {
1417 		if ((antenna & MBIT(0)) && (antenna & MBIT(1)))
1418 			antenna = 2;
1419 		else if (antenna & MBIT(1))
1420 			antenna = 1;
1421 		else if (antenna & MBIT(0))
1422 			antenna = 0;
1423 	}
1424 
1425 #if defined(SD8887) || defined(SD8987)
1426 #define ANTENNA_OFFSET 2
1427 	if (MFALSE
1428 #ifdef SD8887
1429 	    || IS_SD8887(priv->adapter->card_type)
1430 #endif
1431 #ifdef SD8987
1432 	    || IS_SD8987(priv->adapter->card_type)
1433 #endif
1434 	) {
1435 		if ((priv->adapter->antinfo & ANT_DIVERSITY_2G) &&
1436 		    (priv->adapter->antinfo & ANT_DIVERSITY_5G)) {
1437 #define MAX_2G_CHAN 14
1438 			if (rx_channel > MAX_2G_CHAN)
1439 				antenna += ANTENNA_OFFSET;
1440 		}
1441 	}
1442 #endif
1443 
1444 	return antenna;
1445 }
1446 
1447 /**
1448  *  @brief This function adjust the rate index
1449  *
1450  *  @param priv    A pointer to mlan_private structure
1451  *  @param rx_rate rx rate
1452  *  @param rate_info rate info
1453  *  @return        rate index
1454  */
wlan_adjust_data_rate(mlan_private * priv,t_u8 rx_rate,t_u8 rate_info)1455 t_u16 wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info)
1456 {
1457 	t_u16 rate_index = 0;
1458 	t_u8 bw = 0;
1459 	t_u8 nss = 0;
1460 	t_bool sgi_enable = 0;
1461 	t_u8 gi = 0;
1462 #define MAX_MCS_NUM_AX 12
1463 
1464 #define MAX_MCS_NUM_SUPP 16
1465 #define MAX_MCS_NUM_AC 10
1466 #define RATE_INDEX_MCS0 12
1467 	bw = (rate_info & 0xC) >> 2;
1468 	sgi_enable = (rate_info & 0x10) >> 4;
1469 	if ((rate_info & 0x3) == 0) {
1470 		rate_index = (rx_rate > MLAN_RATE_INDEX_OFDM0) ? rx_rate - 1 :
1471 								 rx_rate;
1472 	} else if ((rate_info & 0x03) == 1) {
1473 		rate_index = RATE_INDEX_MCS0 +
1474 			     MAX_MCS_NUM_SUPP * 2 * sgi_enable +
1475 			     MAX_MCS_NUM_SUPP * bw + rx_rate;
1476 	} else if ((rate_info & 0x3) == 2) {
1477 		if (IS_STREAM_2X2(priv->adapter->feature_control))
1478 			nss = rx_rate >> 4; // 0:NSS1, 1:NSS2
1479 		rate_index = RATE_INDEX_MCS0 + MAX_MCS_NUM_SUPP * 4 +
1480 			     MAX_MCS_NUM_AC * 6 * sgi_enable +
1481 			     MAX_MCS_NUM_AC * 2 * bw + MAX_MCS_NUM_AC * nss +
1482 			     (rx_rate & 0x0f);
1483 	} else if ((rate_info & 0x3) == 3) {
1484 		gi = (rate_info & 0x10) >> 4 | (rate_info & 0x80) >> 6;
1485 		if (IS_STREAM_2X2(priv->adapter->feature_control))
1486 			nss = rx_rate >> 4; // 0:NSS1, 1:NSS2
1487 		rate_index = RATE_INDEX_MCS0 + MAX_MCS_NUM_SUPP * 4 +
1488 			     MAX_MCS_NUM_AC * 12 + MAX_MCS_NUM_AX * 6 * gi +
1489 			     MAX_MCS_NUM_AX * 2 * bw + MAX_MCS_NUM_AX * nss +
1490 			     (rx_rate & 0x0f);
1491 	}
1492 	return rate_index;
1493 }
1494 
1495 #ifdef STA_SUPPORT
1496 #endif /* STA_SUPPORT */
1497 
1498 /**
1499  *  @brief convert TX rate_info from v14 to v15+ FW rate_info
1500  *
1501  *  @param v14_rate_info      v14 rate info
1502  *
1503  *  @return             v15+ rate info
1504  */
wlan_convert_v14_tx_rate_info(pmlan_private pmpriv,t_u8 v14_rate_info)1505 t_u8 wlan_convert_v14_tx_rate_info(pmlan_private pmpriv, t_u8 v14_rate_info)
1506 {
1507 	t_u8 rate_info = 0;
1508 
1509 	if (!pmpriv->adapter->pcard_info->v14_fw_api) {
1510 		PRINTM(MERROR, "%s: Not convert for this is not V14 FW\n",
1511 		       __func__);
1512 		return v14_rate_info;
1513 	}
1514 
1515 	rate_info = v14_rate_info & 0x01;
1516 	/* band */
1517 	rate_info |= (v14_rate_info & MBIT(1)) << 1;
1518 	/* short GI */
1519 	rate_info |= (v14_rate_info & MBIT(2)) << 2;
1520 	return rate_info;
1521 }
1522 
1523 /**
1524  *  @brief convert RX rate_info from v14 to v15+ FW rate_info
1525  *
1526  *  @param v14_rate_info      v14 rate info
1527  *
1528  *  @return             v15+ rate info
1529  */
wlan_convert_v14_rx_rate_info(pmlan_private pmpriv,t_u8 v14_rate_info)1530 t_u8 wlan_convert_v14_rx_rate_info(pmlan_private pmpriv, t_u8 v14_rate_info)
1531 {
1532 	t_u8 rate_info = 0;
1533 	t_u8 mode = 0;
1534 	t_u8 bw = 0;
1535 	t_u8 sgi = 0;
1536 
1537 	if (!pmpriv->adapter->pcard_info->v14_fw_api) {
1538 		PRINTM(MERROR, "%s: Not convert for this is not V14 FW\n",
1539 		       __func__);
1540 		return v14_rate_info;
1541 	}
1542 
1543 	mode = v14_rate_info & MBIT(0);
1544 	bw = v14_rate_info & MBIT(1);
1545 	sgi = (v14_rate_info & 0x04) >> 2;
1546 
1547 	rate_info = (mode & 0x01) | ((bw & 0x01) << 2) | ((sgi & 0x01) << 4);
1548 
1549 	return rate_info;
1550 }
1551 
1552 /**
1553  *  @brief Use index to get the data rate
1554  *
1555  *  @param pmadapter        A pointer to mlan_adapter structure
1556  *  @param index            The index of data rate
1557  *  @param tx_rate_info     Tx rate info
1558  *  @param ext_rate_info    Extend tx rate info
1559  *
1560  *  @return                 Data rate or 0
1561  */
wlan_index_to_data_rate(pmlan_adapter pmadapter,t_u8 index,t_u8 tx_rate_info,t_u8 ext_rate_info)1562 t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index,
1563 			      t_u8 tx_rate_info, t_u8 ext_rate_info)
1564 {
1565 #define MCS_NUM_SUPP 16
1566 	t_u16 mcs_rate[4][MCS_NUM_SUPP] = {
1567 		{0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, 0x36, 0x6c,
1568 		 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c}, /*LG 40M*/
1569 		{0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, 0x3c, 0x78,
1570 		 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258}, /*SG 40M */
1571 		{0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, 0x1a, 0x34,
1572 		 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104}, /*LG 20M */
1573 		{0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 0x1c, 0x39,
1574 		 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120}}; /*SG 20M */
1575 
1576 #define MCS_NUM_AC 10
1577 	/* NSS 1. note: the value in the table is 2 multiplier of the actual
1578 	 * rate in other words, it is in the unit of 500 Kbs
1579 	 */
1580 	t_u16 ac_mcs_rate_nss1[8][MCS_NUM_AC] = {
1581 		{0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C,
1582 		 0x618}, /* LG 160M*/
1583 		{0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618,
1584 		 0x6C6}, /* SG 160M*/
1585 		{0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, 0x249, 0x2BE,
1586 		 0x30C}, /* LG 80M */
1587 		{0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, 0x28A, 0x30C,
1588 		 0x363}, /* SG 80M */
1589 		{0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x144,
1590 		 0x168}, /* LG 40M */
1591 		{0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, 0x12C, 0x168,
1592 		 0x190}, /* SG 40M */
1593 		{0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C,
1594 		 0x00}, /* LG 20M */
1595 		{0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE,
1596 		 0x00}, /* SG 20M */
1597 	};
1598 	/* NSS 2. note: the value in the table is 2 multiplier of the actual
1599 	 * rate
1600 	 */
1601 	t_u16 ac_mcs_rate_nss2[8][MCS_NUM_AC] = {
1602 		{0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, 0x924, 0xAF8,
1603 		 0xC30}, /*LG 160M*/
1604 		{0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, 0xA28, 0xC30,
1605 		 0xD8B}, /*SG 160M*/
1606 
1607 		{0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C,
1608 		 0x618}, /*LG 80M*/
1609 		{0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618,
1610 		 0x6C6}, /*SG 80M*/
1611 		{0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, 0x21C, 0x288,
1612 		 0x2D0}, /*LG 40M*/
1613 		{0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, 0x258, 0x2D0,
1614 		 0x320}, /*SG 40M*/
1615 		{0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, 0x138,
1616 		 0x00}, /*LG 20M*/
1617 		{0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, 0x15B,
1618 		 0x00}, /*SG 20M*/
1619 	};
1620 
1621 	t_u32 rate = 0;
1622 	t_u8 mcs_index = 0;
1623 	t_u8 he_dcm = 0;
1624 	//	t_u8 he_tone = 0;
1625 	t_u8 stbc = 0;
1626 
1627 	t_u8 bw = 0;
1628 	t_u8 gi = 0;
1629 
1630 	ENTER();
1631 
1632 	PRINTM(MINFO, "%s:index=%d, tx_rate_info=%d, ext_rate_info=%d\n",
1633 	       __func__, index, tx_rate_info, ext_rate_info);
1634 
1635 	if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_VHT) {
1636 		/* VHT rate */
1637 		mcs_index = index & 0xF;
1638 
1639 		if (mcs_index > 9)
1640 			mcs_index = 9;
1641 
1642 		/* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
1643 		bw = (tx_rate_info & 0xC) >> 2;
1644 		/* LGI: gi =0, SGI: gi = 1 */
1645 		gi = (tx_rate_info & 0x10) >> 4;
1646 		if ((index >> 4) == 1) {
1647 			/* NSS = 2 */
1648 			rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
1649 		} else
1650 			/* NSS = 1 */
1651 			rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];
1652 	} else
1653 
1654 		if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HE) {
1655 		/* VHT rate */
1656 		mcs_index = index & 0xF;
1657 		he_dcm = ext_rate_info & MBIT(0);
1658 
1659 		if (mcs_index > MCS_NUM_AX - 1)
1660 			mcs_index = MCS_NUM_AX - 1;
1661 
1662 		/* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
1663 		bw = (tx_rate_info & (MBIT(3) | MBIT(2))) >> 2;
1664 		/* BIT7:BIT4 0:0= 0.8us,0:1= 0.8us, 1:0=1.6us, 1:1=3.2us or
1665 		 * 0.8us
1666 		 */
1667 		gi = (tx_rate_info & MBIT(4)) >> 4 |
1668 		     (tx_rate_info & MBIT(7)) >> 6;
1669 		/* STBC: BIT5 in tx rate info */
1670 		stbc = (tx_rate_info & MBIT(5)) >> 5;
1671 
1672 		if (gi > 3) {
1673 			PRINTM(MERROR, "Invalid gi value");
1674 			return 0;
1675 		}
1676 
1677 		if ((gi == 3) && stbc && he_dcm) {
1678 			gi = 0;
1679 			stbc = 0;
1680 			he_dcm = 0;
1681 		}
1682 		/* map to gi 0:0.8us,1:1.6us 2:3.2us*/
1683 		if (gi > 0)
1684 			gi = gi - 1;
1685 
1686 		//#ifdef ENABLE_802_11AX
1687 		// TODO: hardcode he_tone here, wait for FW value ready.
1688 		//		he_tone = 4;
1689 
1690 		// he_tone = (ext_rate_info & 0xE) >> 1;
1691 		//#endif
1692 
1693 		if ((index >> 4) == 1) {
1694 			switch (mcs_index) {
1695 			case 0:
1696 			case 1:
1697 				// #if 0
1698 				// if (he_tone < 3) {
1699 				//	rate =
1700 				//ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2
1701 				//+ he_dcm];
1702 				// } else {
1703 				// #endif
1704 				rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
1705 						       [mcs_index * 2 + he_dcm];
1706 				break;
1707 			case 2:
1708 				// #if 0
1709 				// if (he_tone < 3) {
1710 				//	rate =
1711 				//ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2];
1712 				// } else {
1713 				// #endif
1714 				rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
1715 						       [mcs_index * 2];
1716 				break;
1717 			case 3:
1718 			case 4:
1719 				// #if 0
1720 				// if (he_tone < 3) {
1721 				//	rate =
1722 				//ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2
1723 				//- 1 + he_dcm];
1724 				// } else {
1725 				// #endif
1726 				rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
1727 						       [mcs_index * 2 - 1 +
1728 							he_dcm];
1729 				break;
1730 
1731 			default:
1732 				// #if 0
1733 				// if (he_tone < 3) {
1734 				//	rate =
1735 				//ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index
1736 				//+ 4];
1737 				// } else {
1738 				// #endif
1739 				rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
1740 						       [mcs_index + 4];
1741 				break;
1742 			}
1743 		} else {
1744 			switch (mcs_index) {
1745 			case 0:
1746 			case 1:
1747 				// #if 0
1748 				// if (he_tone < 3) {
1749 				//	rate =
1750 				//ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2
1751 				//+ he_dcm];
1752 				// } else {
1753 				// #endif
1754 				rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
1755 						       [mcs_index * 2 + he_dcm];
1756 				break;
1757 			case 2:
1758 				// #if 0
1759 				// if (he_tone < 3) {
1760 				//	rate =
1761 				//ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2];
1762 				// } else {
1763 				// #endif
1764 				rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
1765 						       [mcs_index * 2];
1766 				break;
1767 			case 3:
1768 			case 4:
1769 				// #if 0
1770 				// if (he_tone < 3) {
1771 				//	rate =
1772 				//ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2
1773 				//- 1 + he_dcm];
1774 				// } else {
1775 				// #endif
1776 				rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
1777 						       [mcs_index * 2 - 1 +
1778 							he_dcm];
1779 				break;
1780 
1781 			default:
1782 				// #if 0
1783 				// if (he_tone < 3) {
1784 				//	rate =
1785 				//ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index
1786 				//+ 4];
1787 				// } else {
1788 				// #endif
1789 				rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
1790 						       [mcs_index + 4];
1791 				break;
1792 			}
1793 		}
1794 	} else if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
1795 		/* HT rate */
1796 		/* 20M: bw=0, 40M: bw=1 */
1797 		bw = (tx_rate_info & 0xC) >> 2;
1798 		/* LGI: gi =0, SGI: gi = 1 */
1799 		gi = (tx_rate_info & 0x10) >> 4;
1800 		if (index == MLAN_RATE_BITMAP_MCS0) {
1801 			if (gi == 1)
1802 				rate = 0x0D; /* MCS 32 SGI rate */
1803 			else
1804 				rate = 0x0C; /* MCS 32 LGI rate */
1805 		} else if (index < MCS_NUM_SUPP) {
1806 			if (bw <= 1)
1807 				rate = mcs_rate[2 * (1 - bw) + gi][index];
1808 			else
1809 				rate = WlanDataRates[0];
1810 		} else
1811 			rate = WlanDataRates[0];
1812 	} else {
1813 		/* 11n non HT rates */
1814 		if (index >= WLAN_SUPPORTED_RATES_EXT)
1815 			index = 0;
1816 		rate = WlanDataRates[index];
1817 	}
1818 	LEAVE();
1819 	return rate;
1820 }
1821 
1822 /**
1823  *  @brief Use rate to get the index
1824  *
1825  *  @param pmadapter    A pointer to mlan_adapter structure
1826  *  @param rate         Data rate
1827  *
1828  *  @return                     Index or 0
1829  */
wlan_data_rate_to_index(pmlan_adapter pmadapter,t_u32 rate)1830 t_u8 wlan_data_rate_to_index(pmlan_adapter pmadapter, t_u32 rate)
1831 {
1832 	t_u16 *ptr;
1833 
1834 	ENTER();
1835 	if (rate) {
1836 		ptr = wlan_memchr(pmadapter, WlanDataRates, (t_u8)rate,
1837 				  sizeof(WlanDataRates));
1838 		if (ptr) {
1839 			LEAVE();
1840 			return (t_u8)(ptr - WlanDataRates);
1841 		}
1842 	}
1843 	LEAVE();
1844 	return 0;
1845 }
1846 
1847 /**
1848  *  @brief Get active data rates
1849  *
1850  *  @param pmpriv           A pointer to mlan_private structure
1851  *  @param bss_mode         The specified BSS mode (Infra/IBSS)
1852  *  @param config_bands     The specified band configuration
1853  *  @param rates            The buf to return the active rates
1854  *
1855  *  @return                 The number of Rates
1856  */
wlan_get_active_data_rates(mlan_private * pmpriv,t_u32 bss_mode,t_u16 config_bands,WLAN_802_11_RATES rates)1857 t_u32 wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
1858 				 t_u16 config_bands, WLAN_802_11_RATES rates)
1859 {
1860 	t_u32 k;
1861 
1862 	ENTER();
1863 
1864 	if (pmpriv->media_connected != MTRUE) {
1865 		k = wlan_get_supported_rates(pmpriv, bss_mode, config_bands,
1866 					     rates);
1867 	} else {
1868 		k = wlan_copy_rates(rates, 0,
1869 				    pmpriv->curr_bss_params.data_rates,
1870 				    pmpriv->curr_bss_params.num_of_rates);
1871 	}
1872 
1873 	LEAVE();
1874 	return k;
1875 }
1876 
1877 #ifdef STA_SUPPORT
1878 /**
1879  *  @brief This function search through all the regions cfp table to find the
1880  * channel, if the channel is found then gets the MIN txpower of the channel
1881  *            present in all the regions.
1882  *
1883  *  @param pmpriv       A pointer to mlan_private structure
1884  *  @param band      	band.
1885  *  @param channel      Channel number.
1886  *
1887  *  @return             The Tx power
1888  */
wlan_get_txpwr_of_chan_from_cfp(mlan_private * pmpriv,t_u16 band,t_u8 channel)1889 t_u8 wlan_get_txpwr_of_chan_from_cfp(mlan_private *pmpriv, t_u16 band,
1890 				     t_u8 channel)
1891 {
1892 	t_u8 i = 0;
1893 	t_u8 j = 0;
1894 	t_u8 tx_power = 0;
1895 	t_u32 cfp_no;
1896 	chan_freq_power_t *cfp = MNULL;
1897 	chan_freq_power_t *cfp_a = MNULL;
1898 	t_u32 cfp_no_a;
1899 
1900 	ENTER();
1901 
1902 	if (band & (BAND_B | BAND_G)) {
1903 		for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
1904 			/* Get CFP */
1905 			cfp = cfp_table_BG[i].cfp;
1906 			cfp_no = cfp_table_BG[i].cfp_no;
1907 			/* Find matching channel and get Tx power */
1908 			for (j = 0; j < cfp_no; j++) {
1909 				if ((cfp + j)->channel == channel) {
1910 					if (tx_power != 0)
1911 						tx_power = MIN(
1912 							tx_power,
1913 							(cfp + j)->max_tx_power);
1914 					else
1915 						tx_power =
1916 							(t_u8)(cfp + j)
1917 								->max_tx_power;
1918 					break;
1919 				}
1920 			}
1921 		}
1922 	}
1923 
1924 	if (band & BAND_A) {
1925 		for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
1926 			/* Get CFP */
1927 			cfp_a = cfp_table_A[i].cfp;
1928 			cfp_no_a = cfp_table_A[i].cfp_no;
1929 			for (j = 0; j < cfp_no_a; j++) {
1930 				if ((cfp_a + j)->channel == channel) {
1931 					if (tx_power != 0)
1932 						tx_power = MIN(
1933 							tx_power,
1934 							(cfp_a + j)
1935 								->max_tx_power);
1936 					else
1937 						tx_power = (t_u8)(
1938 							(cfp_a + j)
1939 								->max_tx_power);
1940 					break;
1941 				}
1942 			}
1943 		}
1944 	}
1945 
1946 	LEAVE();
1947 	return tx_power;
1948 }
1949 
1950 /**
1951  *  @brief Get the channel frequency power info for a specific channel
1952  *
1953  *  @param pmadapter            A pointer to mlan_adapter structure
1954  *  @param band                 It can be BAND_A, BAND_G or BAND_B
1955  *  @param channel              The channel to search for
1956  *  @param region_channel       A pointer to region_chan_t structure
1957  *
1958  *  @return                     A pointer to chan_freq_power_t structure or
1959  * MNULL if not found.
1960  */
1961 
1962 chan_freq_power_t *
wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter,t_u16 band,t_u16 channel,region_chan_t * region_channel)1963 wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter, t_u16 band,
1964 				 t_u16 channel, region_chan_t *region_channel)
1965 {
1966 	region_chan_t *rc;
1967 	chan_freq_power_t *cfp = MNULL;
1968 	int i, j;
1969 
1970 	ENTER();
1971 
1972 	for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
1973 		rc = &region_channel[j];
1974 
1975 		if (!rc->valid || !rc->pcfp)
1976 			continue;
1977 		switch (rc->band) {
1978 		case BAND_A:
1979 			switch (band) {
1980 			case BAND_AN:
1981 			case BAND_A | BAND_AN:
1982 			case BAND_A | BAND_AN | BAND_AAC:
1983 			/* Fall Through */
1984 			case BAND_A: /* Matching BAND_A */
1985 				break;
1986 
1987 			default:
1988 				continue;
1989 			}
1990 			break;
1991 		case BAND_B:
1992 		case BAND_G:
1993 			switch (band) {
1994 			case BAND_GN:
1995 			case BAND_B | BAND_G | BAND_GN:
1996 			case BAND_G | BAND_GN:
1997 			case BAND_GN | BAND_GAC:
1998 			case BAND_B | BAND_G | BAND_GN | BAND_GAC:
1999 			case BAND_G | BAND_GN | BAND_GAC:
2000 			case BAND_B | BAND_G:
2001 			/* Fall Through */
2002 			case BAND_B: /* Matching BAND_B/G */
2003 			/* Fall Through */
2004 			case BAND_G:
2005 			/* Fall Through */
2006 			case 0:
2007 				break;
2008 			default:
2009 				continue;
2010 			}
2011 			break;
2012 		default:
2013 			continue;
2014 		}
2015 		if (channel == FIRST_VALID_CHANNEL)
2016 			cfp = &rc->pcfp[0];
2017 		else {
2018 			for (i = 0; i < rc->num_cfp; i++) {
2019 				if (rc->pcfp[i].channel == channel) {
2020 					cfp = &rc->pcfp[i];
2021 					break;
2022 				}
2023 			}
2024 		}
2025 	}
2026 
2027 	if (!cfp && channel)
2028 		PRINTM(MCMND, "%s: can not find cfp by band %d & channel %d\n",
2029 		       __func__, band, channel);
2030 
2031 	LEAVE();
2032 	return cfp;
2033 }
2034 
2035 /**
2036  *  @brief Find the channel frequency power info for a specific channel
2037  *
2038  *  @param pmadapter    A pointer to mlan_adapter structure
2039  *  @param band         It can be BAND_A, BAND_G or BAND_B
2040  *  @param channel      The channel to search for
2041  *
2042  *  @return             A pointer to chan_freq_power_t structure or MNULL if not
2043  * found.
2044  */
wlan_find_cfp_by_band_and_channel(mlan_adapter * pmadapter,t_u16 band,t_u16 channel)2045 chan_freq_power_t *wlan_find_cfp_by_band_and_channel(mlan_adapter *pmadapter,
2046 						     t_u16 band, t_u16 channel)
2047 {
2048 	chan_freq_power_t *cfp = MNULL;
2049 
2050 	ENTER();
2051 
2052 	/* Any station(s) with 11D enabled */
2053 	if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
2054 				 wlan_is_station) > 0)
2055 		cfp = wlan_get_cfp_by_band_and_channel(
2056 			pmadapter, band, channel, pmadapter->universal_channel);
2057 	else
2058 		cfp = wlan_get_cfp_by_band_and_channel(
2059 			pmadapter, band, channel, pmadapter->region_channel);
2060 
2061 	LEAVE();
2062 	return cfp;
2063 }
2064 
2065 /**
2066  *  @brief Find the channel frequency power info for a specific frequency
2067  *
2068  *  @param pmadapter    A pointer to mlan_adapter structure
2069  *  @param band         It can be BAND_A, BAND_G or BAND_B
2070  *  @param freq         The frequency to search for
2071  *
2072  *  @return         Pointer to chan_freq_power_t structure; MNULL if not found
2073  */
wlan_find_cfp_by_band_and_freq(mlan_adapter * pmadapter,t_u16 band,t_u32 freq)2074 chan_freq_power_t *wlan_find_cfp_by_band_and_freq(mlan_adapter *pmadapter,
2075 						  t_u16 band, t_u32 freq)
2076 {
2077 	chan_freq_power_t *cfp = MNULL;
2078 	region_chan_t *rc;
2079 	int i, j;
2080 
2081 	ENTER();
2082 
2083 	for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
2084 		rc = &pmadapter->region_channel[j];
2085 
2086 		/* Any station(s) with 11D enabled */
2087 		if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
2088 					 wlan_is_station) > 0)
2089 			rc = &pmadapter->universal_channel[j];
2090 
2091 		if (!rc->valid || !rc->pcfp)
2092 			continue;
2093 		switch (rc->band) {
2094 		case BAND_A:
2095 			switch (band) {
2096 			case BAND_AN:
2097 			case BAND_A | BAND_AN:
2098 			case BAND_A | BAND_AN | BAND_AAC:
2099 			/* Fall Through */
2100 			case BAND_A: /* Matching BAND_A */
2101 				break;
2102 			default:
2103 				continue;
2104 			}
2105 			break;
2106 		case BAND_B:
2107 		case BAND_G:
2108 			switch (band) {
2109 			case BAND_GN:
2110 			case BAND_B | BAND_G | BAND_GN:
2111 			case BAND_G | BAND_GN:
2112 			case BAND_GN | BAND_GAC:
2113 			case BAND_B | BAND_G | BAND_GN | BAND_GAC:
2114 			case BAND_G | BAND_GN | BAND_GAC:
2115 			case BAND_B | BAND_G:
2116 			/* Fall Through */
2117 			case BAND_B:
2118 			/* Fall Through */
2119 			case BAND_G:
2120 			/* Fall Through */
2121 			case 0:
2122 				break;
2123 			default:
2124 				continue;
2125 			}
2126 			break;
2127 		default:
2128 			continue;
2129 		}
2130 		for (i = 0; i < rc->num_cfp; i++) {
2131 			if (rc->pcfp[i].freq == freq) {
2132 				cfp = &rc->pcfp[i];
2133 				break;
2134 			}
2135 		}
2136 	}
2137 
2138 	if (!cfp && freq)
2139 		PRINTM(MERROR, "%s: cannot find cfp by band %d & freq %d\n",
2140 		       __func__, band, freq);
2141 
2142 	LEAVE();
2143 	return cfp;
2144 }
2145 #endif /* STA_SUPPORT */
2146 
2147 /**
2148  *  @brief Check if Rate Auto
2149  *
2150  *  @param pmpriv               A pointer to mlan_private structure
2151  *
2152  *  @return                     MTRUE or MFALSE
2153  */
wlan_is_rate_auto(mlan_private * pmpriv)2154 t_u8 wlan_is_rate_auto(mlan_private *pmpriv)
2155 {
2156 	t_u32 i;
2157 	int rate_num = 0;
2158 
2159 	ENTER();
2160 
2161 	for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates); i++)
2162 		if (pmpriv->bitmap_rates[i])
2163 			rate_num++;
2164 
2165 	LEAVE();
2166 	if (rate_num > 1)
2167 		return MTRUE;
2168 	else
2169 		return MFALSE;
2170 }
2171 
2172 /**
2173  *  @brief Covert Rate Bitmap to Rate index
2174  *
2175  *  @param pmadapter    Pointer to mlan_adapter structure
2176  *  @param rate_bitmap  Pointer to rate bitmap
2177  *  @param size         Size of the bitmap array
2178  *
2179  *  @return             Rate index
2180  */
wlan_get_rate_index(pmlan_adapter pmadapter,t_u16 * rate_bitmap,int size)2181 int wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 *rate_bitmap, int size)
2182 {
2183 	int i;
2184 
2185 	ENTER();
2186 
2187 	for (i = 0; i < size * 8; i++) {
2188 		if (rate_bitmap[i / 16] & (1 << (i % 16))) {
2189 			LEAVE();
2190 			return i;
2191 		}
2192 	}
2193 
2194 	LEAVE();
2195 	return -1;
2196 }
2197 
2198 /**
2199  *  @brief Convert config_bands to B/G/A band
2200  *
2201  *  @param config_bands     The specified band configuration
2202  *
2203  *  @return                 BAND_B|BAND_G|BAND_A
2204  */
wlan_convert_config_bands(t_u16 config_bands)2205 t_u16 wlan_convert_config_bands(t_u16 config_bands)
2206 {
2207 	t_u16 bands = 0;
2208 	if (config_bands & BAND_B)
2209 		bands |= BAND_B;
2210 	if (config_bands & BAND_G || config_bands & BAND_GN ||
2211 	    config_bands & BAND_GAC || config_bands & BAND_GAX)
2212 		bands |= BAND_G;
2213 	if (config_bands & BAND_A || config_bands & BAND_AN ||
2214 	    config_bands & BAND_AAC || config_bands & BAND_AAX)
2215 		bands |= BAND_A;
2216 	return bands;
2217 }
2218 
2219 /**
2220  *  @brief Get supported data rates
2221  *
2222  *  @param pmpriv           A pointer to mlan_private structure
2223  *  @param bss_mode         The specified BSS mode (Infra/IBSS)
2224  *  @param config_bands     The specified band configuration
2225  *  @param rates            The buf to return the supported rates
2226  *
2227  *  @return                 The number of Rates
2228  */
wlan_get_supported_rates(mlan_private * pmpriv,t_u32 bss_mode,t_u16 config_bands,WLAN_802_11_RATES rates)2229 t_u32 wlan_get_supported_rates(mlan_private *pmpriv, t_u32 bss_mode,
2230 			       t_u16 config_bands, WLAN_802_11_RATES rates)
2231 {
2232 	t_u32 k = 0;
2233 	t_u16 bands = 0;
2234 
2235 	ENTER();
2236 	bands = wlan_convert_config_bands(config_bands);
2237 
2238 	if (bss_mode == MLAN_BSS_MODE_INFRA) {
2239 		/* Infra. mode */
2240 		if (bands == BAND_B) {
2241 			/* B only */
2242 			PRINTM(MINFO, "Band: Infra B\n");
2243 			k = wlan_copy_rates(rates, k, SupportedRates_B,
2244 					    sizeof(SupportedRates_B));
2245 		} else if (bands == BAND_G) {
2246 			/* G only */
2247 			PRINTM(MINFO, "Band: Infra G\n");
2248 			k = wlan_copy_rates(rates, k, SupportedRates_G,
2249 					    sizeof(SupportedRates_G));
2250 
2251 		} else if (bands & (BAND_B | BAND_G)) {
2252 			/* BG only */
2253 			PRINTM(MINFO, "Band: Infra BG\n");
2254 #ifdef WIFI_DIRECT_SUPPORT
2255 			if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
2256 				k = wlan_copy_rates(rates, k, SupportedRates_G,
2257 						    sizeof(SupportedRates_G));
2258 			else
2259 #endif
2260 				k = wlan_copy_rates(rates, k, SupportedRates_BG,
2261 						    sizeof(SupportedRates_BG));
2262 		} else if (bands & BAND_A) {
2263 			/* support A */
2264 			PRINTM(MINFO, "Band: Infra A\n");
2265 			k = wlan_copy_rates(rates, k, SupportedRates_A,
2266 					    sizeof(SupportedRates_A));
2267 		}
2268 	} else {
2269 		/* Adhoc. mode */
2270 		if (bands == BAND_B) {
2271 			/* B only */
2272 			PRINTM(MINFO, "Band: Adhoc B\n");
2273 			k = wlan_copy_rates(rates, k, AdhocRates_B,
2274 					    sizeof(AdhocRates_B));
2275 		} else if (bands == BAND_G) {
2276 			/* G only */
2277 			PRINTM(MINFO, "Band: Adhoc G\n");
2278 			k = wlan_copy_rates(rates, k, AdhocRates_G,
2279 					    sizeof(AdhocRates_G));
2280 
2281 		} else if (bands & BAND_A) {
2282 			/* support A */
2283 			PRINTM(MINFO, "Band: Adhoc A\n");
2284 			k = wlan_copy_rates(rates, k, AdhocRates_A,
2285 					    sizeof(AdhocRates_A));
2286 
2287 		} else {
2288 			PRINTM(MINFO, "Band: Adhoc BG\n");
2289 			k = wlan_copy_rates(rates, k, AdhocRates_BG,
2290 					    sizeof(AdhocRates_BG));
2291 		}
2292 	}
2293 
2294 	LEAVE();
2295 	return k;
2296 }
2297 
2298 #define COUNTRY_ID_US 0
2299 #define COUNTRY_ID_JP 1
2300 #define COUNTRY_ID_CN 2
2301 #define COUNTRY_ID_EU 3
2302 typedef struct _oper_bw_chan {
2303 	/*non-global operating class*/
2304 	t_u8 oper_class;
2305 	/*global operating class*/
2306 	t_u8 global_oper_class;
2307 	/*bandwidth 0-20M 1-40M 2-80M 3-160M*/
2308 	t_u8 bandwidth;
2309 	/*channel list*/
2310 	t_u8 channel_list[13];
2311 } oper_bw_chan;
2312 
2313 /** oper class table for US*/
2314 static oper_bw_chan oper_bw_chan_us[] = {
2315 	/** non-Global oper class, global oper class, bandwidth, channel list*/
2316 	{1, 115, 0, {36, 40, 44, 48}},
2317 	{2, 118, 0, {52, 56, 60, 64}},
2318 	{3, 124, 0, {149, 153, 157, 161}},
2319 	{4,
2320 	 121,
2321 	 0,
2322 	 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144}},
2323 	{5, 125, 0, {149, 153, 157, 161, 165}},
2324 	{12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
2325 	{22, 116, 1, {36, 44}},
2326 	{23, 119, 1, {52, 60}},
2327 	{24, 122, 1, {100, 108, 116, 124, 132, 140}},
2328 	{25, 126, 1, {149, 157}},
2329 	{26, 126, 1, {149, 157}},
2330 	{27, 117, 1, {40, 48}},
2331 	{28, 120, 1, {56, 64}},
2332 	{29, 123, 1, {104, 112, 120, 128, 136, 144}},
2333 	{30, 127, 1, {153, 161}},
2334 	{31, 127, 1, {153, 161}},
2335 	{32, 83, 1, {1, 2, 3, 4, 5, 6, 7}},
2336 	{33, 84, 1, {5, 6, 7, 8, 9, 10, 11}},
2337 	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
2338 	{129, 129, 3, {50, 114}},
2339 	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
2340 };
2341 /** oper class table for EU*/
2342 static oper_bw_chan oper_bw_chan_eu[] = {
2343 	/** non-global oper class,global oper class, bandwidth, channel list*/
2344 	{1, 115, 0, {36, 40, 44, 48}},
2345 	{2, 118, 0, {52, 56, 60, 64}},
2346 	{3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
2347 	{4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
2348 	{5, 116, 1, {36, 44}},
2349 	{6, 119, 1, {52, 60}},
2350 	{7, 122, 1, {100, 108, 116, 124, 132}},
2351 	{8, 117, 1, {40, 48}},
2352 	{9, 120, 1, {56, 64}},
2353 	{10, 123, 1, {104, 112, 120, 128, 136}},
2354 	{11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
2355 	{12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
2356 	{17, 125, 0, {149, 153, 157, 161, 165, 169}},
2357 	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
2358 	{129, 129, 3, {50, 114}},
2359 	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
2360 };
2361 /** oper class table for Japan*/
2362 static oper_bw_chan oper_bw_chan_jp[] = {
2363 	/** non-Global oper class,global oper class, bandwidth, channel list*/
2364 	{1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48}},
2365 	{30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
2366 	{31, 82, 0, {14}},
2367 	{32, 118, 0, {52, 56, 60, 64}},
2368 	{33, 118, 0, {52, 56, 60, 64}},
2369 	{34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
2370 	{35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
2371 	{36, 116, 1, {36, 44}},
2372 	{37, 119, 1, {52, 60}},
2373 	{38, 119, 1, {52, 60}},
2374 	{39, 122, 1, {100, 108, 116, 124, 132}},
2375 	{40, 122, 1, {100, 108, 116, 124, 132}},
2376 	{41, 117, 1, {40, 48}},
2377 	{42, 120, 1, {56, 64}},
2378 	{43, 120, 1, {56, 64}},
2379 	{44, 123, 1, {104, 112, 120, 128, 136}},
2380 	{45, 123, 1, {104, 112, 120, 128, 136}},
2381 	{56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
2382 	{57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
2383 	{58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
2384 	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
2385 	{129, 129, 3, {50, 114}},
2386 	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
2387 };
2388 /** oper class table for China*/
2389 static oper_bw_chan oper_bw_chan_cn[] = {
2390 	/** non-Global oper class,global oper class, bandwidth, channel list*/
2391 	{1, 115, 0, {36, 40, 44, 48}},
2392 	{2, 118, 0, {52, 56, 60, 64}},
2393 	{3, 125, 0, {149, 153, 157, 161, 165}},
2394 	{4, 116, 1, {36, 44}},
2395 	{5, 119, 1, {52, 60}},
2396 	{6, 126, 1, {149, 157}},
2397 	{7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
2398 	{8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
2399 	{9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
2400 	{128, 128, 2, {42, 58, 106, 122, 138, 155}},
2401 	{129, 129, 3, {50, 114}},
2402 	{130, 130, 2, {42, 58, 106, 122, 138, 155}},
2403 };
2404 
2405 /**
2406  *  @brief Get non-global operaing class table according to country
2407  *
2408  *  @param pmpriv             A pointer to mlan_private structure
2409  *  @param arraysize          A pointer to table size
2410  *
2411  *  @return                   A pointer to oper_bw_chan
2412  */
wlan_get_nonglobal_operclass_table(mlan_private * pmpriv,int * arraysize)2413 static oper_bw_chan *wlan_get_nonglobal_operclass_table(mlan_private *pmpriv,
2414 							int *arraysize)
2415 {
2416 	t_u8 country_code[][COUNTRY_CODE_LEN] = {"US", "JP", "CN"};
2417 	int country_id = 0;
2418 	oper_bw_chan *poper_bw_chan = MNULL;
2419 
2420 	ENTER();
2421 
2422 	for (country_id = 0; country_id < 3; country_id++)
2423 		if (!memcmp(pmpriv->adapter, pmpriv->adapter->country_code,
2424 			    country_code[country_id], COUNTRY_CODE_LEN - 1))
2425 			break;
2426 	if (country_id >= 3)
2427 		country_id = COUNTRY_ID_US; /*Set default to US*/
2428 	if (wlan_is_etsi_country(pmpriv->adapter,
2429 				 pmpriv->adapter->country_code))
2430 		country_id = COUNTRY_ID_EU; /** Country in EU */
2431 
2432 	switch (country_id) {
2433 	case COUNTRY_ID_US:
2434 		poper_bw_chan = oper_bw_chan_us;
2435 		*arraysize = sizeof(oper_bw_chan_us);
2436 		break;
2437 	case COUNTRY_ID_JP:
2438 		poper_bw_chan = oper_bw_chan_jp;
2439 		*arraysize = sizeof(oper_bw_chan_jp);
2440 		break;
2441 	case COUNTRY_ID_CN:
2442 		poper_bw_chan = oper_bw_chan_cn;
2443 		*arraysize = sizeof(oper_bw_chan_cn);
2444 		break;
2445 	case COUNTRY_ID_EU:
2446 		poper_bw_chan = oper_bw_chan_eu;
2447 		*arraysize = sizeof(oper_bw_chan_eu);
2448 		break;
2449 	default:
2450 		PRINTM(MERROR, "Country not support!\n");
2451 		break;
2452 	}
2453 
2454 	LEAVE();
2455 	return poper_bw_chan;
2456 }
2457 
2458 /**
2459  *  @brief Check validation of given channel and oper class
2460  *
2461  *  @param pmpriv             A pointer to mlan_private structure
2462  *  @param channel            Channel number
2463  *  @param oper_class         operating class
2464  *
2465  *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
2466  */
wlan_check_operclass_validation(mlan_private * pmpriv,t_u8 channel,t_u8 oper_class)2467 mlan_status wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
2468 					    t_u8 oper_class)
2469 {
2470 	int arraysize = 0, i = 0, channum = 0;
2471 	oper_bw_chan *poper_bw_chan = MNULL;
2472 	t_u8 center_freq_idx = 0;
2473 	t_u8 center_freqs[] = {42, 50, 58, 106, 114, 122, 138, 155};
2474 
2475 	ENTER();
2476 
2477 	for (i = 0; i < (int)sizeof(center_freqs); i++) {
2478 		if (channel == center_freqs[i]) {
2479 			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
2480 			LEAVE();
2481 			return MLAN_STATUS_FAILURE;
2482 		}
2483 	}
2484 	if (oper_class <= 0 || oper_class > 130) {
2485 		PRINTM(MERROR, "Invalid operating class!\n");
2486 		LEAVE();
2487 		return MLAN_STATUS_FAILURE;
2488 	}
2489 	if (oper_class >= 128) {
2490 		center_freq_idx = wlan_get_center_freq_idx(
2491 			pmpriv, BAND_AAC, channel, CHANNEL_BW_80MHZ);
2492 		channel = center_freq_idx;
2493 	}
2494 	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
2495 
2496 	if (!poper_bw_chan) {
2497 		PRINTM(MCMND, "Operating class table do not find!\n");
2498 		LEAVE();
2499 		return MLAN_STATUS_FAILURE;
2500 	}
2501 
2502 	for (i = 0; i < (int)(arraysize / sizeof(oper_bw_chan)); i++) {
2503 		if (poper_bw_chan[i].oper_class == oper_class ||
2504 		    poper_bw_chan[i].global_oper_class == oper_class) {
2505 			for (channum = 0;
2506 			     channum <
2507 			     (int)sizeof(poper_bw_chan[i].channel_list);
2508 			     channum++) {
2509 				if (poper_bw_chan[i].channel_list[channum] &&
2510 				    poper_bw_chan[i].channel_list[channum] ==
2511 					    channel) {
2512 					LEAVE();
2513 					return MLAN_STATUS_SUCCESS;
2514 				}
2515 			}
2516 		}
2517 	}
2518 
2519 	PRINTM(MCMND, "Operating class %d do not match channel %d!\n",
2520 	       oper_class, channel);
2521 	LEAVE();
2522 	return MLAN_STATUS_FAILURE;
2523 }
2524 
2525 /**
2526  *  @brief Get current operating class from channel and bandwidth
2527  *
2528  *  @param pmpriv             A pointer to mlan_private structure
2529  *  @param channel            Channel number
2530  *  @param bw                 Bandwidth
2531  *  @param oper_class         A pointer to current operating class
2532  *
2533  *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
2534  */
wlan_get_curr_oper_class(mlan_private * pmpriv,t_u8 channel,t_u8 bw,t_u8 * oper_class)2535 mlan_status wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel,
2536 				     t_u8 bw, t_u8 *oper_class)
2537 {
2538 	oper_bw_chan *poper_bw_chan = MNULL;
2539 	t_u8 center_freq_idx = 0;
2540 	t_u8 center_freqs[] = {42, 50, 58, 106, 114, 122, 138, 155};
2541 	int i = 0, arraysize = 0, channum = 0;
2542 
2543 	ENTER();
2544 
2545 	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
2546 
2547 	if (!poper_bw_chan) {
2548 		PRINTM(MCMND, "Operating class table do not find!\n");
2549 		LEAVE();
2550 		return MLAN_STATUS_FAILURE;
2551 	}
2552 	for (i = 0; i < (int)sizeof(center_freqs); i++) {
2553 		if (channel == center_freqs[i]) {
2554 			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
2555 			LEAVE();
2556 			return MLAN_STATUS_FAILURE;
2557 		}
2558 	}
2559 	if (bw == BW_80MHZ) {
2560 		center_freq_idx = wlan_get_center_freq_idx(
2561 			pmpriv, BAND_AAC, channel, CHANNEL_BW_80MHZ);
2562 		channel = center_freq_idx;
2563 	}
2564 
2565 	for (i = 0; i < (int)(arraysize / sizeof(oper_bw_chan)); i++) {
2566 		if (poper_bw_chan[i].bandwidth == bw) {
2567 			for (channum = 0;
2568 			     channum <
2569 			     (int)(sizeof(poper_bw_chan[i].channel_list));
2570 			     channum++) {
2571 				if (poper_bw_chan[i].channel_list[channum] &&
2572 				    poper_bw_chan[i].channel_list[channum] ==
2573 					    channel) {
2574 					*oper_class =
2575 						poper_bw_chan[i].oper_class;
2576 					return MLAN_STATUS_SUCCESS;
2577 				}
2578 			}
2579 		}
2580 	}
2581 
2582 	PRINTM(MCMND, "Operating class not found!\n");
2583 	LEAVE();
2584 	return MLAN_STATUS_FAILURE;
2585 }
2586 
2587 /**
2588  *  @brief Add Supported operating classes IE
2589  *
2590  *  @param pmpriv             A pointer to mlan_private structure
2591  *  @param pptlv_out          A pointer to TLV to fill in
2592  *  @param curr_oper_class    Current operating class
2593  *
2594  *  @return                   Length
2595  */
wlan_add_supported_oper_class_ie(mlan_private * pmpriv,t_u8 ** pptlv_out,t_u8 curr_oper_class)2596 int wlan_add_supported_oper_class_ie(mlan_private *pmpriv, t_u8 **pptlv_out,
2597 				     t_u8 curr_oper_class)
2598 {
2599 	t_u8 oper_class_us[] = {1,  2,	3,  4,	5,  12, 22, 23,	 24,  25, 26,
2600 				27, 28, 29, 30, 31, 32, 33, 128, 129, 130};
2601 	t_u8 oper_class_eu[] = {1, 2,  3,  4,  5,  6,	7,   8,
2602 				9, 10, 11, 12, 17, 128, 129, 130};
2603 	t_u8 oper_class_jp[] = {1,  30, 31, 32, 33,  34,  35, 36,
2604 				37, 38, 39, 40, 41,  42,  43, 44,
2605 				45, 56, 57, 58, 128, 129, 130};
2606 	t_u8 oper_class_cn[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 129, 130};
2607 	t_u8 country_code[][COUNTRY_CODE_LEN] = {"US", "JP", "CN"};
2608 	int country_id = 0, ret = 0;
2609 	MrvlIETypes_SuppOperClass_t *poper_class = MNULL;
2610 
2611 	ENTER();
2612 
2613 	for (country_id = 0; country_id < 3; country_id++)
2614 		if (!memcmp(pmpriv->adapter, pmpriv->adapter->country_code,
2615 			    country_code[country_id], COUNTRY_CODE_LEN - 1))
2616 			break;
2617 	if (country_id >= 3)
2618 		country_id = COUNTRY_ID_US; /*Set default to US*/
2619 	if (wlan_is_etsi_country(pmpriv->adapter,
2620 				 pmpriv->adapter->country_code))
2621 		country_id = COUNTRY_ID_EU; /** Country in EU */
2622 	poper_class = (MrvlIETypes_SuppOperClass_t *)*pptlv_out;
2623 	memset(pmpriv->adapter, poper_class, 0,
2624 	       sizeof(MrvlIETypes_SuppOperClass_t));
2625 	poper_class->header.type = wlan_cpu_to_le16(REGULATORY_CLASS);
2626 	if (country_id == COUNTRY_ID_US) {
2627 		poper_class->header.len = sizeof(oper_class_us);
2628 		memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
2629 			   oper_class_us, sizeof(oper_class_us),
2630 			   poper_class->header.len);
2631 	} else if (country_id == COUNTRY_ID_JP) {
2632 		poper_class->header.len = sizeof(oper_class_jp);
2633 		memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
2634 			   oper_class_jp, sizeof(oper_class_jp),
2635 			   poper_class->header.len);
2636 	} else if (country_id == COUNTRY_ID_CN) {
2637 		poper_class->header.len = sizeof(oper_class_cn);
2638 		memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
2639 			   oper_class_cn, sizeof(oper_class_cn),
2640 			   poper_class->header.len);
2641 	} else if (country_id == COUNTRY_ID_EU) {
2642 		poper_class->header.len = sizeof(oper_class_eu);
2643 		memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
2644 			   oper_class_eu, sizeof(oper_class_eu),
2645 			   poper_class->header.len);
2646 	}
2647 	poper_class->current_oper_class = curr_oper_class;
2648 	poper_class->header.len += sizeof(poper_class->current_oper_class);
2649 	DBG_HEXDUMP(MCMD_D, "Operating class", (t_u8 *)poper_class,
2650 		    sizeof(MrvlIEtypesHeader_t) + poper_class->header.len);
2651 	ret = sizeof(MrvlIEtypesHeader_t) + poper_class->header.len;
2652 	*pptlv_out += ret;
2653 	poper_class->header.len = wlan_cpu_to_le16(poper_class->header.len);
2654 
2655 	LEAVE();
2656 	return ret;
2657 }
2658 
2659 /**
2660  *  @brief This function sets region table.
2661  *
2662  *  @param pmpriv  A pointer to mlan_private structure
2663  *  @param region  The region code
2664  *  @param band    The band
2665  *
2666  *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2667  */
wlan_set_regiontable(mlan_private * pmpriv,t_u8 region,t_u16 band)2668 mlan_status wlan_set_regiontable(mlan_private *pmpriv, t_u8 region, t_u16 band)
2669 {
2670 	mlan_adapter *pmadapter = pmpriv->adapter;
2671 	int i = 0, j;
2672 	chan_freq_power_t *cfp;
2673 	int cfp_no;
2674 	region_chan_t region_chan_old[MAX_REGION_CHANNEL_NUM];
2675 	t_u8 cfp_code_bg = region;
2676 	t_u8 cfp_code_a = region;
2677 
2678 	ENTER();
2679 
2680 	memcpy_ext(pmadapter, region_chan_old, pmadapter->region_channel,
2681 		   sizeof(pmadapter->region_channel), sizeof(region_chan_old));
2682 	memset(pmadapter, pmadapter->region_channel, 0,
2683 	       sizeof(pmadapter->region_channel));
2684 
2685 	if (band & (BAND_B | BAND_G | BAND_GN)) {
2686 		if (pmadapter->cfp_code_bg)
2687 			cfp_code_bg = pmadapter->cfp_code_bg;
2688 		PRINTM(MCMND, "%s: 2.4G 0x%x\n", __func__, cfp_code_bg);
2689 		cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
2690 						BAND_G | BAND_B | BAND_GN,
2691 						&cfp_no);
2692 		if (cfp) {
2693 			pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
2694 			pmadapter->region_channel[i].pcfp = cfp;
2695 		} else {
2696 			PRINTM(MERROR, "wrong region code %#x in Band B-G\n",
2697 			       region);
2698 			LEAVE();
2699 			return MLAN_STATUS_FAILURE;
2700 		}
2701 		pmadapter->region_channel[i].valid = MTRUE;
2702 		pmadapter->region_channel[i].region = region;
2703 		if (band & BAND_GN)
2704 			pmadapter->region_channel[i].band = BAND_G;
2705 		else
2706 			pmadapter->region_channel[i].band =
2707 				(band & BAND_G) ? BAND_G : BAND_B;
2708 
2709 		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
2710 			if (region_chan_old[j].band & (BAND_B | BAND_G))
2711 				break;
2712 		}
2713 
2714 		if ((j < MAX_REGION_CHANNEL_NUM) &&
2715 		    (region_chan_old[j].valid == MTRUE)) {
2716 			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
2717 					      region_chan_old[j].pcfp,
2718 					      region_chan_old[j].num_cfp);
2719 		} else if (cfp) {
2720 			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
2721 		}
2722 		i++;
2723 	}
2724 	if (band & (BAND_A | BAND_AN | BAND_AAC)) {
2725 		if (pmadapter->cfp_code_a)
2726 			cfp_code_a = pmadapter->cfp_code_a;
2727 		PRINTM(MCMND, "%s: 5G 0x%x\n", __func__, cfp_code_a);
2728 		cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
2729 						&cfp_no);
2730 		if (cfp) {
2731 			pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
2732 			pmadapter->region_channel[i].pcfp = cfp;
2733 		} else {
2734 			PRINTM(MERROR, "wrong region code %#x in Band A\n",
2735 			       region);
2736 			LEAVE();
2737 			return MLAN_STATUS_FAILURE;
2738 		}
2739 		pmadapter->region_channel[i].valid = MTRUE;
2740 		pmadapter->region_channel[i].region = region;
2741 		pmadapter->region_channel[i].band = BAND_A;
2742 
2743 		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
2744 			if (region_chan_old[j].band & BAND_A)
2745 				break;
2746 		}
2747 		if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid) {
2748 			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
2749 					      region_chan_old[j].pcfp,
2750 					      region_chan_old[j].num_cfp);
2751 		} else if (cfp) {
2752 			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
2753 		}
2754 		i++;
2755 	}
2756 	LEAVE();
2757 	return MLAN_STATUS_SUCCESS;
2758 }
2759 
2760 /**
2761  *  @brief Get if radar detection is enabled or not on a certain channel
2762  *
2763  *  @param priv    Private driver information structure
2764  *  @param chnl Channel to determine radar detection requirements
2765  *
2766  *  @return
2767  *    - MTRUE if radar detection is required
2768  *    - MFALSE otherwise
2769  */
wlan_get_cfp_radar_detect(mlan_private * priv,t_u8 chnl)2770 t_bool wlan_get_cfp_radar_detect(mlan_private *priv, t_u8 chnl)
2771 {
2772 	int i, j;
2773 	t_bool required = MFALSE;
2774 	chan_freq_power_t *pcfp = MNULL;
2775 
2776 	ENTER();
2777 
2778 	/*get the cfp table first*/
2779 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2780 		if (priv->adapter->region_channel[i].band == BAND_A) {
2781 			pcfp = priv->adapter->region_channel[i].pcfp;
2782 			break;
2783 		}
2784 	}
2785 
2786 	if (!pcfp) {
2787 		/* This means operation in BAND-A is not support, we can
2788 		 * just return false here, it's harmless
2789 		 */
2790 		goto done;
2791 	}
2792 
2793 	/*get the radar detection requirements according to chan num*/
2794 	for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2795 		if (pcfp[j].channel == chnl) {
2796 			required = pcfp[j].passive_scan_or_radar_detect;
2797 			break;
2798 		}
2799 	}
2800 
2801 done:
2802 	LEAVE();
2803 	return required;
2804 }
2805 
2806 /**
2807  *  @brief Get if scan type is passive or not on a certain channel for b/g band
2808  *
2809  *  @param priv    Private driver information structure
2810  *  @param chnl Channel to determine scan type
2811  *
2812  *  @return
2813  *    - MTRUE if scan type is passive
2814  *    - MFALSE otherwise
2815  */
wlan_bg_scan_type_is_passive(mlan_private * priv,t_u8 chnl)2816 t_bool wlan_bg_scan_type_is_passive(mlan_private *priv, t_u8 chnl)
2817 {
2818 	int i, j;
2819 	t_bool passive = MFALSE;
2820 	chan_freq_power_t *pcfp = MNULL;
2821 
2822 	ENTER();
2823 
2824 	/*get the cfp table first*/
2825 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2826 		if (priv->adapter->region_channel[i].band & (BAND_B | BAND_G)) {
2827 			pcfp = priv->adapter->region_channel[i].pcfp;
2828 			break;
2829 		}
2830 	}
2831 
2832 	if (!pcfp) {
2833 		/*This means operation in BAND-B or BAND_G is not support, we
2834 		 * can just return false here
2835 		 */
2836 		goto done;
2837 	}
2838 
2839 	/*get the bg scan type according to chan num*/
2840 	for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2841 		if (pcfp[j].channel == chnl) {
2842 			passive = pcfp[j].passive_scan_or_radar_detect;
2843 			break;
2844 		}
2845 	}
2846 
2847 done:
2848 	LEAVE();
2849 	return passive;
2850 }
2851 
2852 /**
2853  *  @brief Get if a channel is NO_IR (passive) or not
2854  *
2855  *  @param priv     Private driver information structure
2856  *  @param band     Band to check
2857  *  @param chan     Channel to check
2858  *
2859  *  @return
2860  *    - MTRUE if channel is passive
2861  *    - MFALSE otherwise
2862  */
2863 
wlan_is_chan_passive(mlan_private * priv,t_u16 band,t_u8 chan)2864 t_bool wlan_is_chan_passive(mlan_private *priv, t_u16 band, t_u8 chan)
2865 {
2866 	int i, j;
2867 	t_bool passive = MFALSE;
2868 	chan_freq_power_t *pcfp = MNULL;
2869 
2870 	ENTER();
2871 
2872 	/* get the cfp table first */
2873 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2874 		if (priv->adapter->region_channel[i].band & band) {
2875 			pcfp = priv->adapter->region_channel[i].pcfp;
2876 			break;
2877 		}
2878 	}
2879 
2880 	if (pcfp) {
2881 		/* check table according to chan num */
2882 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2883 			if (pcfp[j].channel == chan) {
2884 				if (pcfp[j].dynamic.flags & NXP_CHANNEL_PASSIVE)
2885 					passive = MTRUE;
2886 				break;
2887 			}
2888 		}
2889 	}
2890 
2891 	LEAVE();
2892 	return passive;
2893 }
2894 
2895 /**
2896  *  @brief Get if a channel is disabled or not
2897  *
2898  *  @param priv     Private driver information structure
2899  *  @param band     Band to check
2900  *  @param chan     Channel to check
2901  *
2902  *  @return
2903  *    - MTRUE if channel is disabled
2904  *    - MFALSE otherwise
2905  */
2906 
wlan_is_chan_disabled(mlan_private * priv,t_u16 band,t_u8 chan)2907 t_bool wlan_is_chan_disabled(mlan_private *priv, t_u16 band, t_u8 chan)
2908 {
2909 	int i, j;
2910 	t_bool disabled = MFALSE;
2911 	chan_freq_power_t *pcfp = MNULL;
2912 
2913 	ENTER();
2914 
2915 	/* get the cfp table first */
2916 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2917 		if (priv->adapter->region_channel[i].band & band) {
2918 			pcfp = priv->adapter->region_channel[i].pcfp;
2919 			break;
2920 		}
2921 	}
2922 
2923 	if (pcfp) {
2924 		/* check table according to chan num */
2925 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2926 			if (pcfp[j].channel == chan) {
2927 				if (pcfp[j].dynamic.flags &
2928 				    NXP_CHANNEL_DISABLED)
2929 					disabled = MTRUE;
2930 				break;
2931 			}
2932 		}
2933 	}
2934 
2935 	LEAVE();
2936 	return disabled;
2937 }
2938 
2939 /**
2940  *  @brief Get if a channel is blacklisted or not
2941  *
2942  *  @param priv     Private driver information structure
2943  *  @param band     Band to check
2944  *  @param chan     Channel to check
2945  *
2946  *  @return
2947  *    - MTRUE if channel is blacklisted
2948  *    - MFALSE otherwise
2949  */
2950 
wlan_is_chan_blacklisted(mlan_private * priv,t_u16 band,t_u8 chan)2951 t_bool wlan_is_chan_blacklisted(mlan_private *priv, t_u16 band, t_u8 chan)
2952 {
2953 	int i, j;
2954 	t_bool blacklist = MFALSE;
2955 	chan_freq_power_t *pcfp = MNULL;
2956 
2957 	ENTER();
2958 
2959 	/*get the cfp table first*/
2960 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2961 		if (priv->adapter->region_channel[i].band & band) {
2962 			pcfp = priv->adapter->region_channel[i].pcfp;
2963 			break;
2964 		}
2965 	}
2966 
2967 	if (pcfp) {
2968 		/*check table according to chan num*/
2969 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2970 			if (pcfp[j].channel == chan) {
2971 				blacklist = pcfp[j].dynamic.blacklist;
2972 				break;
2973 			}
2974 		}
2975 	}
2976 
2977 	LEAVE();
2978 	return blacklist;
2979 }
2980 
2981 /**
2982  *  @brief Set a channel as blacklisted or not
2983  *
2984  *  @param priv     Private driver information structure
2985  *  @param band     Band to check
2986  *  @param chan     Channel to check
2987  *  @param bl       Blacklist if MTRUE
2988  *
2989  *  @return
2990  *    - MTRUE if channel setting is updated
2991  *    - MFALSE otherwise
2992  */
2993 
wlan_set_chan_blacklist(mlan_private * priv,t_u16 band,t_u8 chan,t_bool bl)2994 t_bool wlan_set_chan_blacklist(mlan_private *priv, t_u16 band, t_u8 chan,
2995 			       t_bool bl)
2996 {
2997 	int i, j;
2998 	t_bool set_bl = MFALSE;
2999 	chan_freq_power_t *pcfp = MNULL;
3000 
3001 	ENTER();
3002 
3003 	/*get the cfp table first*/
3004 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
3005 		if (priv->adapter->region_channel[i].band & band) {
3006 			pcfp = priv->adapter->region_channel[i].pcfp;
3007 			break;
3008 		}
3009 	}
3010 
3011 	if (pcfp) {
3012 		/*check table according to chan num*/
3013 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
3014 			if (pcfp[j].channel == chan) {
3015 				pcfp[j].dynamic.blacklist = bl;
3016 				set_bl = MTRUE;
3017 				break;
3018 			}
3019 		}
3020 	}
3021 
3022 	LEAVE();
3023 	return set_bl;
3024 }
3025 
3026 /**
3027  *  @brief Set channel's dfs state
3028  *
3029  *  @param priv         Private driver information structure
3030  *  @param band         Band to check
3031  *  @param chan         Channel to check
3032  *  @param dfs_state    dfs state
3033  *
3034  *  @return  N/A
3035  */
wlan_set_chan_dfs_state(mlan_private * priv,t_u16 band,t_u8 chan,dfs_state_t dfs_state)3036 t_void wlan_set_chan_dfs_state(mlan_private *priv, t_u16 band, t_u8 chan,
3037 			       dfs_state_t dfs_state)
3038 {
3039 	int i, j;
3040 	chan_freq_power_t *pcfp = MNULL;
3041 
3042 	ENTER();
3043 
3044 	/*get the cfp table first*/
3045 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
3046 		if (priv->adapter->region_channel[i].band & band) {
3047 			pcfp = priv->adapter->region_channel[i].pcfp;
3048 			break;
3049 		}
3050 	}
3051 
3052 	if (pcfp) {
3053 		/*check table according to chan num*/
3054 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
3055 			if (pcfp[j].channel == chan) {
3056 				pcfp[j].dynamic.dfs_state = dfs_state;
3057 				break;
3058 			}
3059 		}
3060 	}
3061 
3062 	LEAVE();
3063 }
3064 
3065 /**
3066  *  @brief get channel's dfs state
3067  *
3068  *  @param priv         Private driver information structure
3069  *  @param band         Band to check
3070  *  @param chan         Channel to check
3071  *
3072  *  @return  channel's dfs state
3073  */
wlan_get_chan_dfs_state(mlan_private * priv,t_u16 band,t_u8 chan)3074 dfs_state_t wlan_get_chan_dfs_state(mlan_private *priv, t_u16 band, t_u8 chan)
3075 {
3076 	int i, j;
3077 	chan_freq_power_t *pcfp = MNULL;
3078 	dfs_state_t dfs_state = DFS_USABLE;
3079 
3080 	ENTER();
3081 
3082 	/*get the cfp table first*/
3083 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
3084 		if (priv->adapter->region_channel[i].band & band) {
3085 			pcfp = priv->adapter->region_channel[i].pcfp;
3086 			break;
3087 		}
3088 	}
3089 
3090 	if (pcfp) {
3091 		/*check table according to chan num*/
3092 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
3093 			if (pcfp[j].channel == chan) {
3094 				dfs_state = pcfp[j].dynamic.dfs_state;
3095 				break;
3096 			}
3097 		}
3098 	}
3099 
3100 	LEAVE();
3101 	return dfs_state;
3102 }
3103 
3104 /**
3105  *  @brief reset all channel's dfs state
3106  *
3107  *  @param priv         Private driver information structure
3108  *  @param band         Band to check
3109  *  @param dfs_state    dfs state
3110  *
3111  *  @return  N/A
3112  */
wlan_reset_all_chan_dfs_state(mlan_private * priv,t_u16 band,dfs_state_t dfs_state)3113 t_void wlan_reset_all_chan_dfs_state(mlan_private *priv, t_u16 band,
3114 				     dfs_state_t dfs_state)
3115 {
3116 	int i, j;
3117 	chan_freq_power_t *pcfp = MNULL;
3118 
3119 	ENTER();
3120 
3121 	/*get the cfp table first*/
3122 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
3123 		if (priv->adapter->region_channel[i].band & band) {
3124 			pcfp = priv->adapter->region_channel[i].pcfp;
3125 			break;
3126 		}
3127 	}
3128 
3129 	if (pcfp) {
3130 		/*check table according to chan num*/
3131 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
3132 			pcfp[j].dynamic.dfs_state = dfs_state;
3133 		}
3134 	}
3135 
3136 	LEAVE();
3137 }
3138 
3139 /**
3140  *  @brief Convert rateid in IEEE format to MRVL format
3141  *
3142  *  @param priv     Private driver information structure
3143  *  @param IeeeMacRate  Rate in terms of IEEE format
3144  *  @param pmbuf     A pointer to packet buffer
3145  *
3146  *  @return
3147  *    Rate ID in terms of MRVL format
3148  */
wlan_ieee_rateid_to_mrvl_rateid(mlan_private * priv,t_u16 IeeeMacRate,t_u8 * dst_mac)3149 t_u8 wlan_ieee_rateid_to_mrvl_rateid(mlan_private *priv, t_u16 IeeeMacRate,
3150 				     t_u8 *dst_mac)
3151 {
3152 	/* Set default rate ID to RATEID_DBPSK1Mbps */
3153 	t_u8 mrvlRATEID = 0;
3154 	const rate_map *rate_tbl = rate_map_table_1x1;
3155 	t_u32 cnt = sizeof(rate_map_table_1x1) / sizeof(rate_map);
3156 	t_u8 skip_nss2 = MTRUE;
3157 	t_u32 i = 0;
3158 	IEEEtypes_HTCap_t *htcap = MNULL;
3159 	t_u8 tx_mcs_supp = GET_TXMCSSUPP(priv->usr_dev_mcs_support);
3160 #ifdef UAP_SUPPORT
3161 	psta_node sta_ptr = MNULL;
3162 #endif
3163 
3164 	ENTER();
3165 
3166 	if (priv->adapter->hw_dev_mcs_support == HT_STREAM_MODE_2X2) {
3167 		rate_tbl = rate_map_table_2x2;
3168 		cnt = sizeof(rate_map_table_2x2) / sizeof(rate_map);
3169 	}
3170 
3171 #ifdef UAP_SUPPORT
3172 	if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
3173 		if (!dst_mac) {
3174 			LEAVE();
3175 			return mrvlRATEID;
3176 		}
3177 		sta_ptr = (sta_node *)util_peek_list(
3178 			priv->adapter->pmoal_handle, &priv->sta_list,
3179 			priv->adapter->callbacks.moal_spin_lock,
3180 			priv->adapter->callbacks.moal_spin_unlock);
3181 		if (!sta_ptr) {
3182 			LEAVE();
3183 			return mrvlRATEID;
3184 		}
3185 		while (sta_ptr != (sta_node *)&priv->sta_list) {
3186 			if (memcmp(priv->adapter, dst_mac, sta_ptr->mac_addr,
3187 				   MLAN_MAC_ADDR_LENGTH)) {
3188 				htcap = &(sta_ptr->HTcap);
3189 				break;
3190 			}
3191 			sta_ptr = sta_ptr->pnext;
3192 		}
3193 	}
3194 #endif
3195 #ifdef STA_SUPPORT
3196 	if (priv->bss_role == MLAN_BSS_ROLE_STA)
3197 		htcap = priv->curr_bss_params.bss_descriptor.pht_cap;
3198 #endif
3199 	if (htcap) {
3200 		/* If user configure tx to 2x2 and peer device rx is 2x2 */
3201 		if (tx_mcs_supp >= 2 && htcap->ht_cap.supported_mcs_set[1])
3202 			skip_nss2 = MFALSE;
3203 	}
3204 
3205 	for (i = 0; i < cnt; i++) {
3206 		if (rate_tbl[i].nss && skip_nss2)
3207 			continue;
3208 		if (rate_tbl[i].rate == IeeeMacRate) {
3209 			mrvlRATEID = rate_tbl[i].id;
3210 			break;
3211 		}
3212 	}
3213 
3214 	return mrvlRATEID;
3215 }
3216 
3217 /**
3218  *  @brief Convert rateid in MRVL format to IEEE format
3219  *
3220  *  @param IeeeMacRate  Rate in terms of MRVL format
3221  *
3222  *  @return
3223  *    Rate ID in terms of IEEE format
3224  */
wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)3225 t_u8 wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)
3226 {
3227 	return rateUnit_500Kbps[rate];
3228 }
3229 
3230 /**
3231  *  @brief	 sort cfp otp table
3232  *
3233  *  @param pmapdater	a pointer to mlan_adapter structure
3234  *
3235  *  @return
3236  *    None
3237  */
wlan_sort_cfp_otp_table(mlan_adapter * pmadapter)3238 static void wlan_sort_cfp_otp_table(mlan_adapter *pmadapter)
3239 {
3240 	t_u8 c, d;
3241 	chan_freq_power_t *ch1;
3242 	chan_freq_power_t *ch2;
3243 	chan_freq_power_t swap;
3244 
3245 	if (pmadapter->tx_power_table_a_rows <= 1)
3246 		return;
3247 	for (c = 0; c < pmadapter->tx_power_table_a_rows - 1; c++) {
3248 		for (d = 0; d < pmadapter->tx_power_table_a_rows - c - 1; d++) {
3249 			ch1 = (chan_freq_power_t *)(pmadapter->cfp_otp_a + d);
3250 			ch2 = (chan_freq_power_t *)(pmadapter->cfp_otp_a + d +
3251 						    1);
3252 			if (ch1->channel > ch2->channel) {
3253 				memcpy_ext(pmadapter, &swap, ch1,
3254 					   sizeof(chan_freq_power_t),
3255 					   sizeof(chan_freq_power_t));
3256 				memcpy_ext(pmadapter, ch1, ch2,
3257 					   sizeof(chan_freq_power_t),
3258 					   sizeof(chan_freq_power_t));
3259 				memcpy_ext(pmadapter, ch2, &swap,
3260 					   sizeof(chan_freq_power_t),
3261 					   sizeof(chan_freq_power_t));
3262 			}
3263 		}
3264 	}
3265 }
3266 
3267 /**
3268  *  @brief	Update CFP tables and power tables from FW
3269  *
3270  *  @param priv		Private driver information structure
3271  *  @param buf		Pointer to the buffer holding TLV data
3272  *					from 0x242 command response.
3273  *  @param buf_left	bufsize
3274  *
3275  *  @return
3276  *    None
3277  */
wlan_add_fw_cfp_tables(pmlan_private pmpriv,t_u8 * buf,t_u16 buf_left)3278 void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
3279 {
3280 	mlan_adapter *pmadapter = pmpriv->adapter;
3281 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
3282 	MrvlIEtypesHeader_t *head;
3283 	t_u16 tlv;
3284 	t_u16 tlv_buf_len;
3285 	t_u16 tlv_buf_left;
3286 	t_u16 i;
3287 	int k = 0, rows, cols;
3288 	t_u16 max_tx_pwr_bg = WLAN_TX_PWR_DEFAULT;
3289 	t_u16 max_tx_pwr_a = WLAN_TX_PWR_DEFAULT;
3290 	t_u8 *tlv_buf;
3291 	t_u8 *data;
3292 	t_u8 *tmp;
3293 	mlan_status ret;
3294 
3295 	ENTER();
3296 
3297 	if (!buf) {
3298 		PRINTM(MERROR, "CFP table update failed!\n");
3299 		goto out;
3300 	}
3301 	if (pmadapter->otp_region) {
3302 		memset(pmadapter, pmadapter->region_channel, 0,
3303 		       sizeof(pmadapter->region_channel));
3304 		wlan_free_fw_cfp_tables(pmadapter);
3305 	}
3306 	pmadapter->tx_power_table_bg_rows = FW_CFP_TABLE_MAX_ROWS_BG;
3307 	pmadapter->tx_power_table_bg_cols = FW_CFP_TABLE_MAX_COLS_BG;
3308 	pmadapter->tx_power_table_a_rows = FW_CFP_TABLE_MAX_ROWS_A;
3309 	pmadapter->tx_power_table_a_cols = FW_CFP_TABLE_MAX_COLS_A;
3310 	tlv_buf = (t_u8 *)buf;
3311 	tlv_buf_left = buf_left;
3312 
3313 	while (tlv_buf_left >= sizeof(*head)) {
3314 		head = (MrvlIEtypesHeader_t *)tlv_buf;
3315 		tlv = wlan_le16_to_cpu(head->type);
3316 		tlv_buf_len = wlan_le16_to_cpu(head->len);
3317 
3318 		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
3319 			break;
3320 		data = (t_u8 *)head + sizeof(*head);
3321 
3322 		switch (tlv) {
3323 		case TLV_TYPE_REGION_INFO:
3324 			/* Skip adding fw region info if it already exists or
3325 			 * if this TLV has no set data
3326 			 */
3327 			if (*data == 0)
3328 				break;
3329 			if (pmadapter->otp_region)
3330 				break;
3331 
3332 			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
3333 					       sizeof(otp_region_info_t),
3334 					       MLAN_MEM_DEF,
3335 					       (t_u8 **)&pmadapter->otp_region);
3336 			if (ret != MLAN_STATUS_SUCCESS ||
3337 			    !pmadapter->otp_region) {
3338 				PRINTM(MERROR,
3339 				       "Memory allocation for the otp region info struct failed!\n");
3340 				break;
3341 			}
3342 			/* Save region info values from OTP in the otp_region
3343 			 * structure
3344 			 */
3345 			memcpy_ext(pmadapter, pmadapter->otp_region, data,
3346 				   sizeof(otp_region_info_t),
3347 				   sizeof(otp_region_info_t));
3348 			data += sizeof(otp_region_info_t);
3349 			/* Get pre-defined cfp tables corresponding to the
3350 			 * region code in OTP
3351 			 */
3352 			for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
3353 				if (cfp_table_BG[i].code ==
3354 				    pmadapter->otp_region->region_code) {
3355 					max_tx_pwr_bg = (cfp_table_BG[i].cfp)
3356 								->max_tx_power;
3357 					break;
3358 				}
3359 			}
3360 			for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
3361 				if (cfp_table_A[i].code ==
3362 				    pmadapter->otp_region->region_code) {
3363 					max_tx_pwr_a = (cfp_table_A[i].cfp)
3364 							       ->max_tx_power;
3365 					break;
3366 				}
3367 			}
3368 			/* Update the region code and the country code in
3369 			 * pmadapter
3370 			 */
3371 			pmadapter->region_code =
3372 				pmadapter->otp_region->region_code;
3373 			pmadapter->country_code[0] =
3374 				pmadapter->otp_region->country_code[0];
3375 			pmadapter->country_code[1] =
3376 				pmadapter->otp_region->country_code[1];
3377 			pmadapter->country_code[2] = '\0';
3378 			pmadapter->domain_reg.country_code[0] =
3379 				pmadapter->otp_region->country_code[0];
3380 			pmadapter->domain_reg.country_code[1] =
3381 				pmadapter->otp_region->country_code[1];
3382 			pmadapter->domain_reg.country_code[2] = '\0';
3383 			PRINTM(MCMND,
3384 			       "OTP region: region_code=%d %c%c dfs_region=%d\n",
3385 			       pmadapter->otp_region->region_code,
3386 			       pmadapter->country_code[0],
3387 			       pmadapter->country_code[1],
3388 			       pmadapter->otp_region->dfs_region);
3389 			pmadapter->cfp_code_bg =
3390 				pmadapter->otp_region->region_code;
3391 			pmadapter->cfp_code_a =
3392 				pmadapter->otp_region->region_code;
3393 			break;
3394 		case TLV_TYPE_CHAN_ATTR_CFG:
3395 			/* Skip adding fw cfp tables if they already exist or
3396 			 * if this TLV has no set data
3397 			 */
3398 			if (*data == 0)
3399 				break;
3400 			if (pmadapter->cfp_otp_bg || pmadapter->cfp_otp_a) {
3401 				break;
3402 			}
3403 
3404 			ret = pcb->moal_malloc(
3405 				pmadapter->pmoal_handle,
3406 				pmadapter->tx_power_table_bg_rows *
3407 					sizeof(chan_freq_power_t),
3408 				MLAN_MEM_DEF, (t_u8 **)&pmadapter->cfp_otp_bg);
3409 			if (ret != MLAN_STATUS_SUCCESS ||
3410 			    !pmadapter->cfp_otp_bg) {
3411 				PRINTM(MERROR,
3412 				       "Memory allocation for storing otp bg table data failed!\n");
3413 				break;
3414 			}
3415 			/* Save channel usability flags from OTP data in the fw
3416 			 * cfp bg table and set frequency and max_tx_power
3417 			 * values
3418 			 */
3419 			for (i = 0; i < pmadapter->tx_power_table_bg_rows;
3420 			     i++) {
3421 				(pmadapter->cfp_otp_bg + i)->channel = *data;
3422 				if (*data == 14)
3423 					(pmadapter->cfp_otp_bg + i)->freq =
3424 						2484;
3425 				else
3426 					(pmadapter->cfp_otp_bg + i)->freq =
3427 						2412 + 5 * (*data - 1);
3428 				(pmadapter->cfp_otp_bg + i)->max_tx_power =
3429 					max_tx_pwr_bg;
3430 				data++;
3431 				(pmadapter->cfp_otp_bg + i)->dynamic.flags =
3432 					*data;
3433 				if (*data & NXP_CHANNEL_DFS)
3434 					(pmadapter->cfp_otp_bg + i)
3435 						->passive_scan_or_radar_detect =
3436 						MTRUE;
3437 				PRINTM(MCMD_D,
3438 				       "OTP Region (BG): chan=%d flags=0x%x\n",
3439 				       (pmadapter->cfp_otp_bg + i)->channel,
3440 				       (pmadapter->cfp_otp_bg + i)
3441 					       ->dynamic.flags);
3442 				data++;
3443 			}
3444 			ret = pcb->moal_malloc(
3445 				pmadapter->pmoal_handle,
3446 				pmadapter->tx_power_table_a_rows *
3447 					sizeof(chan_freq_power_t),
3448 				MLAN_MEM_DEF, (t_u8 **)&pmadapter->cfp_otp_a);
3449 			if (ret != MLAN_STATUS_SUCCESS ||
3450 			    !pmadapter->cfp_otp_a) {
3451 				PRINTM(MERROR,
3452 				       "Memory allocation for storing otp a table data failed!\n");
3453 				break;
3454 			}
3455 			/* Save channel usability flags from OTP data in the fw
3456 			 * cfp a table and set frequency and max_tx_power values
3457 			 */
3458 			for (i = 0; i < pmadapter->tx_power_table_a_rows; i++) {
3459 				(pmadapter->cfp_otp_a + i)->channel = *data;
3460 				if (*data < 183)
3461 					/* 5GHz channels */
3462 					(pmadapter->cfp_otp_a + i)->freq =
3463 						5035 + 5 * (*data - 7);
3464 				else
3465 					/* 4GHz channels */
3466 					(pmadapter->cfp_otp_a + i)->freq =
3467 						4915 + 5 * (*data - 183);
3468 				(pmadapter->cfp_otp_a + i)->max_tx_power =
3469 					max_tx_pwr_a;
3470 				data++;
3471 				(pmadapter->cfp_otp_a + i)->dynamic.flags =
3472 					*data;
3473 				(pmadapter->cfp_otp_a + i)->dynamic.dfs_state =
3474 					DFS_USABLE;
3475 				if (*data & NXP_CHANNEL_DFS)
3476 					(pmadapter->cfp_otp_a + i)
3477 						->passive_scan_or_radar_detect =
3478 						MTRUE;
3479 				PRINTM(MCMD_D,
3480 				       "OTP Region (A): chan=%d flags=0x%x\n",
3481 				       (pmadapter->cfp_otp_a + i)->channel,
3482 				       (pmadapter->cfp_otp_a + i)
3483 					       ->dynamic.flags);
3484 
3485 				data++;
3486 			}
3487 			break;
3488 		case TLV_TYPE_POWER_TABLE:
3489 			/* Skip adding fw power tables if this TLV has no data
3490 			 * or if they already exists but force reg rule is set
3491 			 * in the otp
3492 			 */
3493 			if (*data == 0)
3494 				break;
3495 			if (pmadapter->otp_region &&
3496 			    pmadapter->otp_region->force_reg &&
3497 			    pmadapter->tx_power_table_bg)
3498 				break;
3499 
3500 			/* Save the tlv data in power tables for band BG and A
3501 			 */
3502 			tmp = data;
3503 			i = 0;
3504 			while ((i <
3505 				pmadapter->tx_power_table_bg_rows *
3506 					pmadapter->tx_power_table_bg_cols) &&
3507 			       (i < tlv_buf_len)) {
3508 				i++;
3509 				tmp++;
3510 			}
3511 			if (!pmadapter->tx_power_table_bg) {
3512 				ret = pcb->moal_malloc(
3513 					pmadapter->pmoal_handle, i,
3514 					MLAN_MEM_DEF,
3515 					(t_u8 **)&pmadapter->tx_power_table_bg);
3516 				if (ret != MLAN_STATUS_SUCCESS ||
3517 				    !pmadapter->tx_power_table_bg) {
3518 					PRINTM(MERROR,
3519 					       "Memory allocation for the BG-band power table failed!\n");
3520 					break;
3521 				}
3522 			}
3523 			memcpy_ext(pmadapter, pmadapter->tx_power_table_bg,
3524 				   data, i, i);
3525 			pmadapter->tx_power_table_bg_size = i;
3526 			data += i;
3527 			i = 0;
3528 			while ((i < pmadapter->tx_power_table_a_rows *
3529 					    pmadapter->tx_power_table_a_cols) &&
3530 			       (i < (tlv_buf_len -
3531 				     pmadapter->tx_power_table_bg_size))) {
3532 				i++;
3533 			}
3534 			if (!pmadapter->tx_power_table_a) {
3535 				ret = pcb->moal_malloc(
3536 					pmadapter->pmoal_handle, i,
3537 					MLAN_MEM_DEF,
3538 					(t_u8 **)&pmadapter->tx_power_table_a);
3539 				if (ret != MLAN_STATUS_SUCCESS ||
3540 				    !pmadapter->tx_power_table_a) {
3541 					PRINTM(MERROR,
3542 					       "Memory allocation for the A-band power table failed!\n");
3543 					break;
3544 				}
3545 			}
3546 			memcpy_ext(pmadapter, pmadapter->tx_power_table_a, data,
3547 				   i, i);
3548 			pmadapter->tx_power_table_a_size = i;
3549 			break;
3550 		case TLV_TYPE_POWER_TABLE_ATTR:
3551 			pmadapter->tx_power_table_bg_rows =
3552 				((power_table_attr_t *)data)->rows_2g;
3553 			pmadapter->tx_power_table_bg_cols =
3554 				((power_table_attr_t *)data)->cols_2g;
3555 			pmadapter->tx_power_table_a_rows =
3556 				((power_table_attr_t *)data)->rows_5g;
3557 			pmadapter->tx_power_table_a_cols =
3558 				((power_table_attr_t *)data)->cols_5g;
3559 			PRINTM(MCMD_D,
3560 			       "OTP region: bg_row=%d,bg_cols=%d a_row=%d, a_cols=%d\n",
3561 			       pmadapter->tx_power_table_bg_rows,
3562 			       pmadapter->tx_power_table_bg_cols,
3563 			       pmadapter->tx_power_table_a_rows,
3564 			       pmadapter->tx_power_table_a_cols);
3565 			break;
3566 		default:
3567 			break;
3568 		}
3569 		tlv_buf += (sizeof(*head) + tlv_buf_len);
3570 		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
3571 	}
3572 	if (!pmadapter->cfp_otp_bg || !pmadapter->tx_power_table_bg)
3573 		goto out;
3574 	/* Set remaining flags for BG */
3575 	rows = pmadapter->tx_power_table_bg_rows;
3576 	cols = pmadapter->tx_power_table_bg_cols;
3577 
3578 	for (i = 0; i < rows; i++) {
3579 		k = (i * cols) + 1;
3580 		if ((pmadapter->cfp_otp_bg + i)->dynamic.flags &
3581 		    NXP_CHANNEL_DISABLED)
3582 			continue;
3583 
3584 		if (pmadapter->tx_power_table_bg[k + MOD_CCK] == 0)
3585 			(pmadapter->cfp_otp_bg + i)->dynamic.flags |=
3586 				NXP_CHANNEL_NO_CCK;
3587 
3588 		if (pmadapter->tx_power_table_bg[k + MOD_OFDM_PSK] == 0 &&
3589 		    pmadapter->tx_power_table_bg[k + MOD_OFDM_QAM16] == 0 &&
3590 		    pmadapter->tx_power_table_bg[k + MOD_OFDM_QAM64] == 0) {
3591 			(pmadapter->cfp_otp_bg + i)->dynamic.flags |=
3592 				NXP_CHANNEL_NO_OFDM;
3593 		}
3594 	}
3595 	if (pmadapter->cfp_otp_a)
3596 		wlan_sort_cfp_otp_table(pmadapter);
3597 out:
3598 	LEAVE();
3599 }
3600 
3601 /**
3602  *  @brief	This function deallocates otp cfp and power tables memory.
3603  *
3604  *  @param pmadapter	A pointer to mlan_adapter structure
3605  */
wlan_free_fw_cfp_tables(mlan_adapter * pmadapter)3606 void wlan_free_fw_cfp_tables(mlan_adapter *pmadapter)
3607 {
3608 	pmlan_callbacks pcb;
3609 
3610 	ENTER();
3611 
3612 	pcb = &pmadapter->callbacks;
3613 	if (pmadapter->otp_region)
3614 		pcb->moal_mfree(pmadapter->pmoal_handle,
3615 				(t_u8 *)pmadapter->otp_region);
3616 	if (pmadapter->cfp_otp_bg)
3617 		pcb->moal_mfree(pmadapter->pmoal_handle,
3618 				(t_u8 *)pmadapter->cfp_otp_bg);
3619 	if (pmadapter->tx_power_table_bg)
3620 		pcb->moal_mfree(pmadapter->pmoal_handle,
3621 				(t_u8 *)pmadapter->tx_power_table_bg);
3622 	pmadapter->otp_region = MNULL;
3623 	pmadapter->cfp_otp_bg = MNULL;
3624 	pmadapter->tx_power_table_bg = MNULL;
3625 	pmadapter->tx_power_table_bg_size = 0;
3626 	if (pmadapter->cfp_otp_a)
3627 		pcb->moal_mfree(pmadapter->pmoal_handle,
3628 				(t_u8 *)pmadapter->cfp_otp_a);
3629 	if (pmadapter->tx_power_table_a)
3630 		pcb->moal_mfree(pmadapter->pmoal_handle,
3631 				(t_u8 *)pmadapter->tx_power_table_a);
3632 	pmadapter->cfp_otp_a = MNULL;
3633 	pmadapter->tx_power_table_a = MNULL;
3634 	pmadapter->tx_power_table_a_size = 0;
3635 	LEAVE();
3636 }
3637 
3638 /**
3639  *  @brief Get DFS chan list
3640  *
3641  *  @param pmadapter    Pointer to mlan_adapter
3642  *  @param pioctl_req   Pointer to mlan_ioctl_req
3643  *
3644  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3645  */
wlan_get_cfp_table(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3646 mlan_status wlan_get_cfp_table(pmlan_adapter pmadapter,
3647 			       pmlan_ioctl_req pioctl_req)
3648 {
3649 	mlan_ds_misc_cfg *ds_misc_cfg = MNULL;
3650 	mlan_status ret = MLAN_STATUS_FAILURE;
3651 	chan_freq_power_t *cfp = MNULL;
3652 	t_u32 cfp_no = 0;
3653 
3654 	ENTER();
3655 	if (pioctl_req) {
3656 		ds_misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3657 		if (pioctl_req->action == MLAN_ACT_GET) {
3658 			cfp = wlan_get_region_cfp_table(
3659 				pmadapter, pmadapter->region_code,
3660 				ds_misc_cfg->param.cfp.band, &cfp_no);
3661 			if (cfp) {
3662 				ds_misc_cfg->param.cfp.num_chan = cfp_no;
3663 				memcpy_ext(pmadapter,
3664 					   ds_misc_cfg->param.cfp.cfp_tbl, cfp,
3665 					   cfp_no * sizeof(chan_freq_power_t),
3666 					   cfp_no * sizeof(chan_freq_power_t));
3667 			}
3668 			ret = MLAN_STATUS_SUCCESS;
3669 		}
3670 	}
3671 	LEAVE();
3672 	return ret;
3673 }
3674 
3675 /**
3676  *  @brief	Get power tables and cfp tables for set region code
3677  *			into the IOCTL request buffer
3678  *
3679  *  @param pmadapter	Private mlan adapter structure
3680  *  @param pioctl_req	Pointer to the IOCTL request structure
3681  *
3682  *  @return	success, otherwise fail
3683  *
3684  */
wlan_get_cfpinfo(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3685 mlan_status wlan_get_cfpinfo(pmlan_adapter pmadapter,
3686 			     pmlan_ioctl_req pioctl_req)
3687 {
3688 	chan_freq_power_t *cfp_bg = MNULL;
3689 	t_u32 cfp_no_bg = 0;
3690 	chan_freq_power_t *cfp_a = MNULL;
3691 	t_u32 cfp_no_a = 0;
3692 	t_u8 cfp_code_a = pmadapter->region_code;
3693 	t_u8 cfp_code_bg = pmadapter->region_code;
3694 	t_u32 len = 0, size = 0;
3695 	t_u8 *req_buf, *tmp;
3696 	mlan_status ret = MLAN_STATUS_SUCCESS;
3697 
3698 	ENTER();
3699 
3700 	if (!pioctl_req || !pioctl_req->pbuf) {
3701 		PRINTM(MERROR, "MLAN IOCTL information is not present!\n");
3702 		ret = MLAN_STATUS_FAILURE;
3703 		goto out;
3704 	}
3705 	/* Calculate the total response size required to return region,
3706 	 * country codes, cfp tables and power tables
3707 	 */
3708 	size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
3709 	/* Add size to store region, country and environment codes */
3710 	size += sizeof(t_u32);
3711 	if (pmadapter->cfp_code_bg)
3712 		cfp_code_bg = pmadapter->cfp_code_bg;
3713 
3714 	/* Get cfp table and its size corresponding to the region code */
3715 	cfp_bg = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
3716 					   BAND_G | BAND_B, &cfp_no_bg);
3717 	size += cfp_no_bg * sizeof(chan_freq_power_t);
3718 	if (pmadapter->cfp_code_a)
3719 		cfp_code_a = pmadapter->cfp_code_a;
3720 	cfp_a = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
3721 					  &cfp_no_a);
3722 	size += cfp_no_a * sizeof(chan_freq_power_t);
3723 	if (pmadapter->otp_region)
3724 		size += sizeof(pmadapter->otp_region->environment);
3725 
3726 	/* Get power table size */
3727 	if (pmadapter->tx_power_table_bg) {
3728 		size += pmadapter->tx_power_table_bg_size;
3729 		/* Add size to store table size, rows and cols */
3730 		size += 3 * sizeof(t_u32);
3731 	}
3732 	if (pmadapter->tx_power_table_a) {
3733 		size += pmadapter->tx_power_table_a_size;
3734 		size += 3 * sizeof(t_u32);
3735 	}
3736 	/* Check information buffer length of MLAN IOCTL */
3737 	if (pioctl_req->buf_len < size) {
3738 		PRINTM(MWARN,
3739 		       "MLAN IOCTL information buffer length is too short.\n");
3740 		pioctl_req->buf_len_needed = size;
3741 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3742 		ret = MLAN_STATUS_RESOURCE;
3743 		goto out;
3744 	}
3745 	/* Copy the total size of region code, country code and environment
3746 	 * in first four bytes of the IOCTL request buffer and then copy
3747 	 * codes respectively in following bytes
3748 	 */
3749 	req_buf = (t_u8 *)pioctl_req->pbuf;
3750 	size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
3751 	if (pmadapter->otp_region)
3752 		size += sizeof(pmadapter->otp_region->environment);
3753 	tmp = (t_u8 *)&size;
3754 	memcpy_ext(pmadapter, req_buf, tmp, sizeof(size), sizeof(size));
3755 	len += sizeof(size);
3756 	memcpy_ext(pmadapter, req_buf + len, &pmadapter->region_code,
3757 		   sizeof(pmadapter->region_code),
3758 		   sizeof(pmadapter->region_code));
3759 	len += sizeof(pmadapter->region_code);
3760 	memcpy_ext(pmadapter, req_buf + len, &pmadapter->country_code,
3761 		   sizeof(pmadapter->country_code),
3762 		   sizeof(pmadapter->country_code));
3763 	len += sizeof(pmadapter->country_code);
3764 	if (pmadapter->otp_region) {
3765 		memcpy_ext(pmadapter, req_buf + len,
3766 			   &pmadapter->otp_region->environment,
3767 			   sizeof(pmadapter->otp_region->environment),
3768 			   sizeof(pmadapter->otp_region->environment));
3769 		len += sizeof(pmadapter->otp_region->environment);
3770 	}
3771 	/* copy the cfp table size followed by the entire table */
3772 	if (!cfp_bg)
3773 		goto out;
3774 	size = cfp_no_bg * sizeof(chan_freq_power_t);
3775 	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3776 	len += sizeof(size);
3777 	memcpy_ext(pmadapter, req_buf + len, cfp_bg, size, size);
3778 	len += size;
3779 	if (!cfp_a)
3780 		goto out;
3781 	size = cfp_no_a * sizeof(chan_freq_power_t);
3782 	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3783 	len += sizeof(size);
3784 	memcpy_ext(pmadapter, req_buf + len, cfp_a, size, size);
3785 	len += size;
3786 	/* Copy the size of the power table, number of rows, number of cols
3787 	 * and the entire power table
3788 	 */
3789 	if (!pmadapter->tx_power_table_bg)
3790 		goto out;
3791 	size = pmadapter->tx_power_table_bg_size;
3792 	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3793 	len += sizeof(size);
3794 
3795 	/* No. of rows */
3796 	size = pmadapter->tx_power_table_bg_rows;
3797 	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3798 	len += sizeof(size);
3799 
3800 	/* No. of cols */
3801 	size = pmadapter->tx_power_table_bg_size /
3802 	       pmadapter->tx_power_table_bg_rows;
3803 	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3804 	len += sizeof(size);
3805 	memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_bg,
3806 		   pmadapter->tx_power_table_bg_size,
3807 		   pmadapter->tx_power_table_bg_size);
3808 	len += pmadapter->tx_power_table_bg_size;
3809 	if (!pmadapter->tx_power_table_a)
3810 		goto out;
3811 	size = pmadapter->tx_power_table_a_size;
3812 	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3813 	len += sizeof(size);
3814 
3815 	/* No. of rows */
3816 	size = pmadapter->tx_power_table_a_rows;
3817 	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3818 	len += sizeof(size);
3819 
3820 	/* No. of cols */
3821 	size = pmadapter->tx_power_table_a_size /
3822 	       pmadapter->tx_power_table_a_rows;
3823 	memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3824 	len += sizeof(size);
3825 	memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_a,
3826 		   pmadapter->tx_power_table_a_size,
3827 		   pmadapter->tx_power_table_a_size);
3828 	len += pmadapter->tx_power_table_a_size;
3829 out:
3830 	if (pioctl_req)
3831 		pioctl_req->data_read_written = len;
3832 
3833 	LEAVE();
3834 	return ret;
3835 }
3836