xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/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  *  Copyright (C) 2009-2017, Marvell International Ltd.
8  *
9  *  This software file (the "File") is distributed by Marvell International
10  *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
11  *  (the "License").  You may use, redistribute and/or modify this File in
12  *  accordance with the terms and conditions of the License, a copy of which
13  *  is available by writing to the Free Software Foundation, Inc.,
14  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
15  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
16  *
17  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
20  *  this warranty disclaimer.
21  */
22 
23 /*************************************************************
24 Change Log:
25     04/16/2009: initial version
26 ************************************************************/
27 
28 #include "mlan.h"
29 #include "mlan_util.h"
30 #include "mlan_fw.h"
31 #include "mlan_join.h"
32 #include "mlan_main.h"
33 
34 /********************************************************
35 			Local Variables
36 ********************************************************/
37 
38 /** 100mW */
39 #define WLAN_TX_PWR_DEFAULT     20
40 /** 100mW */
41 #define WLAN_TX_PWR_00_DEFAULT      20
42 /** 100mW */
43 #define WLAN_TX_PWR_US_DEFAULT      20
44 /** 100mW */
45 #define WLAN_TX_PWR_JP_BG_DEFAULT   20
46 /** 200mW */
47 #define WLAN_TX_PWR_JP_A_DEFAULT    23
48 /** 100mW */
49 #define WLAN_TX_PWR_FR_100MW        20
50 /** 10mW */
51 #define WLAN_TX_PWR_FR_10MW         10
52 /** 100mW */
53 #define WLAN_TX_PWR_EMEA_DEFAULT    20
54 /** 2000mW */
55 #define WLAN_TX_PWR_CN_2000MW       33
56 /** 200mW */
57 #define WLAN_TX_PWR_200MW   23
58 /** 1000mW */
59 #define WLAN_TX_PWR_1000MW   30
60 /** 30mW */
61 #define WLAN_TX_PWR_SP_30MW   14
62 /** 60mW */
63 #define WLAN_TX_PWR_SP_60MW   17
64 /** 25mW */
65 #define WLAN_TX_PWR_25MW   14
66 /** 250mW */
67 #define WLAN_TX_PWR_250MW   24
68 
69 /** Region code mapping */
70 typedef struct _country_code_mapping {
71     /** Region */
72 	t_u8 country_code[COUNTRY_CODE_LEN];
73     /** Code for B/G CFP table */
74 	t_u8 cfp_code_bg;
75     /** Code for A CFP table */
76 	t_u8 cfp_code_a;
77 } country_code_mapping_t;
78 
79 #define EU_CFP_CODE_BG  0x30
80 #define EU_CFP_CODE_A   0x30
81 
82 /** Region code mapping table */
83 static country_code_mapping_t country_code_mapping[] = {
84 	{"US", 0x10, 0x10},	/* US FCC      */
85 	{"CA", 0x10, 0x20},	/* IC Canada   */
86 	{"SG", 0x10, 0x10},	/* Singapore   */
87 	{"EU", 0x30, 0x30},	/* ETSI        */
88 	{"AU", 0x30, 0x30},	/* Australia   */
89 	{"KR", 0x30, 0x30},	/* Republic Of Korea */
90 	{"JP", 0xFF, 0x40},	/* Japan       */
91 	{"CN", 0x30, 0x50},	/* China       */
92 	{"BR", 0x01, 0x09},	/* Brazil      */
93 	{"RU", 0x30, 0x0f},	/* Russia      */
94 	{"IN", 0x10, 0x06},	/* India       */
95 	{"MY", 0x30, 0x06},	/* Malaysia    */
96 };
97 
98 /** Country code for ETSI */
99 static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
100 	"AL", "AD", "AT", "AU", "BY", "BE", "BA", "BG", "HR", "CY",
101 	"CZ", "DK", "EE", "FI", "FR", "MK", "DE", "GR", "HU", "IS",
102 	"IE", "IT", "KR", "LV", "LI", "LT", "LU", "MT", "MD", "MC",
103 	"ME", "NL", "NO", "PL", "RO", "RU", "SM", "RS", "SI", "SK",
104 	"ES", "SE", "CH", "TR", "UA", "UK", "GB"
105 };
106 
107 /**
108  * The structure for Channel-Frequency-Power table
109  */
110 typedef struct _cfp_table {
111     /** Region or Code */
112 	t_u8 code;
113     /** Frequency/Power */
114 	chan_freq_power_t *cfp;
115     /** No of CFP flag */
116 	int cfp_no;
117 } cfp_table_t;
118 
119 /* Format { Channel, Frequency (MHz), MaxTxPower } */
120 /** Band: 'B/G', Region: USA FCC/Canada IC */
121 static chan_freq_power_t channel_freq_power_US_BG[] = {
122 	{1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE},
123 	{2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE},
124 	{3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE},
125 	{4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE},
126 	{5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE},
127 	{6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE},
128 	{7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE},
129 	{8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE},
130 	{9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE},
131 	{10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE},
132 	{11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE}
133 };
134 
135 /** Band: 'B/G', Region: Europe ETSI/China */
136 static chan_freq_power_t channel_freq_power_EU_BG[] = {
137 	{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
138 	{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
139 	{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
140 	{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
141 	{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
142 	{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
143 	{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
144 	{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
145 	{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
146 	{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
147 	{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
148 	{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
149 	{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}
150 };
151 
152 /** Band: 'B/G', Region: Japan */
153 static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
154 	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
155 	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
156 	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
157 	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
158 	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
159 	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
160 	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
161 	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
162 	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
163 	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
164 	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
165 	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
166 	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
167 };
168 
169 /** Band: 'B/G', Region: Japan */
170 static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
171 	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
172 };
173 
174 /** Band: 'B/G', Region: Japan */
175 static chan_freq_power_t channel_freq_power_JPNFE_BG[] = {
176 	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
177 	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
178 	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
179 	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
180 	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
181 	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
182 	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
183 	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
184 	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
185 	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
186 	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
187 	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE},
188 	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE}
189 };
190 
191 /** Band : 'B/G', Region: Brazil */
192 static chan_freq_power_t channel_freq_power_BR_BG[] = {
193 	{1, 2412, WLAN_TX_PWR_1000MW, MFALSE},
194 	{2, 2417, WLAN_TX_PWR_1000MW, MFALSE},
195 	{3, 2422, WLAN_TX_PWR_1000MW, MFALSE},
196 	{4, 2427, WLAN_TX_PWR_1000MW, MFALSE},
197 	{5, 2432, WLAN_TX_PWR_1000MW, MFALSE},
198 	{6, 2437, WLAN_TX_PWR_1000MW, MFALSE},
199 	{7, 2442, WLAN_TX_PWR_1000MW, MFALSE},
200 	{8, 2447, WLAN_TX_PWR_1000MW, MFALSE},
201 	{9, 2452, WLAN_TX_PWR_1000MW, MFALSE},
202 	{10, 2457, WLAN_TX_PWR_1000MW, MFALSE},
203 	{11, 2462, WLAN_TX_PWR_1000MW, MFALSE},
204 	{12, 2467, WLAN_TX_PWR_1000MW, MFALSE},
205 	{13, 2472, WLAN_TX_PWR_1000MW, MFALSE},
206 };
207 
208 /** Band : 'B/G', Region: Special */
209 static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
210 	{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
211 	{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
212 	{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
213 	{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
214 	{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
215 	{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
216 	{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
217 	{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
218 	{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
219 	{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
220 	{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
221 	{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
222 	{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
223 	{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
224 };
225 
226 /**
227  * The 2.4GHz CFP tables
228  */
229 static cfp_table_t cfp_table_BG[] = {
230 	{
231 	 0x01,			/* Brazil */
232 	 channel_freq_power_BR_BG,
233 	 NELEMENTS(channel_freq_power_BR_BG),
234 	 },
235 	{0x10,			/* US FCC */
236 	 channel_freq_power_US_BG,
237 	 NELEMENTS(channel_freq_power_US_BG),
238 	 },
239 	{0x20,			/* CANADA IC */
240 	 channel_freq_power_US_BG,
241 	 NELEMENTS(channel_freq_power_US_BG),
242 	 },
243 	{0x30,			/* EU */
244 	 channel_freq_power_EU_BG,
245 	 NELEMENTS(channel_freq_power_EU_BG),
246 	 },
247 	{0x40,			/* JAPAN */
248 	 channel_freq_power_JPN40_BG,
249 	 NELEMENTS(channel_freq_power_JPN40_BG),
250 	 },
251 	{0x41,			/* JAPAN */
252 	 channel_freq_power_JPN41_BG,
253 	 NELEMENTS(channel_freq_power_JPN41_BG),
254 	 },
255 	{0x50,			/* China */
256 	 channel_freq_power_EU_BG,
257 	 NELEMENTS(channel_freq_power_EU_BG),
258 	 },
259 	{
260 	 0xfe,			/* JAPAN */
261 	 channel_freq_power_JPNFE_BG,
262 	 NELEMENTS(channel_freq_power_JPNFE_BG),
263 	 },
264 	{0xff,			/* Special */
265 	 channel_freq_power_SPECIAL_BG,
266 	 NELEMENTS(channel_freq_power_SPECIAL_BG),
267 	 },
268 /* Add new region here */
269 };
270 
271 /** Number of the CFP tables for 2.4GHz */
272 #define MLAN_CFP_TABLE_SIZE_BG  (NELEMENTS(cfp_table_BG))
273 
274 /* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
275 /** Band: 'A', Region: World FCC */
276 
277 /* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
278 /** Band: 'A', Region: USA FCC */
279 static chan_freq_power_t channel_freq_power_A[] = {
280 	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
281 	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
282 	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
283 	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
284 	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
285 	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
286 	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
287 	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
288 	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
289 	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
290 	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
291 	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
292 	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
293 	{120, 5600, WLAN_TX_PWR_US_DEFAULT, MTRUE},
294 	{124, 5620, WLAN_TX_PWR_US_DEFAULT, MTRUE},
295 	{128, 5640, WLAN_TX_PWR_US_DEFAULT, MTRUE},
296 	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
297 	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
298 	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
299 	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
300 	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
301 	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
302 	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
303 	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
304 };
305 
306 /** Band: 'A', Region: Canada IC */
307 static chan_freq_power_t channel_freq_power_CAN_A[] = {
308 	{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
309 	{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
310 	{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
311 	{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
312 	{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
313 	{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
314 	{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
315 	{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
316 	{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
317 	{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
318 	{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
319 	{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
320 	{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
321 	{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
322 	{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
323 	{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
324 	{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
325 	{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
326 	{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
327 	{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
328 	{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
329 };
330 
331 /** Band: 'A', Region: Europe ETSI */
332 static chan_freq_power_t channel_freq_power_EU_A[] = {
333 	{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
334 	{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
335 	{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
336 	{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
337 	{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
338 	{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
339 	{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
340 	{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
341 	{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
342 	{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
343 	{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
344 	{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
345 	{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
346 	{120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
347 	{124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
348 	{128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
349 	{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
350 	{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
351 	{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
352 	{149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
353 	{153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
354 	{157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
355 	{161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
356 	{165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE}
357 };
358 
359 /** Band: 'A', Region: Japan */
360 static chan_freq_power_t channel_freq_power_JPN_A[] = {
361 	{36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
362 	{40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
363 	{44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
364 	{48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
365 	{52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
366 	{56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
367 	{60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
368 	{64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
369 	{100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
370 	{104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
371 	{108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
372 	{112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
373 	{116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
374 	{120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
375 	{124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
376 	{128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
377 	{132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
378 	{136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
379 	{140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE}
380 };
381 
382 /** Band: 'A', Region: China */
383 static chan_freq_power_t channel_freq_power_CN_A[] = {
384 	{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
385 	{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
386 	{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
387 	{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
388 	{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
389 	{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
390 	{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
391 	{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
392 	{149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE},
393 	{153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE},
394 	{157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE},
395 	{161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE},
396 	{165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE}
397 };
398 
399 /** Band: 'A', NULL */
400 static chan_freq_power_t channel_freq_power_NULL_A[] = {
401 };
402 
403 /** Band: 'A', Region: Spain/Austria/Brazil */
404 static chan_freq_power_t channel_freq_power_SPN2_A[] = {
405 	{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
406 	{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
407 	{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
408 	{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
409 	{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
410 	{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
411 	{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
412 	{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
413 };
414 
415 /** Band: 'A', Region: Brazil */
416 static chan_freq_power_t channel_freq_power_BR1_A[] = {
417 	{100, 5500, WLAN_TX_PWR_250MW, MTRUE},
418 	{104, 5520, WLAN_TX_PWR_250MW, MTRUE},
419 	{108, 5540, WLAN_TX_PWR_250MW, MTRUE},
420 	{112, 5560, WLAN_TX_PWR_250MW, MTRUE},
421 	{116, 5580, WLAN_TX_PWR_250MW, MTRUE},
422 	{120, 5600, WLAN_TX_PWR_250MW, MTRUE},
423 	{124, 5620, WLAN_TX_PWR_250MW, MTRUE},
424 	{128, 5640, WLAN_TX_PWR_250MW, MTRUE},
425 	{132, 5660, WLAN_TX_PWR_250MW, MTRUE},
426 	{136, 5680, WLAN_TX_PWR_250MW, MTRUE},
427 	{140, 5700, WLAN_TX_PWR_250MW, MTRUE},
428 };
429 
430 /** Band: 'A', Region: Brazil */
431 static chan_freq_power_t channel_freq_power_BR2_A[] = {
432 	{149, 5745, WLAN_TX_PWR_1000MW, MFALSE},
433 	{153, 5765, WLAN_TX_PWR_1000MW, MFALSE},
434 	{157, 5785, WLAN_TX_PWR_1000MW, MFALSE},
435 	{161, 5805, WLAN_TX_PWR_1000MW, MFALSE},
436 	{165, 5825, WLAN_TX_PWR_1000MW, MFALSE}
437 };
438 
439 /** Band: 'A', Region: Russia */
440 static chan_freq_power_t channel_freq_power_RU_A[] = {
441 	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
442 	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
443 	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
444 	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
445 	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
446 	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
447 	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
448 	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
449 	{132, 5660, WLAN_TX_PWR_DEFAULT, MFALSE},
450 	{136, 5680, WLAN_TX_PWR_DEFAULT, MFALSE},
451 	{140, 5700, WLAN_TX_PWR_DEFAULT, MFALSE},
452 	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
453 	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
454 	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
455 	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
456 };
457 
458 /** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
459 static chan_freq_power_t channel_freq_power_low_band[] = {
460 	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
461 	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
462 	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
463 	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
464 };
465 
466 /** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
467 static chan_freq_power_t channel_freq_power_lower_middle_band[] = {
468 	{52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE},
469 	{56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE},
470 	{60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE},
471 	{64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE},
472 };
473 
474 /** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
475 static chan_freq_power_t channel_freq_power_upper_middle_band[] = {
476 	{100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE},
477 	{104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE},
478 	{108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE},
479 	{112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE},
480 	{116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE},
481 	{120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE},
482 	{124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE},
483 	{128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE},
484 	{132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE},
485 	{136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE},
486 	{140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE},
487 };
488 
489 /** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
490 static chan_freq_power_t channel_freq_power_high_band[] = {
491 	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
492 	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
493 	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
494 	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
495 	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
496 };
497 
498 /** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
499  * High band (5725-5850 MHz) channels */
500 static chan_freq_power_t channel_freq_power_low_high_band[] = {
501 	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
502 	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
503 	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
504 	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
505 	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
506 	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
507 	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
508 	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
509 	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
510 };
511 
512 /** Band: 'A', Code: 6, Low band (5150-5250 MHz) and
513  * mid low (5260-5320) and High band (5725-5850 MHz) channels */
514 static chan_freq_power_t channel_freq_power_low_middle_high_band[] = {
515 	{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
516 	{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
517 	{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
518 	{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
519 	{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
520 	{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
521 	{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
522 	{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
523 	{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
524 	{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
525 	{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
526 	{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
527 	{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
528 };
529 
530 /**
531  * The 5GHz CFP tables
532  */
533 static cfp_table_t cfp_table_A[] = {
534 	{0x1,			/* Low band (5150-5250 MHz) channels */
535 	 channel_freq_power_low_band,
536 	 NELEMENTS(channel_freq_power_low_band)
537 	 },
538 	{0x2,			/* Lower middle band (5250-5350 MHz) channels */
539 	 channel_freq_power_lower_middle_band,
540 	 NELEMENTS(channel_freq_power_lower_middle_band)
541 	 },
542 	{0x3,			/* Upper middle band (5470-5725 MHz) channels */
543 	 channel_freq_power_upper_middle_band,
544 	 NELEMENTS(channel_freq_power_upper_middle_band)
545 	 },
546 	{0x4,			/* High band (5725-5850 MHz) channels */
547 	 channel_freq_power_high_band,
548 	 NELEMENTS(channel_freq_power_high_band)
549 	 },
550 	{0x5,			/* Low band (5150-5250 MHz) and
551 				   High band (5725-5850 MHz) channels */
552 	 channel_freq_power_low_high_band,
553 	 NELEMENTS(channel_freq_power_low_high_band)
554 	 },
555 	{0x6,			/* Low band (5150-5250 MHz)
556 				   Mid band (5260-5320) and
557 				   High band (5725-5850 MHz) channels */
558 	 channel_freq_power_low_middle_high_band,
559 	 NELEMENTS(channel_freq_power_low_middle_high_band)
560 	 },
561 	{0x09,			/* SPAIN/Austria/Brazil */
562 	 channel_freq_power_SPN2_A,
563 	 NELEMENTS(channel_freq_power_SPN2_A),
564 	 },
565 	{0x0c,			/* Brazil */
566 	 channel_freq_power_BR1_A,
567 	 NELEMENTS(channel_freq_power_BR1_A),
568 	 },
569 	{0x0e,			/* Brazil */
570 	 channel_freq_power_BR2_A,
571 	 NELEMENTS(channel_freq_power_BR2_A),
572 	 },
573 	{0x0f,			/* Russia */
574 	 channel_freq_power_RU_A,
575 	 NELEMENTS(channel_freq_power_RU_A),
576 	 },
577 	{0x10,			/* US FCC */
578 	 channel_freq_power_A,
579 	 NELEMENTS(channel_freq_power_A),
580 	 },
581 	{0x20,			/* CANADA IC */
582 	 channel_freq_power_CAN_A,
583 	 NELEMENTS(channel_freq_power_CAN_A),
584 	 },
585 	{0x30,			/* EU */
586 	 channel_freq_power_EU_A,
587 	 NELEMENTS(channel_freq_power_EU_A),
588 	 },
589 	{0x40,			/* JAPAN */
590 	 channel_freq_power_JPN_A,
591 	 NELEMENTS(channel_freq_power_JPN_A),
592 	 },
593 	{0x41,			/* JAPAN */
594 	 channel_freq_power_JPN_A,
595 	 NELEMENTS(channel_freq_power_JPN_A),
596 	 },
597 	{0x50,			/* China */
598 	 channel_freq_power_CN_A,
599 	 NELEMENTS(channel_freq_power_CN_A),
600 	 },
601 	{0xfe,			/* JAPAN */
602 	 channel_freq_power_NULL_A,
603 	 NELEMENTS(channel_freq_power_NULL_A),
604 	 },
605 	{0xff,			/* Special */
606 	 channel_freq_power_JPN_A,
607 	 NELEMENTS(channel_freq_power_JPN_A),
608 	 },
609 /* Add new region here */
610 };
611 
612 /** Number of the CFP tables for 5GHz */
613 #define MLAN_CFP_TABLE_SIZE_A   (NELEMENTS(cfp_table_A))
614 
615 enum {
616 	RATEID_DBPSK1Mbps,	//(0)
617 	RATEID_DQPSK2Mbps,	//(1)
618 	RATEID_CCK5_5Mbps,	//(2)
619 	RATEID_CCK11Mbps,	//(3)
620 	RATEID_CCK22Mbps,	//(4)
621 	RATEID_OFDM6Mbps,	//(5)
622 	RATEID_OFDM9Mbps,	//(6)
623 	RATEID_OFDM12Mbps,	//(7)
624 	RATEID_OFDM18Mbps,	//(8)
625 	RATEID_OFDM24Mbps,	//(9)
626 	RATEID_OFDM36Mbps,	//(10)
627 	RATEID_OFDM48Mbps,	//(11)
628 	RATEID_OFDM54Mbps,	//(12)
629 	RATEID_OFDM72Mbps,	//(13)
630 };
631 
632 static const t_u8 rateUnit_500Kbps[] = {
633 	(10 / 5),		/* 1Mbps */
634 	(20 / 5),		/* 2Mbps */
635 
636 	(55 / 5),		/* 5.5Mbps */
637 	(110 / 5),		/* 11Mbps */
638 	(10 / 5),		/* 22Mbps, intentionally set to 1Mbps because it's not available */
639 
640 	(60 / 5),		/* 6Mbps */
641 	(90 / 5),		/* 9Mbps */
642 	(120 / 5),		/* 12Mbps */
643 	(180 / 5),		/* 18Mbps */
644 	(240 / 5),		/* 24Mbps */
645 	(360 / 5),		/* 36Mbps */
646 	(480 / 5),		/* 48Mbps */
647 	(540 / 5),		/* 54Mbps */
648 	(60 / 5),		/* 72Mbps  intentionally set to 6Mbps because it's not available */
649 };
650 
651 typedef struct _rate_map {
652     /** Rate, in 0.5Mbps */
653 	t_u32 rate;
654     /** Mrvl rate id, refer to RATEID_XXX in FW */
655 	t_u32 id;
656     /** nss: 0-nss1, 1-nss2 */
657 	t_u8 nss;
658 } rate_map;
659 
660 /** rate_map_table_1x1 is based on rate_map_table_2x2 and remove nss2 part.
661  * For the chip who only support 1x1, Mrvl rate idx define is different with 2x2 in FW
662  * We need redefine a bitrate to Mrvl rate idx table for 1x1 chip.
663   */
664 const rate_map rate_map_table_1x1[] = {
665 	/* LG <--> Mrvl rate idx */
666 	{2, 0, 0},		//RATEID_DBPSK1Mbps
667 	{4, 1, 0},		//RATEID_DQPSK2Mbps
668 	{11, 2, 0},		//RATEID_CCK5_5Mbps
669 	{22, 3, 0},		//RATEID_CCK11Mbps
670 	{44, 4, 0},		//RATEID_CCK22Mbps
671 	{12, 5, 0},		//RATEID_OFDM6Mbps
672 	{18, 6, 0},		//RATEID_OFDM9Mbps
673 	{24, 7, 0},		//RATEID_OFDM12Mbps
674 	{36, 8, 0},		//RATEID_OFDM18Mbps
675 	{48, 9, 0},		//RATEID_OFDM24Mbps
676 	{72, 10, 0},		//RATEID_OFDM36Mbps
677 	{96, 11, 0},		//RATEID_OFDM48Mbps
678 	{108, 12, 0},		//RATEID_OFDM54Mbps
679 	{144, 13, 0},		//RATEID_OFDM72Mbps
680 
681 	/* HT bw20 <--> Mrvl rate idx */
682 	{13, 14, 0},		//RATEID_MCS0_6d5Mbps
683 	{26, 15, 0},		//RATEID_MCS1_13Mbps
684 	{39, 16, 0},		//RATEID_MCS2_19d5Mbps
685 	{52, 17, 0},		//RATEID_MCS3_26Mbps
686 	{78, 18, 0},		//RATEID_MCS4_39Mbps
687 	{104, 19, 0},		//RATEID_MCS5_52Mbps
688 	{117, 20, 0},		//RATEID_MCS6_58d5Mbps
689 	{130, 21, 0},		//RATEID_MCS7_65Mbps
690 
691 	/* HT bw40<--> Mrvl rate idx */
692 	{12, 22, 0},		//RATEID_MCS32BW40_6Mbps,   for 1x1 start from 22
693 	{27, 23, 0},		//RATEID_MCS0BW40_13d5Mbps
694 	{54, 24, 0},		//RATEID_MCS1BW40_27Mbps
695 	{81, 25, 0},		//RATEID_MCS2BW40_40d5Mbps
696 	{108, 26, 0},		//RATEID_MCS3BW40_54Mbps
697 	{162, 27, 0},		//RATEID_MCS4BW40_81Mbps
698 	{216, 28, 0},		//RATEID_MCS5BW40_108Mbps
699 	{243, 29, 0},		//RATEID_MCS6BW40_121d5Mbps
700 	{270, 30, 0},		//RATEID_MCS7BW40_135Mbps
701 
702 };
703 
704 /********************************************************
705 			Global Variables
706 ********************************************************/
707 /**
708  * The table to keep region code
709  */
710 t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = {
711 	0x10, 0x20, 0x30, 0x40, 0x41, 0x50, 0xfe, 0xff
712 };
713 
714 /** The table to keep CFP code for BG */
715 t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG] = { };
716 
717 /** The table to keep CFP code for A */
718 t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = { 0x1, 0x2, 0x3, 0x4, 0x5 };
719 
720 /**
721  * The rates supported for ad-hoc B mode
722  */
723 t_u8 AdhocRates_B[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
724 
725 /**
726  * The rates supported for ad-hoc G mode
727  */
728 t_u8 AdhocRates_G[G_SUPPORTED_RATES] = {
729 	0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
730 };
731 
732 /**
733  * The rates supported for ad-hoc BG mode
734  */
735 t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = {
736 	0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
737 	0x60, 0x6c, 0x00
738 };
739 
740 /**
741  * The rates supported in A mode for ad-hoc
742  */
743 t_u8 AdhocRates_A[A_SUPPORTED_RATES] = {
744 	0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
745 };
746 
747 /**
748  * The rates supported in A mode (used for BAND_A)
749  */
750 t_u8 SupportedRates_A[A_SUPPORTED_RATES] = {
751 	0x0c, 0x12, 0x18, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
752 };
753 
754 /**
755  * The rates supported by the card
756  */
757 t_u16 WlanDataRates[WLAN_SUPPORTED_RATES_EXT] = {
758 	0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
759 	0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,
760 	0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75,
761 	0x82, 0x0C, 0x1B, 0x36, 0x51, 0x6C, 0xA2,
762 	0xD8, 0xF3, 0x10E, 0x00
763 };
764 
765 /**
766  * The rates supported in B mode
767  */
768 t_u8 SupportedRates_B[B_SUPPORTED_RATES] = {
769 	0x02, 0x04, 0x0b, 0x16, 0x00
770 };
771 
772 /**
773  * The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
774  */
775 t_u8 SupportedRates_G[G_SUPPORTED_RATES] = {
776 	0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00
777 };
778 
779 /**
780  * The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
781  */
782 t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = {
783 	0x02, 0x04, 0x0b, 0x0c, 0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
784 	0x60, 0x6c, 0x00
785 };
786 
787 /**
788  * The rates supported in N mode
789  */
790 t_u8 SupportedRates_N[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
791 
792 /********************************************************
793 			Local Functions
794 ********************************************************/
795 /**
796  *  @brief Find a character in a string.
797  *
798  *  @param pmadapter    A pointer to mlan_adapter structure
799  *  @param s            A pointer to string
800  *  @param c            Character to be located
801  *  @param n            The length of string
802  *
803  *  @return        A pointer to the first occurrence of c in string, or MNULL if c is not found.
804  */
805 static void *
wlan_memchr(pmlan_adapter pmadapter,void * s,int c,int n)806 wlan_memchr(pmlan_adapter pmadapter, void *s, int c, int n)
807 {
808 	const t_u8 *p = (t_u8 *)s;
809 
810 	ENTER();
811 
812 	while (n--) {
813 		if ((t_u8)c == *p++) {
814 			LEAVE();
815 			return (void *)(p - 1);
816 		}
817 	}
818 
819 	LEAVE();
820 	return MNULL;
821 }
822 
823 /**
824  *  @brief This function finds the CFP in
825  *          cfp_table_BG/A based on region/code and band parameter.
826  *
827  *  @param pmadapter  A pointer to mlan_adapter structure
828  *  @param region     The region code
829  *  @param band       The band
830  *  @param cfp_no     A pointer to CFP number
831  *
832  *  @return           A pointer to CFP
833  */
834 static chan_freq_power_t *
wlan_get_region_cfp_table(pmlan_adapter pmadapter,t_u8 region,t_u8 band,int * cfp_no)835 wlan_get_region_cfp_table(pmlan_adapter pmadapter, t_u8 region, t_u8 band,
836 			  int *cfp_no)
837 {
838 	t_u32 i;
839 	t_u8 cfp_bg, cfp_a;
840 
841 	ENTER();
842 
843 	cfp_bg = cfp_a = region;
844 	if (!region) {
845 		/* Invalid region code, use CFP code */
846 		cfp_bg = pmadapter->cfp_code_bg;
847 		cfp_a = pmadapter->cfp_code_a;
848 	}
849 	if (band & (BAND_B | BAND_G | BAND_GN)) {
850 		/* Return the FW cfp table for requested region code, if available.
851 		 * If region is not forced and the requested region code is different,
852 		 * simply return the corresponding pre-defined table.
853 		 */
854 		if (pmadapter->otp_region && pmadapter->cfp_otp_bg) {
855 			if (pmadapter->otp_region->force_reg ||
856 			    (cfp_bg ==
857 			     (t_u8)pmadapter->otp_region->region_code)) {
858 				*cfp_no = FW_CFP_TABLE_MAX_ROWS_BG;
859 				LEAVE();
860 				return pmadapter->cfp_otp_bg;
861 			}
862 		}
863 		for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
864 			PRINTM(MINFO, "cfp_table_BG[%d].code=%d\n", i,
865 			       cfp_table_BG[i].code);
866 			/* Check if region/code matches for BG bands */
867 			if (cfp_table_BG[i].code == cfp_bg) {
868 				/* Select by band */
869 				*cfp_no = cfp_table_BG[i].cfp_no;
870 				LEAVE();
871 				return cfp_table_BG[i].cfp;
872 			}
873 		}
874 	}
875 	if (band & (BAND_A | BAND_AN)) {
876 		/* Return the FW cfp table for requested region code */
877 		if (pmadapter->otp_region && pmadapter->cfp_otp_a) {
878 			if (pmadapter->otp_region->force_reg ||
879 			    (cfp_a ==
880 			     (t_u8)pmadapter->otp_region->region_code)) {
881 				*cfp_no = FW_CFP_TABLE_MAX_ROWS_A;
882 				LEAVE();
883 				return pmadapter->cfp_otp_a;
884 			}
885 		}
886 		for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
887 			PRINTM(MINFO, "cfp_table_A[%d].code=%d\n", i,
888 			       cfp_table_A[i].code);
889 			/* Check if region/code matches for A bands */
890 			if (cfp_table_A[i].code == cfp_a) {
891 				/* Select by band */
892 				*cfp_no = cfp_table_A[i].cfp_no;
893 				LEAVE();
894 				return cfp_table_A[i].cfp;
895 			}
896 		}
897 	}
898 
899 	if (!region)
900 		PRINTM(MERROR, "Error Band[0x%x] or code[BG:%#x, A:%#x]\n",
901 		       band, cfp_bg, cfp_a);
902 	else
903 		PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band,
904 		       region);
905 
906 	LEAVE();
907 	return MNULL;
908 }
909 
910 /**
911  *  @brief This function copies dynamic CFP elements from one table to another.
912  *         Only copy elements where channel numbers match.
913  *
914  *  @param pmadapter   A pointer to mlan_adapter structure
915  *  @param cfp         Destination table
916  *  @param num_cfp     Number of elements in dest table
917  *  @param cfp_src     Source table
918  *  @param num_cfp_src Number of elements in source table
919  */
920 static t_void
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)921 wlan_cfp_copy_dynamic(pmlan_adapter pmadapter,
922 		      chan_freq_power_t *cfp, t_u8 num_cfp,
923 		      chan_freq_power_t *cfp_src, t_u8 num_cfp_src)
924 {
925 	int i, j;
926 	ENTER();
927 
928 	/* first clear dest dynamic blacklisted entries */
929 	for (i = 0; i < num_cfp; i++)
930 		cfp[i].dynamic.blacklist = MFALSE;
931 
932 	/* copy dynamic blacklisted entries from source where channels match */
933 	if (cfp_src) {
934 		for (i = 0; i < num_cfp; i++)
935 			for (j = 0; j < num_cfp_src; j++)
936 				if (cfp[i].channel == cfp_src[j].channel) {
937 					cfp[i].dynamic.blacklist =
938 						cfp_src[j].dynamic.blacklist;
939 					break;
940 				}
941 	}
942 
943 	LEAVE();
944 }
945 
946 /********************************************************
947 			Global Functions
948 ********************************************************/
949 /**
950  *  @brief This function converts region string to integer code
951  *
952  *  @param pmadapter        A pointer to mlan_adapter structure
953  *  @param country_code     Country string
954  *  @param cfp_bg           Pointer to buffer
955  *  @param cfp_a            Pointer to buffer
956  *
957  *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
958  */
959 mlan_status
wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,t_u8 * country_code,t_u8 * cfp_bg,t_u8 * cfp_a)960 wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter, t_u8 *country_code,
961 				   t_u8 *cfp_bg, t_u8 *cfp_a)
962 {
963 	t_u8 i;
964 
965 	ENTER();
966 
967 	/* Look for code in mapping table */
968 	for (i = 0; i < NELEMENTS(country_code_mapping); i++) {
969 		if (!memcmp(pmadapter, country_code_mapping[i].country_code,
970 			    country_code, COUNTRY_CODE_LEN - 1)) {
971 			*cfp_bg = country_code_mapping[i].cfp_code_bg;
972 			*cfp_a = country_code_mapping[i].cfp_code_a;
973 			LEAVE();
974 			return MLAN_STATUS_SUCCESS;
975 		}
976 	}
977 
978 	/* If still not found, look for code in EU country code table */
979 	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
980 		if (!memcmp(pmadapter, eu_country_code_table[i],
981 			    country_code, COUNTRY_CODE_LEN - 1)) {
982 			*cfp_bg = EU_CFP_CODE_BG;
983 			*cfp_a = EU_CFP_CODE_A;
984 			LEAVE();
985 			return MLAN_STATUS_SUCCESS;
986 		}
987 	}
988 
989 	LEAVE();
990 	return MLAN_STATUS_FAILURE;
991 }
992 
993 /**
994  *  @brief This function finds if given country code is in EU table
995  *
996  *  @param pmadapter        A pointer to mlan_adapter structure
997  *  @param country_code     Country string
998  *
999  *  @return                 MTRUE or MFALSE
1000  */
1001 t_bool
wlan_is_etsi_country(pmlan_adapter pmadapter,t_u8 * country_code)1002 wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
1003 {
1004 
1005 	t_u8 i;
1006 
1007 	ENTER();
1008 
1009 	/* Look for code in EU country code table */
1010 	for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
1011 		if (!memcmp(pmadapter, eu_country_code_table[i],
1012 			    country_code, COUNTRY_CODE_LEN - 1)) {
1013 			LEAVE();
1014 			return MTRUE;
1015 		}
1016 	}
1017 
1018 	LEAVE();
1019 	return MFALSE;
1020 }
1021 
1022 #define BAND_MASK_5G        0x03
1023 #define ANTENNA_OFFSET      2
1024 /**
1025  *   @brief This function adjust the antenna index
1026  *
1027  *   V16_FW_API: Bit0: ant A, Bit 1:ant B, Bit0 & Bit 1: A+B
1028  *   8887: case1: 0 - 2.4G ant A,  1- 2.4G antB, 2-- 5G ant C
1029  *   case2: 0 - 2.4G ant A,  1- 2.4G antB, 0x80- 5G antA, 0x81-5G ant B
1030  *   @param priv 	 A pointer to mlan_private structure
1031  *   @param prx_pd   A pointer to the RxPD structure
1032  *
1033  *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1034  */
1035 t_u8
wlan_adjust_antenna(pmlan_private priv,RxPD * prx_pd)1036 wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd)
1037 {
1038 	t_u8 antenna = prx_pd->antenna;
1039 	if (prx_pd->antenna == 0xff)
1040 		return 0;
1041 	if ((antenna & MBIT(0)) && (antenna & MBIT(1)))
1042 		antenna = 2;
1043 	else if (antenna & MBIT(1))
1044 		antenna = 1;
1045 	else if (antenna & MBIT(0))
1046 		antenna = 0;
1047 
1048 	return antenna;
1049 }
1050 
1051 /**
1052  *  @brief This function adjust the rate index
1053  *
1054  *  @param priv    A pointer to mlan_private structure
1055  *  @param rx_rate rx rate
1056  *  @param rate_info rate info
1057  *  @return        rate index
1058  */
1059 t_u8
wlan_adjust_data_rate(mlan_private * priv,t_u8 rx_rate,t_u8 rate_info)1060 wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info)
1061 {
1062 	t_u8 rate_index = 0;
1063 	t_u8 bw = 0;
1064 	t_bool sgi_enable = 0;
1065 
1066 #define MAX_MCS_NUM_SUPP    16
1067 
1068 #define MAX_MCS_NUM_AC    10
1069 #define RATE_INDEX_MCS0   12
1070 	bw = (rate_info & 0xC) >> 2;
1071 	sgi_enable = (rate_info & 0x10) >> 4;
1072 	if ((rate_info & 0x3) == 0) {
1073 		rate_index =
1074 			(rx_rate >
1075 			 MLAN_RATE_INDEX_OFDM0) ? rx_rate - 1 : rx_rate;
1076 	} else if ((rate_info & 0x03) == 1) {
1077 		rate_index = RATE_INDEX_MCS0 +
1078 			MAX_MCS_NUM_SUPP * 2 * sgi_enable +
1079 			MAX_MCS_NUM_SUPP * bw + rx_rate;
1080 	}
1081 	return rate_index;
1082 }
1083 
1084 #ifdef STA_SUPPORT
1085 #endif /* STA_SUPPORT */
1086 
1087 /**
1088  *  @brief convert ht_info to rate_info
1089  *
1090  *  @param ht_info      ht info
1091  *
1092  *  @return             rate info
1093  */
1094 t_u8
wlan_convert_v14_rate_ht_info(t_u8 ht_info)1095 wlan_convert_v14_rate_ht_info(t_u8 ht_info)
1096 {
1097 	t_u8 rate_info = 0;
1098 	rate_info = ht_info & 0x01;
1099 	/* band */
1100 	rate_info |= (ht_info & MBIT(1)) << 1;
1101 	/* short GI */
1102 	rate_info |= (ht_info & MBIT(2)) << 2;
1103 	return rate_info;
1104 }
1105 
1106 /**
1107  *  @brief Use index to get the data rate
1108  *
1109  *  @param pmadapter        A pointer to mlan_adapter structure
1110  *  @param index            The index of data rate
1111  *  @param tx_rate_info     Tx rate info
1112  *
1113  *  @return                 Data rate or 0
1114  */
1115 t_u32
wlan_index_to_data_rate(pmlan_adapter pmadapter,t_u8 index,t_u8 tx_rate_info)1116 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 tx_rate_info)
1117 {
1118 #define MCS_NUM_SUPP    8
1119 	t_u16 mcs_rate[4][MCS_NUM_SUPP] = { {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e},	/*LG 40M */
1120 	{0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c},	/*SG 40M */
1121 	{0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82},	/*LG 20M */
1122 	{0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90}
1123 	};			/*SG 20M */
1124 
1125 	t_u32 rate = 0;
1126 	t_u8 bw = 0;
1127 	t_u8 gi = 0;
1128 	ENTER();
1129 
1130 	if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
1131 		/* HT rate */
1132 		/* 20M: bw=0, 40M: bw=1 */
1133 		bw = (tx_rate_info & 0xC) >> 2;
1134 		/* LGI: gi =0, SGI: gi = 1 */
1135 		gi = (tx_rate_info & 0x10) >> 4;
1136 		if (index == MLAN_RATE_BITMAP_MCS0) {
1137 			if (gi == 1)
1138 				rate = 0x0D;	/* MCS 32 SGI rate */
1139 			else
1140 				rate = 0x0C;	/* MCS 32 LGI rate */
1141 		} else if (index < MCS_NUM_SUPP) {
1142 			if (bw <= 1)
1143 				rate = mcs_rate[2 * (1 - bw) + gi][index];
1144 			else
1145 				rate = WlanDataRates[0];
1146 		} else
1147 			rate = WlanDataRates[0];
1148 	} else {
1149 		/* 11n non HT rates */
1150 		if (index >= WLAN_SUPPORTED_RATES_EXT)
1151 			index = 0;
1152 		rate = WlanDataRates[index];
1153 	}
1154 	LEAVE();
1155 	return rate;
1156 }
1157 
1158 /**
1159  *  @brief Use rate to get the index
1160  *
1161  *  @param pmadapter    A pointer to mlan_adapter structure
1162  *  @param rate         Data rate
1163  *
1164  *  @return                     Index or 0
1165  */
1166 t_u8
wlan_data_rate_to_index(pmlan_adapter pmadapter,t_u32 rate)1167 wlan_data_rate_to_index(pmlan_adapter pmadapter, t_u32 rate)
1168 {
1169 	t_u16 *ptr;
1170 
1171 	ENTER();
1172 	if (rate) {
1173 		ptr = wlan_memchr(pmadapter, WlanDataRates, (t_u8)rate,
1174 				  sizeof(WlanDataRates));
1175 		if (ptr) {
1176 			LEAVE();
1177 			return (t_u8)(ptr - WlanDataRates);
1178 		}
1179 	}
1180 	LEAVE();
1181 	return 0;
1182 }
1183 
1184 /**
1185  *  @brief Get active data rates
1186  *
1187  *  @param pmpriv           A pointer to mlan_private structure
1188  *  @param bss_mode         The specified BSS mode (Infra/IBSS)
1189  *  @param config_bands     The specified band configuration
1190  *  @param rates            The buf to return the active rates
1191  *
1192  *  @return                 The number of Rates
1193  */
1194 t_u32
wlan_get_active_data_rates(mlan_private * pmpriv,t_u32 bss_mode,t_u8 config_bands,WLAN_802_11_RATES rates)1195 wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
1196 			   t_u8 config_bands, WLAN_802_11_RATES rates)
1197 {
1198 	t_u32 k;
1199 
1200 	ENTER();
1201 
1202 	if (pmpriv->media_connected != MTRUE) {
1203 		k = wlan_get_supported_rates(pmpriv, bss_mode, config_bands,
1204 					     rates);
1205 	} else {
1206 		k = wlan_copy_rates(rates, 0,
1207 				    pmpriv->curr_bss_params.data_rates,
1208 				    pmpriv->curr_bss_params.num_of_rates);
1209 	}
1210 
1211 	LEAVE();
1212 	return k;
1213 }
1214 
1215 #ifdef STA_SUPPORT
1216 /**
1217  *  @brief This function search through all the regions cfp table to find the channel,
1218  *            if the channel is found then gets the MIN txpower of the channel
1219  *            present in all the regions.
1220  *
1221  *  @param pmpriv       A pointer to mlan_private structure
1222  *  @param channel      Channel number.
1223  *
1224  *  @return             The Tx power
1225  */
1226 t_u8
wlan_get_txpwr_of_chan_from_cfp(mlan_private * pmpriv,t_u8 channel)1227 wlan_get_txpwr_of_chan_from_cfp(mlan_private *pmpriv, t_u8 channel)
1228 {
1229 	t_u8 i = 0;
1230 	t_u8 j = 0;
1231 	t_u8 tx_power = 0;
1232 	t_u32 cfp_no;
1233 	chan_freq_power_t *cfp = MNULL;
1234 	chan_freq_power_t *cfp_a = MNULL;
1235 	t_u32 cfp_no_a;
1236 
1237 	ENTER();
1238 
1239 	for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
1240 		/* Get CFP */
1241 		cfp = cfp_table_BG[i].cfp;
1242 		cfp_no = cfp_table_BG[i].cfp_no;
1243 		/* Find matching channel and get Tx power */
1244 		for (j = 0; j < cfp_no; j++) {
1245 			if ((cfp + j)->channel == channel) {
1246 				if (tx_power != 0)
1247 					tx_power =
1248 						MIN(tx_power,
1249 						    (cfp + j)->max_tx_power);
1250 				else
1251 					tx_power =
1252 						(t_u8)(cfp + j)->max_tx_power;
1253 				break;
1254 			}
1255 		}
1256 	}
1257 
1258 	for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
1259 		/* Get CFP */
1260 		cfp_a = cfp_table_A[i].cfp;
1261 		cfp_no_a = cfp_table_A[i].cfp_no;
1262 		for (j = 0; j < cfp_no_a; j++) {
1263 			if ((cfp_a + j)->channel == channel) {
1264 				if (tx_power != 0)
1265 					tx_power =
1266 						MIN(tx_power,
1267 						    (cfp_a + j)->max_tx_power);
1268 				else
1269 					tx_power =
1270 						(t_u8)((cfp_a +
1271 							j)->max_tx_power);
1272 				break;
1273 			}
1274 		}
1275 	}
1276 
1277 	LEAVE();
1278 	return tx_power;
1279 }
1280 
1281 /**
1282  *  @brief Get the channel frequency power info for a specific channel
1283  *
1284  *  @param pmadapter            A pointer to mlan_adapter structure
1285  *  @param band                 It can be BAND_A, BAND_G or BAND_B
1286  *  @param channel              The channel to search for
1287  *  @param region_channel       A pointer to region_chan_t structure
1288  *
1289  *  @return                     A pointer to chan_freq_power_t structure or MNULL if not found.
1290  */
1291 
1292 chan_freq_power_t *
wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter,t_u8 band,t_u16 channel,region_chan_t * region_channel)1293 wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter,
1294 				 t_u8 band,
1295 				 t_u16 channel, region_chan_t *region_channel)
1296 {
1297 	region_chan_t *rc;
1298 	chan_freq_power_t *cfp = MNULL;
1299 	int i, j;
1300 
1301 	ENTER();
1302 
1303 	for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
1304 		rc = &region_channel[j];
1305 
1306 		if (!rc->valid || !rc->pcfp)
1307 			continue;
1308 		switch (rc->band) {
1309 		case BAND_A:
1310 			switch (band) {
1311 			case BAND_AN:
1312 			case BAND_A | BAND_AN:
1313 			case BAND_A:	/* Matching BAND_A */
1314 				break;
1315 
1316 			default:
1317 				continue;
1318 			}
1319 			break;
1320 		case BAND_B:
1321 		case BAND_G:
1322 			switch (band) {
1323 			case BAND_GN:
1324 			case BAND_B | BAND_G | BAND_GN:
1325 			case BAND_G | BAND_GN:
1326 			case BAND_B | BAND_G:
1327 			case BAND_B:	/* Matching BAND_B/G */
1328 			case BAND_G:
1329 			case 0:
1330 				break;
1331 			default:
1332 				continue;
1333 			}
1334 			break;
1335 		default:
1336 			continue;
1337 		}
1338 		if (channel == FIRST_VALID_CHANNEL)
1339 			cfp = &rc->pcfp[0];
1340 		else {
1341 			for (i = 0; i < rc->num_cfp; i++) {
1342 				if (rc->pcfp[i].channel == channel) {
1343 					cfp = &rc->pcfp[i];
1344 					break;
1345 				}
1346 			}
1347 		}
1348 	}
1349 
1350 	if (!cfp && channel)
1351 		PRINTM(MCMND, "wlan_get_cfp_by_band_and_channel(): cannot find "
1352 		       "cfp by band %d & channel %d\n", band, channel);
1353 
1354 	LEAVE();
1355 	return cfp;
1356 }
1357 
1358 /**
1359  *  @brief Find the channel frequency power info for a specific channel
1360  *
1361  *  @param pmadapter    A pointer to mlan_adapter structure
1362  *  @param band         It can be BAND_A, BAND_G or BAND_B
1363  *  @param channel      The channel to search for
1364  *
1365  *  @return             A pointer to chan_freq_power_t structure or MNULL if not found.
1366  */
1367 chan_freq_power_t *
wlan_find_cfp_by_band_and_channel(mlan_adapter * pmadapter,t_u8 band,t_u16 channel)1368 wlan_find_cfp_by_band_and_channel(mlan_adapter *pmadapter,
1369 				  t_u8 band, t_u16 channel)
1370 {
1371 	chan_freq_power_t *cfp = MNULL;
1372 
1373 	ENTER();
1374 
1375 	/* Any station(s) with 11D enabled */
1376 	if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
1377 				 wlan_is_station) > 0)
1378 		cfp = wlan_get_cfp_by_band_and_channel(pmadapter, band, channel,
1379 						       pmadapter->
1380 						       universal_channel);
1381 	else
1382 		cfp = wlan_get_cfp_by_band_and_channel(pmadapter, band, channel,
1383 						       pmadapter->
1384 						       region_channel);
1385 
1386 	LEAVE();
1387 	return cfp;
1388 }
1389 
1390 /**
1391  *  @brief Find the channel frequency power info for a specific frequency
1392  *
1393  *  @param pmadapter    A pointer to mlan_adapter structure
1394  *  @param band         It can be BAND_A, BAND_G or BAND_B
1395  *  @param freq         The frequency to search for
1396  *
1397  *  @return         Pointer to chan_freq_power_t structure; MNULL if not found
1398  */
1399 chan_freq_power_t *
wlan_find_cfp_by_band_and_freq(mlan_adapter * pmadapter,t_u8 band,t_u32 freq)1400 wlan_find_cfp_by_band_and_freq(mlan_adapter *pmadapter, t_u8 band, t_u32 freq)
1401 {
1402 	chan_freq_power_t *cfp = MNULL;
1403 	region_chan_t *rc;
1404 	int i, j;
1405 
1406 	ENTER();
1407 
1408 	for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
1409 		rc = &pmadapter->region_channel[j];
1410 
1411 		/* Any station(s) with 11D enabled */
1412 		if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
1413 					 wlan_is_station) > 0)
1414 			rc = &pmadapter->universal_channel[j];
1415 
1416 		if (!rc->valid || !rc->pcfp)
1417 			continue;
1418 		switch (rc->band) {
1419 		case BAND_A:
1420 			switch (band) {
1421 			case BAND_AN:
1422 			case BAND_A | BAND_AN:
1423 			case BAND_A:	/* Matching BAND_A */
1424 				break;
1425 			default:
1426 				continue;
1427 			}
1428 			break;
1429 		case BAND_B:
1430 		case BAND_G:
1431 			switch (band) {
1432 			case BAND_GN:
1433 			case BAND_B | BAND_G | BAND_GN:
1434 			case BAND_G | BAND_GN:
1435 			case BAND_B | BAND_G:
1436 			case BAND_B:
1437 			case BAND_G:
1438 			case 0:
1439 				break;
1440 			default:
1441 				continue;
1442 			}
1443 			break;
1444 		default:
1445 			continue;
1446 		}
1447 		for (i = 0; i < rc->num_cfp; i++) {
1448 			if (rc->pcfp[i].freq == freq) {
1449 				cfp = &rc->pcfp[i];
1450 				break;
1451 			}
1452 		}
1453 	}
1454 
1455 	if (!cfp && freq)
1456 		PRINTM(MERROR,
1457 		       "wlan_find_cfp_by_band_and_freq(): cannot find cfp by "
1458 		       "band %d & freq %d\n", band, freq);
1459 
1460 	LEAVE();
1461 	return cfp;
1462 }
1463 #endif /* STA_SUPPORT */
1464 
1465 /**
1466  *  @brief Check if Rate Auto
1467  *
1468  *  @param pmpriv               A pointer to mlan_private structure
1469  *
1470  *  @return                     MTRUE or MFALSE
1471  */
1472 t_u8
wlan_is_rate_auto(mlan_private * pmpriv)1473 wlan_is_rate_auto(mlan_private *pmpriv)
1474 {
1475 	t_u32 i;
1476 	int rate_num = 0;
1477 
1478 	ENTER();
1479 
1480 	for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates); i++)
1481 		if (pmpriv->bitmap_rates[i])
1482 			rate_num++;
1483 
1484 	LEAVE();
1485 	if (rate_num > 1)
1486 		return MTRUE;
1487 	else
1488 		return MFALSE;
1489 }
1490 
1491 /**
1492  *  @brief Covert Rate Bitmap to Rate index
1493  *
1494  *  @param pmadapter    Pointer to mlan_adapter structure
1495  *  @param rate_bitmap  Pointer to rate bitmap
1496  *  @param size         Size of the bitmap array
1497  *
1498  *  @return             Rate index
1499  */
1500 int
wlan_get_rate_index(pmlan_adapter pmadapter,t_u16 * rate_bitmap,int size)1501 wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 *rate_bitmap, int size)
1502 {
1503 	int i;
1504 
1505 	ENTER();
1506 
1507 	for (i = 0; i < size * 8; i++) {
1508 		if (rate_bitmap[i / 16] & (1 << (i % 16))) {
1509 			LEAVE();
1510 			return i;
1511 		}
1512 	}
1513 
1514 	LEAVE();
1515 	return -1;
1516 }
1517 
1518 /**
1519  *  @brief Get supported data rates
1520  *
1521  *  @param pmpriv           A pointer to mlan_private structure
1522  *  @param bss_mode         The specified BSS mode (Infra/IBSS)
1523  *  @param config_bands     The specified band configuration
1524  *  @param rates            The buf to return the supported rates
1525  *
1526  *  @return                 The number of Rates
1527  */
1528 t_u32
wlan_get_supported_rates(mlan_private * pmpriv,t_u32 bss_mode,t_u8 config_bands,WLAN_802_11_RATES rates)1529 wlan_get_supported_rates(mlan_private *pmpriv, t_u32 bss_mode,
1530 			 t_u8 config_bands, WLAN_802_11_RATES rates)
1531 {
1532 	t_u32 k = 0;
1533 
1534 	ENTER();
1535 
1536 	if (bss_mode == MLAN_BSS_MODE_INFRA) {
1537 		/* Infra. mode */
1538 		switch (config_bands) {
1539 		case (t_u8)BAND_B:
1540 			PRINTM(MINFO, "Infra Band=%d SupportedRates_B\n",
1541 			       config_bands);
1542 			k = wlan_copy_rates(rates, k, SupportedRates_B,
1543 					    sizeof(SupportedRates_B));
1544 			break;
1545 		case (t_u8)BAND_G:
1546 		case BAND_G | BAND_GN:
1547 			PRINTM(MINFO, "Infra band=%d SupportedRates_G\n",
1548 			       config_bands);
1549 			k = wlan_copy_rates(rates, k, SupportedRates_G,
1550 					    sizeof(SupportedRates_G));
1551 			break;
1552 		case BAND_B | BAND_G:
1553 		case BAND_A | BAND_B | BAND_G:
1554 		case BAND_A | BAND_B:
1555 		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
1556 		case BAND_B | BAND_G | BAND_GN:
1557 			PRINTM(MINFO, "Infra band=%d SupportedRates_BG\n",
1558 			       config_bands);
1559 #ifdef WIFI_DIRECT_SUPPORT
1560 			if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
1561 				k = wlan_copy_rates(rates, k, SupportedRates_G,
1562 						    sizeof(SupportedRates_G));
1563 			else
1564 				k = wlan_copy_rates(rates, k, SupportedRates_BG,
1565 						    sizeof(SupportedRates_BG));
1566 #else
1567 			k = wlan_copy_rates(rates, k, SupportedRates_BG,
1568 					    sizeof(SupportedRates_BG));
1569 #endif
1570 			break;
1571 		case BAND_A:
1572 		case BAND_A | BAND_G:
1573 			PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
1574 			       config_bands);
1575 			k = wlan_copy_rates(rates, k, SupportedRates_A,
1576 					    sizeof(SupportedRates_A));
1577 			break;
1578 		case BAND_AN:
1579 		case BAND_A | BAND_AN:
1580 		case BAND_A | BAND_G | BAND_AN | BAND_GN:
1581 			PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
1582 			       config_bands);
1583 			k = wlan_copy_rates(rates, k, SupportedRates_A,
1584 					    sizeof(SupportedRates_A));
1585 			break;
1586 		case BAND_GN:
1587 			PRINTM(MINFO, "Infra band=%d SupportedRates_N\n",
1588 			       config_bands);
1589 			k = wlan_copy_rates(rates, k, SupportedRates_N,
1590 					    sizeof(SupportedRates_N));
1591 			break;
1592 		}
1593 	} else {
1594 		/* Ad-hoc mode */
1595 		switch (config_bands) {
1596 		case (t_u8)BAND_B:
1597 			PRINTM(MINFO, "Band: Adhoc B\n");
1598 			k = wlan_copy_rates(rates, k, AdhocRates_B,
1599 					    sizeof(AdhocRates_B));
1600 			break;
1601 		case (t_u8)BAND_G:
1602 		case BAND_G | BAND_GN:
1603 			PRINTM(MINFO, "Band: Adhoc G only\n");
1604 			k = wlan_copy_rates(rates, k, AdhocRates_G,
1605 					    sizeof(AdhocRates_G));
1606 			break;
1607 		case BAND_B | BAND_G:
1608 		case BAND_B | BAND_G | BAND_GN:
1609 			PRINTM(MINFO, "Band: Adhoc BG\n");
1610 			k = wlan_copy_rates(rates, k, AdhocRates_BG,
1611 					    sizeof(AdhocRates_BG));
1612 			break;
1613 		case BAND_A:
1614 		case BAND_AN:
1615 		case BAND_A | BAND_AN:
1616 			PRINTM(MINFO, "Band: Adhoc A\n");
1617 			k = wlan_copy_rates(rates, k, AdhocRates_A,
1618 					    sizeof(AdhocRates_A));
1619 			break;
1620 		}
1621 	}
1622 
1623 	LEAVE();
1624 	return k;
1625 }
1626 
1627 #define COUNTRY_ID_US 0
1628 #define COUNTRY_ID_JP 1
1629 #define COUNTRY_ID_CN 2
1630 #define COUNTRY_ID_EU 3
1631 typedef struct _oper_bw_chan {
1632 	/*non-global operating class */
1633 	t_u8 oper_class;
1634 	/*global operating class */
1635 	t_u8 global_oper_class;
1636 	/*bandwidth 0-20M 1-40M 2-80M 3-160M */
1637 	t_u8 bandwidth;
1638 	/*channel list */
1639 	t_u8 channel_list[13];
1640 } oper_bw_chan;
1641 
1642 /** oper class table for US*/
1643 static oper_bw_chan oper_bw_chan_us[] = {
1644     /** non-Global oper class, global oper class, bandwidth, channel list*/
1645 	{1, 115, 0, {36, 40, 44, 48}},
1646 	{2, 118, 0, {52, 56, 60, 64}},
1647 	{3, 124, 0, {149, 153, 157, 161}},
1648 	{4, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
1649 	{5, 125, 0, {149, 153, 157, 161, 165}},
1650 	{12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
1651 	{22, 116, 1, {36, 44}},
1652 	{23, 119, 1, {52, 60}},
1653 	{24, 122, 1, {100, 108, 116, 124, 132}},
1654 	{25, 126, 1, {149, 157}},
1655 	{26, 126, 1, {149, 157}},
1656 	{27, 117, 1, {40, 48}},
1657 	{28, 120, 1, {56, 64}},
1658 	{29, 123, 1, {104, 112, 120, 128, 136}},
1659 	{30, 127, 1, {153, 161}},
1660 	{31, 127, 1, {153, 161}},
1661 	{32, 83, 1, {1, 2, 3, 4, 5, 6, 7}},
1662 	{33, 84, 1, {5, 6, 7, 8, 9, 10, 11}},
1663 };
1664 
1665 /** oper class table for EU*/
1666 static oper_bw_chan oper_bw_chan_eu[] = {
1667     /** non-global oper class,global oper class, bandwidth, channel list*/
1668 	{1, 115, 0, {36, 40, 44, 48}},
1669 	{2, 118, 0, {52, 56, 60, 64}},
1670 	{3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
1671 	{4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
1672 	{5, 116, 1, {36, 44}},
1673 	{6, 119, 1, {52, 60}},
1674 	{7, 122, 1, {100, 108, 116, 124, 132}},
1675 	{8, 117, 1, {40, 48}},
1676 	{9, 120, 1, {56, 64}},
1677 	{10, 123, 1, {104, 112, 120, 128, 136}},
1678 	{11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
1679 	{12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
1680 	{17, 125, 0, {149, 153, 157, 161, 165, 169}},
1681 };
1682 
1683 /** oper class table for Japan*/
1684 static oper_bw_chan oper_bw_chan_jp[] = {
1685     /** non-Global oper class,global oper class, bandwidth, channel list*/
1686 	{1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48}},
1687 	{30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
1688 	{31, 82, 0, {14}},
1689 	{32, 118, 0, {52, 56, 60, 64}},
1690 	{33, 118, 0, {52, 56, 60, 64}},
1691 	{34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
1692 	{35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
1693 	{36, 116, 1, {36, 44}},
1694 	{37, 119, 1, {52, 60}},
1695 	{38, 119, 1, {52, 60}},
1696 	{39, 122, 1, {100, 108, 116, 124, 132}},
1697 	{40, 122, 1, {100, 108, 116, 124, 132}},
1698 	{41, 117, 1, {40, 48}},
1699 	{42, 120, 1, {56, 64}},
1700 	{43, 120, 1, {56, 64}},
1701 	{44, 123, 1, {104, 112, 120, 128, 136}},
1702 	{45, 123, 1, {104, 112, 120, 128, 136}},
1703 	{56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
1704 	{57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
1705 	{58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
1706 };
1707 
1708 /** oper class table for China*/
1709 static oper_bw_chan oper_bw_chan_cn[] = {
1710     /** non-Global oper class,global oper class, bandwidth, channel list*/
1711 	{1, 115, 0, {36, 40, 44, 48}},
1712 	{2, 118, 0, {52, 56, 60, 64}},
1713 	{3, 125, 0, {149, 153, 157, 161, 165}},
1714 	{4, 116, 1, {36, 44}},
1715 	{5, 119, 1, {52, 60}},
1716 	{6, 126, 1, {149, 157}},
1717 	{7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
1718 	{8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
1719 	{9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
1720 };
1721 
1722 /**
1723  *  @brief Get non-global operaing class table according to country
1724  *
1725  *  @param pmpriv             A pointer to mlan_private structure
1726  *  @param arraysize          A pointer to table size
1727  *
1728  *  @return                   A pointer to oper_bw_chan
1729  */
1730 oper_bw_chan *
wlan_get_nonglobal_operclass_table(mlan_private * pmpriv,int * arraysize)1731 wlan_get_nonglobal_operclass_table(mlan_private *pmpriv, int *arraysize)
1732 {
1733 	t_u8 country_code[][COUNTRY_CODE_LEN] = { "US", "JP", "CN" };
1734 	int country_id = 0;
1735 	oper_bw_chan *poper_bw_chan = MNULL;
1736 
1737 	ENTER();
1738 
1739 	for (country_id = 0; country_id < 3; country_id++)
1740 		if (!memcmp
1741 		    (pmpriv->adapter, pmpriv->adapter->country_code,
1742 		     country_code[country_id], COUNTRY_CODE_LEN - 1))
1743 			break;
1744 	if (country_id >= 3)
1745 		country_id = COUNTRY_ID_US;	/*Set default to US */
1746 	if (wlan_is_etsi_country
1747 	    (pmpriv->adapter, pmpriv->adapter->country_code))
1748 		country_id = COUNTRY_ID_EU;
1749 				    /** Country in EU */
1750 
1751 	switch (country_id) {
1752 	case COUNTRY_ID_US:
1753 		poper_bw_chan = oper_bw_chan_us;
1754 		*arraysize = sizeof(oper_bw_chan_us);
1755 		break;
1756 	case COUNTRY_ID_JP:
1757 		poper_bw_chan = oper_bw_chan_jp;
1758 		*arraysize = sizeof(oper_bw_chan_jp);
1759 		break;
1760 	case COUNTRY_ID_CN:
1761 		poper_bw_chan = oper_bw_chan_cn;
1762 		*arraysize = sizeof(oper_bw_chan_cn);
1763 		break;
1764 	case COUNTRY_ID_EU:
1765 		poper_bw_chan = oper_bw_chan_eu;
1766 		*arraysize = sizeof(oper_bw_chan_eu);
1767 		break;
1768 	default:
1769 		PRINTM(MERROR, "Country not support!\n");
1770 		break;
1771 	}
1772 
1773 	LEAVE();
1774 	return poper_bw_chan;
1775 }
1776 
1777 /**
1778  *  @brief Check validation of given channel and oper class
1779  *
1780  *  @param pmpriv             A pointer to mlan_private structure
1781  *  @param channel            Channel number
1782  *  @param oper_class         operating class
1783  *
1784  *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
1785  */
1786 mlan_status
wlan_check_operclass_validation(mlan_private * pmpriv,t_u8 channel,t_u8 oper_class)1787 wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
1788 				t_u8 oper_class)
1789 {
1790 	int arraysize = 0, i = 0, channum = 0;
1791 	oper_bw_chan *poper_bw_chan = MNULL;
1792 	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
1793 
1794 	ENTER();
1795 
1796 	for (i = 0; i < sizeof(center_freqs); i++) {
1797 		if (channel == center_freqs[i]) {
1798 			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
1799 			LEAVE();
1800 			return MLAN_STATUS_FAILURE;
1801 		}
1802 	}
1803 	if (oper_class <= 0 || oper_class > 130) {
1804 		PRINTM(MERROR, "Invalid operating class!\n");
1805 		LEAVE();
1806 		return MLAN_STATUS_FAILURE;
1807 	}
1808 	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
1809 
1810 	if (!poper_bw_chan) {
1811 		PRINTM(MCMND, "Operating class table do not find!\n");
1812 		LEAVE();
1813 		return MLAN_STATUS_FAILURE;
1814 	}
1815 
1816 	for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
1817 		if (poper_bw_chan[i].oper_class == oper_class ||
1818 		    poper_bw_chan[i].global_oper_class == oper_class) {
1819 			for (channum = 0;
1820 			     channum < sizeof(poper_bw_chan[i].channel_list);
1821 			     channum++) {
1822 				if (poper_bw_chan[i].channel_list[channum] &&
1823 				    poper_bw_chan[i].channel_list[channum] ==
1824 				    channel) {
1825 					LEAVE();
1826 					return MLAN_STATUS_SUCCESS;
1827 				}
1828 			}
1829 		}
1830 	}
1831 
1832 	PRINTM(MCMND, "Operating class %d do not match channel %d!\n",
1833 	       oper_class, channel);
1834 	LEAVE();
1835 	return MLAN_STATUS_FAILURE;
1836 }
1837 
1838 /**
1839  *  @brief Get current operating class from channel and bandwidth
1840  *
1841  *  @param pmpriv             A pointer to mlan_private structure
1842  *  @param channel            Channel number
1843  *  @param bw                 Bandwidth
1844  *  @param oper_class         A pointer to current operating class
1845  *
1846  *  @return                   MLAN_STATUS_PENDING --success, otherwise fail
1847  */
1848 mlan_status
wlan_get_curr_oper_class(mlan_private * pmpriv,t_u8 channel,t_u8 bw,t_u8 * oper_class)1849 wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel, t_u8 bw,
1850 			 t_u8 *oper_class)
1851 {
1852 	oper_bw_chan *poper_bw_chan = MNULL;
1853 	t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
1854 	int i = 0, arraysize = 0, channum = 0;
1855 
1856 	ENTER();
1857 
1858 	poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
1859 
1860 	if (!poper_bw_chan) {
1861 		PRINTM(MCMND, "Operating class table do not find!\n");
1862 		LEAVE();
1863 		return MLAN_STATUS_FAILURE;
1864 	}
1865 	for (i = 0; i < sizeof(center_freqs); i++) {
1866 		if (channel == center_freqs[i]) {
1867 			PRINTM(MERROR, "Invalid channel number %d!\n", channel);
1868 			LEAVE();
1869 			return MLAN_STATUS_FAILURE;
1870 		}
1871 	}
1872 
1873 	for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
1874 		if (poper_bw_chan[i].bandwidth == bw) {
1875 			for (channum = 0;
1876 			     channum < sizeof(poper_bw_chan[i].channel_list);
1877 			     channum++) {
1878 				if (poper_bw_chan[i].channel_list[channum] &&
1879 				    poper_bw_chan[i].channel_list[channum] ==
1880 				    channel) {
1881 					*oper_class =
1882 						poper_bw_chan[i].oper_class;
1883 					return MLAN_STATUS_SUCCESS;
1884 				}
1885 			}
1886 		}
1887 	}
1888 
1889 	PRINTM(MCMND, "Operating class not find!\n");
1890 	LEAVE();
1891 	return MLAN_STATUS_FAILURE;
1892 }
1893 
1894 /**
1895  *  @brief Add Supported operating classes IE
1896  *
1897  *  @param pmpriv             A pointer to mlan_private structure
1898  *  @param pptlv_out          A pointer to TLV to fill in
1899  *  @param curr_oper_class    Current operating class
1900  *
1901  *  @return                   Length
1902  */
1903 int
wlan_add_supported_oper_class_ie(IN mlan_private * pmpriv,OUT t_u8 ** pptlv_out,t_u8 curr_oper_class)1904 wlan_add_supported_oper_class_ie(IN mlan_private *pmpriv, OUT t_u8 **pptlv_out,
1905 				 t_u8 curr_oper_class)
1906 {
1907 
1908 	t_u8 oper_class_us[] =
1909 		{ 1, 2, 3, 4, 5, 12, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
1910 	 33
1911 	};
1912 	t_u8 oper_class_eu[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 17
1913 	};
1914 	t_u8 oper_class_jp[] =
1915 		{ 1, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
1916 	 45, 56, 57, 58
1917 	};
1918 	t_u8 oper_class_cn[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9
1919 	};
1920 	t_u8 country_code[][COUNTRY_CODE_LEN] = { "US", "JP", "CN" };
1921 	int country_id = 0, ret = 0;
1922 	MrvlIETypes_SuppOperClass_t *poper_class = MNULL;
1923 
1924 	ENTER();
1925 
1926 	for (country_id = 0; country_id < 3; country_id++)
1927 		if (!memcmp
1928 		    (pmpriv->adapter, pmpriv->adapter->country_code,
1929 		     country_code[country_id], COUNTRY_CODE_LEN - 1))
1930 			break;
1931 	if (country_id >= 3)
1932 		country_id = COUNTRY_ID_US;	/*Set default to US */
1933 	if (wlan_is_etsi_country
1934 	    (pmpriv->adapter, pmpriv->adapter->country_code))
1935 		country_id = COUNTRY_ID_EU;
1936 				    /** Country in EU */
1937 	poper_class = (MrvlIETypes_SuppOperClass_t *) * pptlv_out;
1938 	memset(pmpriv->adapter, poper_class, 0,
1939 	       sizeof(MrvlIETypes_SuppOperClass_t));
1940 	poper_class->header.type = wlan_cpu_to_le16(REGULATORY_CLASS);
1941 	if (country_id == COUNTRY_ID_US) {
1942 		poper_class->header.len = sizeof(oper_class_us);
1943 		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_us,
1944 		       sizeof(oper_class_us));
1945 	} else if (country_id == COUNTRY_ID_JP) {
1946 		poper_class->header.len = sizeof(oper_class_jp);
1947 		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_jp,
1948 		       sizeof(oper_class_jp));
1949 	} else if (country_id == COUNTRY_ID_CN) {
1950 		poper_class->header.len = sizeof(oper_class_cn);
1951 		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_cn,
1952 		       sizeof(oper_class_cn));
1953 	} else if (country_id == COUNTRY_ID_EU) {
1954 		poper_class->header.len = sizeof(oper_class_eu);
1955 		memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_eu,
1956 		       sizeof(oper_class_eu));
1957 	}
1958 	poper_class->current_oper_class = curr_oper_class;
1959 	poper_class->header.len += sizeof(poper_class->current_oper_class);
1960 	DBG_HEXDUMP(MCMD_D, "Operating class", (t_u8 *)poper_class,
1961 		    sizeof(MrvlIEtypesHeader_t) + poper_class->header.len);
1962 	ret = sizeof(MrvlIEtypesHeader_t) + poper_class->header.len;
1963 	*pptlv_out += ret;
1964 	poper_class->header.len = wlan_cpu_to_le16(poper_class->header.len);
1965 
1966 	LEAVE();
1967 	return ret;
1968 }
1969 
1970 /**
1971  *  @brief This function sets region table.
1972  *
1973  *  @param pmpriv  A pointer to mlan_private structure
1974  *  @param region  The region code
1975  *  @param band    The band
1976  *
1977  *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1978  */
1979 mlan_status
wlan_set_regiontable(mlan_private * pmpriv,t_u8 region,t_u8 band)1980 wlan_set_regiontable(mlan_private *pmpriv, t_u8 region, t_u8 band)
1981 {
1982 	mlan_adapter *pmadapter = pmpriv->adapter;
1983 	int i = 0, j;
1984 	chan_freq_power_t *cfp;
1985 	int cfp_no;
1986 	region_chan_t region_chan_old[MAX_REGION_CHANNEL_NUM];
1987 
1988 	ENTER();
1989 
1990 	memcpy(pmadapter, region_chan_old, pmadapter->region_channel,
1991 	       sizeof(pmadapter->region_channel));
1992 	memset(pmadapter, pmadapter->region_channel, 0,
1993 	       sizeof(pmadapter->region_channel));
1994 
1995 	if (band & (BAND_B | BAND_G | BAND_GN)) {
1996 		cfp = wlan_get_region_cfp_table(pmadapter, region,
1997 						BAND_G | BAND_B | BAND_GN,
1998 						&cfp_no);
1999 		if (cfp) {
2000 			pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
2001 			pmadapter->region_channel[i].pcfp = cfp;
2002 		} else {
2003 			PRINTM(MERROR, "wrong region code %#x in Band B-G\n",
2004 			       region);
2005 			LEAVE();
2006 			return MLAN_STATUS_FAILURE;
2007 		}
2008 		pmadapter->region_channel[i].valid = MTRUE;
2009 		pmadapter->region_channel[i].region = region;
2010 		if (band & BAND_GN)
2011 			pmadapter->region_channel[i].band = BAND_G;
2012 		else
2013 			pmadapter->region_channel[i].band =
2014 				(band & BAND_G) ? BAND_G : BAND_B;
2015 
2016 		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
2017 			if (region_chan_old[j].band & (BAND_B | BAND_G))
2018 				break;
2019 		}
2020 		if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid)
2021 			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
2022 					      region_chan_old[j].pcfp,
2023 					      region_chan_old[j].num_cfp);
2024 		else
2025 			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
2026 		i++;
2027 	}
2028 	if (band & (BAND_A | BAND_AN)) {
2029 		cfp = wlan_get_region_cfp_table(pmadapter, region, BAND_A,
2030 						&cfp_no);
2031 		if (cfp) {
2032 			pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
2033 			pmadapter->region_channel[i].pcfp = cfp;
2034 		} else {
2035 			PRINTM(MERROR, "wrong region code %#x in Band A\n",
2036 			       region);
2037 			LEAVE();
2038 			return MLAN_STATUS_FAILURE;
2039 		}
2040 		pmadapter->region_channel[i].valid = MTRUE;
2041 		pmadapter->region_channel[i].region = region;
2042 		pmadapter->region_channel[i].band = BAND_A;
2043 
2044 		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
2045 			if (region_chan_old[j].band & BAND_A)
2046 				break;
2047 		}
2048 		if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid)
2049 			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
2050 					      region_chan_old[j].pcfp,
2051 					      region_chan_old[j].num_cfp);
2052 		else
2053 			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
2054 	}
2055 	LEAVE();
2056 	return MLAN_STATUS_SUCCESS;
2057 }
2058 
2059 /**
2060  *  @brief Get if radar detection is enabled or not on a certain channel
2061  *
2062  *  @param priv    Private driver information structure
2063  *  @param chnl Channel to determine radar detection requirements
2064  *
2065  *  @return
2066  *    - MTRUE if radar detection is required
2067  *    - MFALSE otherwise
2068  */
2069 t_bool
wlan_get_cfp_radar_detect(mlan_private * priv,t_u8 chnl)2070 wlan_get_cfp_radar_detect(mlan_private *priv, t_u8 chnl)
2071 {
2072 	int i, j;
2073 	t_bool required = MFALSE;
2074 	chan_freq_power_t *pcfp = MNULL;
2075 
2076 	ENTER();
2077 
2078 	/*get the cfp table first */
2079 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2080 		if (priv->adapter->region_channel[i].band == BAND_A) {
2081 			pcfp = priv->adapter->region_channel[i].pcfp;
2082 			break;
2083 		}
2084 	}
2085 
2086 	if (!pcfp) {
2087 		/*This means operation in BAND-A is not support, we can
2088 		   just return false here, it's harmless */
2089 		goto done;
2090 	}
2091 
2092 	/*get the radar detection requirements according to chan num */
2093 	for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2094 		if (pcfp[j].channel == chnl) {
2095 			required = pcfp[j].passive_scan_or_radar_detect;
2096 			break;
2097 		}
2098 	}
2099 
2100 done:
2101 	LEAVE();
2102 	return required;
2103 }
2104 
2105 /**
2106  *  @brief Get if scan type is passive or not on a certain channel for b/g band
2107  *
2108  *  @param priv    Private driver information structure
2109  *  @param chnl Channel to determine scan type
2110  *
2111  *  @return
2112  *    - MTRUE if scan type is passive
2113  *    - MFALSE otherwise
2114  */
2115 
2116 t_bool
wlan_bg_scan_type_is_passive(mlan_private * priv,t_u8 chnl)2117 wlan_bg_scan_type_is_passive(mlan_private *priv, t_u8 chnl)
2118 {
2119 	int i, j;
2120 	t_bool passive = MFALSE;
2121 	chan_freq_power_t *pcfp = MNULL;
2122 
2123 	ENTER();
2124 
2125 	/*get the cfp table first */
2126 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2127 		if (priv->adapter->region_channel[i].band & (BAND_B | BAND_G)) {
2128 			pcfp = priv->adapter->region_channel[i].pcfp;
2129 			break;
2130 		}
2131 	}
2132 
2133 	if (!pcfp) {
2134 		/*This means operation in BAND-B or BAND_G is not support, we can
2135 		 * just return false here*/
2136 		goto done;
2137 	}
2138 
2139 	/*get the bg scan type according to chan num */
2140 	for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2141 		if (pcfp[j].channel == chnl) {
2142 			passive = pcfp[j].passive_scan_or_radar_detect;
2143 			break;
2144 		}
2145 	}
2146 
2147 done:
2148 	LEAVE();
2149 	return passive;
2150 }
2151 
2152 /**
2153  *  @brief Get if a channel is disabled or not
2154  *
2155  *  @param priv     Private driver information structure
2156  *  @param band     Band to check
2157  *  @param chan     Channel to check
2158  *
2159  *  @return
2160  *    - MTRUE if channel is disabled
2161  *    - MFALSE otherwise
2162  */
2163 
2164 t_bool
wlan_is_chan_disabled(mlan_private * priv,t_u8 band,t_u8 chan)2165 wlan_is_chan_disabled(mlan_private *priv, t_u8 band, t_u8 chan)
2166 {
2167 	int i, j;
2168 	t_bool disabled = MFALSE;
2169 	chan_freq_power_t *pcfp = MNULL;
2170 
2171 	ENTER();
2172 
2173 	/* get the cfp table first */
2174 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2175 		if (priv->adapter->region_channel[i].band & band) {
2176 			pcfp = priv->adapter->region_channel[i].pcfp;
2177 			break;
2178 		}
2179 	}
2180 
2181 	if (pcfp) {
2182 		/* check table according to chan num */
2183 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2184 			if (pcfp[j].channel == chan) {
2185 				if (pcfp[j].dynamic.
2186 				    flags & MARVELL_CHANNEL_DISABLED)
2187 					disabled = MTRUE;
2188 				break;
2189 			}
2190 		}
2191 	}
2192 
2193 	LEAVE();
2194 	return disabled;
2195 }
2196 
2197 /**
2198  *  @brief Get if a channel is blacklisted or not
2199  *
2200  *  @param priv     Private driver information structure
2201  *  @param band     Band to check
2202  *  @param chan     Channel to check
2203  *
2204  *  @return
2205  *    - MTRUE if channel is blacklisted
2206  *    - MFALSE otherwise
2207  */
2208 
2209 t_bool
wlan_is_chan_blacklisted(mlan_private * priv,t_u8 band,t_u8 chan)2210 wlan_is_chan_blacklisted(mlan_private *priv, t_u8 band, t_u8 chan)
2211 {
2212 	int i, j;
2213 	t_bool blacklist = MFALSE;
2214 	chan_freq_power_t *pcfp = MNULL;
2215 
2216 	ENTER();
2217 
2218 	/*get the cfp table first */
2219 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2220 		if (priv->adapter->region_channel[i].band & band) {
2221 			pcfp = priv->adapter->region_channel[i].pcfp;
2222 			break;
2223 		}
2224 	}
2225 
2226 	if (pcfp) {
2227 		/*check table according to chan num */
2228 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2229 			if (pcfp[j].channel == chan) {
2230 				blacklist = pcfp[j].dynamic.blacklist;
2231 				break;
2232 			}
2233 		}
2234 	}
2235 
2236 	LEAVE();
2237 	return blacklist;
2238 }
2239 
2240 /**
2241  *  @brief Set a channel as blacklisted or not
2242  *
2243  *  @param priv     Private driver information structure
2244  *  @param band     Band to check
2245  *  @param chan     Channel to check
2246  *  @param bl       Blacklist if MTRUE
2247  *
2248  *  @return
2249  *    - MTRUE if channel setting is updated
2250  *    - MFALSE otherwise
2251  */
2252 
2253 t_bool
wlan_set_chan_blacklist(mlan_private * priv,t_u8 band,t_u8 chan,t_bool bl)2254 wlan_set_chan_blacklist(mlan_private *priv, t_u8 band, t_u8 chan, t_bool bl)
2255 {
2256 	int i, j;
2257 	t_bool set_bl = MFALSE;
2258 	chan_freq_power_t *pcfp = MNULL;
2259 
2260 	ENTER();
2261 
2262 	/*get the cfp table first */
2263 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2264 		if (priv->adapter->region_channel[i].band & band) {
2265 			pcfp = priv->adapter->region_channel[i].pcfp;
2266 			break;
2267 		}
2268 	}
2269 
2270 	if (pcfp) {
2271 		/*check table according to chan num */
2272 		for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2273 			if (pcfp[j].channel == chan) {
2274 				pcfp[j].dynamic.blacklist = bl;
2275 				set_bl = MTRUE;
2276 				break;
2277 			}
2278 		}
2279 	}
2280 
2281 	LEAVE();
2282 	return set_bl;
2283 }
2284 
2285 /**
2286  *  @brief Convert rateid in IEEE format to MRVL format
2287  *
2288  *  @param priv     Private driver information structure
2289  *  @param IeeeMacRate  Rate in terms of IEEE format
2290  *  @param pmbuf     A pointer to packet buffer
2291  *
2292  *  @return
2293  *    Rate ID in terms of MRVL format
2294  */
2295 t_u8
wlan_ieee_rateid_to_mrvl_rateid(mlan_private * priv,t_u16 IeeeMacRate,t_u8 * dst_mac)2296 wlan_ieee_rateid_to_mrvl_rateid(mlan_private *priv, t_u16 IeeeMacRate,
2297 				t_u8 *dst_mac)
2298 {
2299 	/* Set default rate ID to RATEID_DBPSK1Mbps */
2300 	t_u8 mrvlRATEID = 0;
2301 	const rate_map *rate_tbl = rate_map_table_1x1;
2302 	t_u32 cnt = sizeof(rate_map_table_1x1) / sizeof(rate_map);
2303 	t_u8 skip_nss2 = MTRUE;
2304 	t_u32 i = 0;
2305 
2306 	ENTER();
2307 
2308 	for (i = 0; i < cnt; i++) {
2309 		if (rate_tbl[i].nss && skip_nss2)
2310 			continue;
2311 		if (rate_tbl[i].rate == IeeeMacRate) {
2312 			mrvlRATEID = rate_tbl[i].id;
2313 			break;
2314 		}
2315 	}
2316 
2317 	return mrvlRATEID;
2318 }
2319 
2320 /**
2321  *  @brief Convert rateid in MRVL format to IEEE format
2322  *
2323  *  @param IeeeMacRate  Rate in terms of MRVL format
2324  *
2325  *  @return
2326  *    Rate ID in terms of IEEE format
2327  */
2328 t_u8
wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)2329 wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)
2330 {
2331 	return rateUnit_500Kbps[rate];
2332 }
2333 
2334 /**
2335  *  @brief	Update CFP tables and power tables from FW
2336  *
2337  *  @param priv		Private driver information structure
2338  *  @param buf		Pointer to the buffer holding TLV data
2339  *					from 0x242 command response.
2340  *  @param buf_left	bufsize
2341  *
2342  *  @return
2343  *    None
2344  */
2345 void
wlan_add_fw_cfp_tables(pmlan_private pmpriv,t_u8 * buf,t_u16 buf_left)2346 wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
2347 {
2348 	mlan_adapter *pmadapter = pmpriv->adapter;
2349 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2350 	MrvlIEtypesHeader_t *head;
2351 	t_u16 tlv;
2352 	t_u16 tlv_buf_len;
2353 	t_u16 tlv_buf_left;
2354 	t_u16 i;
2355 	t_u16 max_tx_pwr_bg = WLAN_TX_PWR_DEFAULT;
2356 	t_u16 max_tx_pwr_a = WLAN_TX_PWR_DEFAULT;
2357 	t_u8 *tlv_buf;
2358 	t_u8 *data;
2359 	t_u8 *tmp;
2360 	mlan_status ret;
2361 
2362 	ENTER();
2363 
2364 	if (!buf) {
2365 		PRINTM(MERROR, "CFP table update failed!\n");
2366 		goto out;
2367 	}
2368 	tlv_buf = (t_u8 *)buf;
2369 	tlv_buf_left = buf_left;
2370 
2371 	while (tlv_buf_left >= sizeof(*head)) {
2372 		head = (MrvlIEtypesHeader_t *)tlv_buf;
2373 		tlv = wlan_le16_to_cpu(head->type);
2374 		tlv_buf_len = wlan_le16_to_cpu(head->len);
2375 
2376 		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
2377 			break;
2378 		data = (t_u8 *)head + sizeof(*head);
2379 
2380 		switch (tlv) {
2381 		case TLV_TYPE_REGION_INFO:
2382 			/* Skip adding fw region info if it already exists or
2383 			 * if this TLV has no set data
2384 			 */
2385 			if (*data == 0)
2386 				break;
2387 			if (pmadapter->otp_region)
2388 				break;
2389 
2390 			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2391 					       sizeof(otp_region_info_t),
2392 					       MLAN_MEM_DEF,
2393 					       (t_u8 **)&pmadapter->otp_region);
2394 			if (ret != MLAN_STATUS_SUCCESS ||
2395 			    !pmadapter->otp_region) {
2396 				PRINTM(MERROR,
2397 				       "Memory allocation for the otp region"
2398 				       " info struct failed!\n");
2399 				break;
2400 			}
2401 			/* Save region info values from OTP in the otp_region
2402 			 * structure
2403 			 */
2404 			memcpy(pmadapter, pmadapter->otp_region, data,
2405 			       sizeof(otp_region_info_t));
2406 			data += sizeof(otp_region_info_t);
2407 			/* Get pre-defined cfp tables corresponding to the region code
2408 			 * in OTP
2409 			 */
2410 			for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
2411 				if (cfp_table_BG[i].code ==
2412 				    pmadapter->otp_region->region_code) {
2413 					max_tx_pwr_bg =
2414 						(cfp_table_BG[i].cfp)->
2415 						max_tx_power;
2416 					break;
2417 				}
2418 			}
2419 			for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
2420 				if (cfp_table_A[i].code ==
2421 				    pmadapter->otp_region->region_code) {
2422 					max_tx_pwr_a =
2423 						(cfp_table_A[i].cfp)->
2424 						max_tx_power;
2425 					break;
2426 				}
2427 			}
2428 			/* Update the region code and the country code in pmadapter */
2429 			pmadapter->region_code =
2430 				pmadapter->otp_region->region_code;
2431 			pmadapter->country_code[0] =
2432 				pmadapter->otp_region->country_code[0];
2433 			pmadapter->country_code[1] =
2434 				pmadapter->otp_region->country_code[1];
2435 			pmadapter->country_code[2] = '\0';
2436 			pmadapter->domain_reg.country_code[0] =
2437 				pmadapter->otp_region->country_code[0];
2438 			pmadapter->domain_reg.country_code[1] =
2439 				pmadapter->otp_region->country_code[1];
2440 			pmadapter->domain_reg.country_code[2] = '\0';
2441 			pmadapter->cfp_code_bg =
2442 				pmadapter->otp_region->region_code;
2443 			pmadapter->cfp_code_a =
2444 				pmadapter->otp_region->region_code;
2445 			break;
2446 		case TLV_TYPE_CHAN_ATTR_CFG:
2447 			/* Skip adding fw cfp tables if they already exist or
2448 			 * if this TLV has no set data
2449 			 */
2450 			if (*data == 0)
2451 				break;
2452 			if (pmadapter->cfp_otp_bg || pmadapter->cfp_otp_a) {
2453 				break;
2454 			}
2455 
2456 			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2457 					       FW_CFP_TABLE_MAX_ROWS_BG *
2458 					       sizeof(chan_freq_power_t),
2459 					       MLAN_MEM_DEF,
2460 					       (t_u8 **)&pmadapter->cfp_otp_bg);
2461 			if (ret != MLAN_STATUS_SUCCESS ||
2462 			    !pmadapter->cfp_otp_bg) {
2463 				PRINTM(MERROR,
2464 				       "Memory allocation for storing otp bg"
2465 				       " table data failed!\n");
2466 				break;
2467 			}
2468 			/* Save channel usability flags from OTP data in the fw cfp bg
2469 			 * table and set frequency and max_tx_power values
2470 			 */
2471 			for (i = 0; i < FW_CFP_TABLE_MAX_ROWS_BG; i++) {
2472 				(pmadapter->cfp_otp_bg + i)->channel = *data;
2473 				if (*data == 14)
2474 					(pmadapter->cfp_otp_bg + i)->freq =
2475 						2484;
2476 				else
2477 					(pmadapter->cfp_otp_bg + i)->freq =
2478 						2412 + 5 * (*data - 1);
2479 				(pmadapter->cfp_otp_bg + i)->max_tx_power =
2480 					max_tx_pwr_bg;
2481 				data++;
2482 				(pmadapter->cfp_otp_bg + i)->dynamic.flags =
2483 					*data;
2484 				if (*data & MARVELL_CHANNEL_DFS)
2485 					(pmadapter->cfp_otp_bg +
2486 					 i)->passive_scan_or_radar_detect =
2487 			MTRUE;
2488 				data++;
2489 			}
2490 			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2491 					       FW_CFP_TABLE_MAX_ROWS_A *
2492 					       sizeof(chan_freq_power_t),
2493 					       MLAN_MEM_DEF,
2494 					       (t_u8 **)&pmadapter->cfp_otp_a);
2495 			if (ret != MLAN_STATUS_SUCCESS || !pmadapter->cfp_otp_a) {
2496 				PRINTM(MERROR,
2497 				       "Memory allocation for storing otp a"
2498 				       " table data failed!\n");
2499 				break;
2500 			}
2501 			/* Save channel usability flags from OTP data in the fw cfp a
2502 			 * table and set frequency and max_tx_power values
2503 			 */
2504 			for (i = 0; i < FW_CFP_TABLE_MAX_ROWS_A; i++) {
2505 				(pmadapter->cfp_otp_a + i)->channel = *data;
2506 				if (*data < 183)
2507 					/* 5GHz channels */
2508 					(pmadapter->cfp_otp_a + i)->freq =
2509 						5035 + 5 * (*data - 7);
2510 				else
2511 					/* 4GHz channels */
2512 					(pmadapter->cfp_otp_a + i)->freq =
2513 						4915 + 5 * (*data - 183);
2514 				(pmadapter->cfp_otp_a + i)->max_tx_power =
2515 					max_tx_pwr_a;
2516 				data++;
2517 				(pmadapter->cfp_otp_a + i)->dynamic.flags =
2518 					*data;
2519 				if (*data & MARVELL_CHANNEL_DFS)
2520 					(pmadapter->cfp_otp_a +
2521 					 i)->passive_scan_or_radar_detect =
2522 			 MTRUE;
2523 				data++;
2524 			}
2525 			break;
2526 		case TLV_TYPE_POWER_TABLE:
2527 			/* Skip adding fw power tables if this TLV has no data or
2528 			 * if they already exists but force reg rule is set in the otp
2529 			 */
2530 			if (*data == 0)
2531 				break;
2532 			if (pmadapter->otp_region &&
2533 			    pmadapter->otp_region->force_reg)
2534 				break;
2535 
2536 			/* Save the tlv data in power tables for band BG and A */
2537 			tmp = data;
2538 			i = 0;
2539 			while ((i < FW_CFP_TABLE_MAX_ROWS_BG *
2540 				FW_CFP_TABLE_MAX_COLS_BG)
2541 			       && (i < tlv_buf_len) && (*tmp != 36)) {
2542 				i++;
2543 				tmp++;
2544 			}
2545 			if (!pmadapter->tx_power_table_bg) {
2546 				ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2547 						       i, MLAN_MEM_DEF,
2548 						       (t_u8 **)&pmadapter->
2549 						       tx_power_table_bg);
2550 				if (ret != MLAN_STATUS_SUCCESS ||
2551 				    !pmadapter->tx_power_table_bg) {
2552 					PRINTM(MERROR,
2553 					       "Memory allocation for the BG-band"
2554 					       " power table falied!\n");
2555 					break;
2556 				}
2557 			}
2558 			memcpy(pmadapter, pmadapter->tx_power_table_bg, data,
2559 			       i);
2560 			pmadapter->tx_power_table_bg_size = i;
2561 			data += i;
2562 			i = 0;
2563 			while ((i <
2564 				FW_CFP_TABLE_MAX_ROWS_A *
2565 				FW_CFP_TABLE_MAX_COLS_A)
2566 			       && (i <
2567 				   (tlv_buf_len -
2568 				    pmadapter->tx_power_table_bg_size))) {
2569 				i++;
2570 			}
2571 			if (!pmadapter->tx_power_table_a) {
2572 				ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2573 						       i, MLAN_MEM_DEF,
2574 						       (t_u8 **)&pmadapter->
2575 						       tx_power_table_a);
2576 				if (ret != MLAN_STATUS_SUCCESS ||
2577 				    !pmadapter->tx_power_table_a) {
2578 					PRINTM(MERROR,
2579 					       "Memory allocation for the A-band"
2580 					       " power table failed!\n");
2581 					break;
2582 				}
2583 			}
2584 			memcpy(pmadapter, pmadapter->tx_power_table_a, data, i);
2585 			pmadapter->tx_power_table_a_size = i;
2586 			break;
2587 		default:
2588 			break;
2589 		}
2590 		tlv_buf += (sizeof(*head) + tlv_buf_len);
2591 		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
2592 	}
2593 out:
2594 	LEAVE();
2595 }
2596 
2597 /**
2598  *  @brief	This function deallocates otp cfp and power tables memory.
2599  *
2600  *  @param pmadapter	A pointer to mlan_adapter structure
2601  */
2602 void
wlan_free_fw_cfp_tables(mlan_adapter * pmadapter)2603 wlan_free_fw_cfp_tables(mlan_adapter *pmadapter)
2604 {
2605 	pmlan_callbacks pcb;
2606 
2607 	ENTER();
2608 
2609 	pcb = &pmadapter->callbacks;
2610 	if (pmadapter->otp_region)
2611 		pcb->moal_mfree(pmadapter->pmoal_handle,
2612 				(t_u8 *)pmadapter->otp_region);
2613 	if (pmadapter->cfp_otp_bg)
2614 		pcb->moal_mfree(pmadapter->pmoal_handle,
2615 				(t_u8 *)pmadapter->cfp_otp_bg);
2616 	if (pmadapter->tx_power_table_bg)
2617 		pcb->moal_mfree(pmadapter->pmoal_handle,
2618 				(t_u8 *)pmadapter->tx_power_table_bg);
2619 	pmadapter->tx_power_table_bg_size = 0;
2620 	if (pmadapter->cfp_otp_a)
2621 		pcb->moal_mfree(pmadapter->pmoal_handle,
2622 				(t_u8 *)pmadapter->cfp_otp_a);
2623 	if (pmadapter->tx_power_table_a)
2624 		pcb->moal_mfree(pmadapter->pmoal_handle,
2625 				(t_u8 *)pmadapter->tx_power_table_a);
2626 	pmadapter->tx_power_table_a_size = 0;
2627 	LEAVE();
2628 }
2629 
2630 /**
2631  *  @brief	Get power tables and cfp tables for set region code
2632  *			into the IOCTL request buffer
2633  *
2634  *  @param pmadapter	Private mlan adapter structure
2635  *  @param pioctl_req	Pointer to the IOCTL request structure
2636  *
2637  *  @return	success, otherwise fail
2638  *
2639  */
2640 mlan_status
wlan_get_cfpinfo(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2641 wlan_get_cfpinfo(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
2642 {
2643 	chan_freq_power_t *cfp_bg = MNULL;
2644 	t_u32 cfp_no_bg = 0;
2645 	chan_freq_power_t *cfp_a = MNULL;
2646 	t_u32 cfp_no_a = 0;
2647 	t_u32 len = 0, size = 0;
2648 	t_u8 *req_buf, *tmp;
2649 	mlan_status ret = MLAN_STATUS_SUCCESS;
2650 
2651 	ENTER();
2652 
2653 	if (!pioctl_req || !pioctl_req->pbuf) {
2654 		PRINTM(MERROR, "MLAN IOCTL information is not present!\n");
2655 		ret = MLAN_STATUS_FAILURE;
2656 		goto out;
2657 	}
2658 	/* Calculate the total response size required to return region,
2659 	 * country codes, cfp tables and power tables
2660 	 */
2661 	size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
2662 	/* Add size to store region, country and environment codes */
2663 	size += sizeof(t_u32);
2664 
2665 	/* Get cfp table and its size corresponding to the region code */
2666 	cfp_bg = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
2667 					   BAND_G | BAND_B, &cfp_no_bg);
2668 	size += cfp_no_bg * sizeof(chan_freq_power_t);
2669 	cfp_a = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
2670 					  BAND_A, &cfp_no_a);
2671 	size += cfp_no_a * sizeof(chan_freq_power_t);
2672 	if (pmadapter->otp_region)
2673 		size += sizeof(pmadapter->otp_region->environment);
2674 
2675 	/* Get power table size */
2676 	if (pmadapter->tx_power_table_bg) {
2677 		size += pmadapter->tx_power_table_bg_size;
2678 		/* Add size to store table size, rows and cols */
2679 		size += 3 * sizeof(t_u32);
2680 	}
2681 	if (pmadapter->tx_power_table_a) {
2682 		size += pmadapter->tx_power_table_a_size;
2683 		size += 3 * sizeof(t_u32);
2684 	}
2685 	/* Check information buffer length of MLAN IOCTL */
2686 	if (pioctl_req->buf_len < size) {
2687 		PRINTM(MWARN,
2688 		       "MLAN IOCTL information buffer length is too short.\n");
2689 		pioctl_req->buf_len_needed = size;
2690 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
2691 		ret = MLAN_STATUS_RESOURCE;
2692 		goto out;
2693 	}
2694 	/* Copy the total size of region code, country code and environment
2695 	 * in first four bytes of the IOCTL request buffer and then copy
2696 	 * codes respectively in following bytes
2697 	 */
2698 	req_buf = (t_u8 *)pioctl_req->pbuf;
2699 	size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
2700 	if (pmadapter->otp_region)
2701 		size += sizeof(pmadapter->otp_region->environment);
2702 	tmp = (t_u8 *)&size;
2703 	memcpy(pmadapter, req_buf, tmp, sizeof(size));
2704 	len += sizeof(size);
2705 	memcpy(pmadapter, req_buf + len, &pmadapter->region_code,
2706 	       sizeof(pmadapter->region_code));
2707 	len += sizeof(pmadapter->region_code);
2708 	memcpy(pmadapter, req_buf + len, &pmadapter->country_code,
2709 	       sizeof(pmadapter->country_code));
2710 	len += sizeof(pmadapter->country_code);
2711 	if (pmadapter->otp_region) {
2712 		memcpy(pmadapter, req_buf + len,
2713 		       &pmadapter->otp_region->environment,
2714 		       sizeof(pmadapter->otp_region->environment));
2715 		len += sizeof(pmadapter->otp_region->environment);
2716 	}
2717 	/* copy the cfp table size followed by the entire table */
2718 	if (!cfp_bg)
2719 		goto out;
2720 	size = cfp_no_bg * sizeof(chan_freq_power_t);
2721 	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
2722 	len += sizeof(size);
2723 	memcpy(pmadapter, req_buf + len, cfp_bg, size);
2724 	len += size;
2725 	if (!cfp_a)
2726 		goto out;
2727 	size = cfp_no_a * sizeof(chan_freq_power_t);
2728 	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
2729 	len += sizeof(size);
2730 	memcpy(pmadapter, req_buf + len, cfp_a, size);
2731 	len += size;
2732 	/* Copy the size of the power table, number of rows, number of cols
2733 	 * and the entire power table
2734 	 */
2735 	if (!pmadapter->tx_power_table_bg)
2736 		goto out;
2737 	size = pmadapter->tx_power_table_bg_size;
2738 	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
2739 	len += sizeof(size);
2740 
2741 	/* No. of rows */
2742 	size = FW_CFP_TABLE_MAX_ROWS_BG;
2743 	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
2744 	len += sizeof(size);
2745 
2746 	/* No. of cols */
2747 	size = pmadapter->tx_power_table_bg_size / FW_CFP_TABLE_MAX_ROWS_BG;
2748 	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
2749 	len += sizeof(size);
2750 	memcpy(pmadapter, req_buf + len, pmadapter->tx_power_table_bg,
2751 	       pmadapter->tx_power_table_bg_size);
2752 	len += pmadapter->tx_power_table_bg_size;
2753 	if (!pmadapter->tx_power_table_a)
2754 		goto out;
2755 	size = pmadapter->tx_power_table_a_size;
2756 	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
2757 	len += sizeof(size);
2758 
2759 	/* No. of rows */
2760 	size = FW_CFP_TABLE_MAX_ROWS_A;
2761 	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
2762 	len += sizeof(size);
2763 
2764 	/* No. of cols */
2765 	size = pmadapter->tx_power_table_a_size / FW_CFP_TABLE_MAX_ROWS_A;
2766 	memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
2767 	len += sizeof(size);
2768 	memcpy(pmadapter, req_buf + len, pmadapter->tx_power_table_a,
2769 	       pmadapter->tx_power_table_a_size);
2770 	len += pmadapter->tx_power_table_a_size;
2771 out:
2772 	pioctl_req->data_read_written = len;
2773 
2774 	LEAVE();
2775 	return ret;
2776 }
2777