xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_11h.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file mlan_11h.c
2  *
3  *  @brief This file contains functions for 802.11H.
4  *
5  *
6  *  Copyright 2008-2021 NXP
7  *
8  *  This software file (the File) is distributed by NXP
9  *  under the terms of the GNU General Public License Version 2, June 1991
10  *  (the License).  You may use, redistribute and/or modify the File in
11  *  accordance with the terms and conditions of the License, a copy of which
12  *  is available by writing to the Free Software Foundation, Inc.,
13  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15  *
16  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
19  *  this warranty disclaimer.
20  *
21  */
22 
23 /*************************************************************
24 Change Log:
25     03/26/2009: initial version
26 ************************************************************/
27 
28 #include "mlan.h"
29 #include "mlan_join.h"
30 #include "mlan_util.h"
31 #include "mlan_fw.h"
32 #include "mlan_main.h"
33 #include "mlan_ioctl.h"
34 #include "mlan_11h.h"
35 #include "mlan_11n.h"
36 #ifdef UAP_SUPPORT
37 #include "mlan_uap.h"
38 #endif
39 
40 /********************************************************
41 			Local Variables
42 ********************************************************/
43 
44 /** Default IBSS DFS recovery interval (in TBTTs); used for adhoc start */
45 #define WLAN_11H_DEFAULT_DFS_RECOVERY_INTERVAL 100
46 
47 /** Default 11h power constraint used to offset the maximum transmit power */
48 #define WLAN_11H_TPC_POWERCONSTRAINT 0
49 
50 /** 11h TPC Power capability minimum setting, sent in TPC_INFO command to fw */
51 #define WLAN_11H_TPC_POWERCAPABILITY_MIN 5
52 
53 /** 11h TPC Power capability maximum setting, sent in TPC_INFO command to fw */
54 #define WLAN_11H_TPC_POWERCAPABILITY_MAX 20
55 
56 /** Regulatory requirement for the duration of a channel availability check */
57 #define WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION 60000 /* in ms */
58 
59 /** Starting Frequency for 11A band */
60 #define START_FREQ_11A_BAND 5000 /* in MHz */
61 
62 /** DFS Channel Move Time */
63 #define DFS_CHAN_MOVE_TIME 10 /* in sec */
64 
65 /** Regulatory requirement for the duration of a non-occupancy period */
66 #define WLAN_11H_NON_OCCUPANCY_PERIOD 1800 /* in sec (30mins) */
67 
68 /** Maximum allowable age (seconds) on DFS report data */
69 #define MAX_DFS_REPORT_USABLE_AGE_SEC (120) /* 2 minutes */
70 
71 /** Minimum delay for CHAN_SW IE to broadcast by FW */
72 #define MIN_RDH_CHAN_SW_IE_PERIOD_MSEC (400) /* 4 beacons @ 100ms */
73 
74 /** Maximum delay for CHAN_SW IE to broadcast by FW */
75 #define MAX_RDH_CHAN_SW_IE_PERIOD_MSEC (3000) /* 5 beacons @ 600ms */
76 
77 /** Maximum retries on selecting new random channel */
78 #define MAX_RANDOM_CHANNEL_RETRIES (20)
79 
80 /** Maximum retries on selecting new random non-dfs channel */
81 #define MAX_SWITCH_CHANNEL_RETRIES (30)
82 
83 /** Value for undetermined priv_curr_idx on first entry to new RDH stage */
84 #define RDH_STAGE_FIRST_ENTRY_PRIV_IDX (0xff)
85 
86 /** Region codes 0x10, 0x20:  channels 1 thru 11 supported */
87 static const IEEEtypes_SupportChan_Subband_t wlan_11h_2_4G_region_FCC = {1, 11};
88 
89 /** Region codes 0x30, 0x32, 0x41, 0x50:  channels 1 thru 13 supported */
90 static const IEEEtypes_SupportChan_Subband_t wlan_11h_2_4G_region_EU = {1, 13};
91 
92 /** Region code 0x40:  only channel 14 supported */
93 static const IEEEtypes_SupportChan_Subband_t wlan_11h_2_4G_region_JPN40 = {14,
94 									   1};
95 
96 /** JPN sub-band config : Start Channel = 8, NumChans = 3 */
97 static const IEEEtypes_SupportChan_Subband_t wlan_11h_JPN_bottom_band = {8, 3};
98 
99 /** U-NII sub-band config : Start Channel = 36, NumChans = 4 */
100 static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_lower_band = {36, 4};
101 
102 /** U-NII sub-band config : Start Channel = 52, NumChans = 4 */
103 static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_middle_band = {52,
104 									  4};
105 
106 /** U-NII sub-band config : Start Channel = 100, NumChans = 11 */
107 static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_mid_upper_band = {
108 	100, 11};
109 
110 /** U-NII sub-band config : Start Channel = 100, NumChans = 5 */
111 static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_mid_upper_band_0 = {
112 	100, 5};
113 
114 /** U-NII sub-band config : Start Channel = 132, NumChans = 3 */
115 static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_mid_upper_band_1 = {
116 	132, 3};
117 
118 /** U-NII sub-band config : Start Channel = 149, NumChans = 5 */
119 static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_upper_band = {149,
120 									 5};
121 /** U-NII sub-band config : Start Channel = 169, NumChans = 3 */
122 static const IEEEtypes_SupportChan_Subband_t wlan_11h_unii_4_band = {169, 3};
123 
124 /** Internally passed structure used to send a CMD_802_11_TPC_INFO command */
125 typedef struct {
126 	t_u8 chan; /**< Channel to which the power constraint applies */
127 	t_u8 power_constraint; /**< Local power constraint to send to firmware
128 				*/
129 } wlan_11h_tpc_info_param_t;
130 
131 /********************************************************
132 			Global Variables
133 ********************************************************/
134 
135 /********************************************************
136 			Local Functions
137 ********************************************************/
138 
139 /**
140  *  @brief Utility function to get a random number based on the underlying OS
141  *
142  *  @param pmadapter Pointer to mlan_adapter
143  *  @return random integer
144  */
wlan_11h_get_random_num(pmlan_adapter pmadapter)145 static t_u32 wlan_11h_get_random_num(pmlan_adapter pmadapter)
146 {
147 	t_u32 sec, usec;
148 
149 	ENTER();
150 	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
151 						  &usec);
152 	sec = (sec & 0xFFFF) + (sec >> 16);
153 	usec = (usec & 0xFFFF) + (usec >> 16);
154 
155 	LEAVE();
156 	return (usec << 16) | sec;
157 }
158 
159 /**
160  *  @brief Convert an IEEE formatted IE to 16-bit ID/Len NXP
161  *         proprietary format
162  *
163  *  @param pmadapter Pointer to mlan_adapter
164  *  @param pout_buf Output parameter: Buffer to output NXP formatted IE
165  *  @param pin_ie   Pointer to IEEE IE to be converted to NXP format
166  *
167  *  @return         Number of bytes output to pout_buf parameter return
168  */
wlan_11h_convert_ieee_to_mrvl_ie(mlan_adapter * pmadapter,t_u8 * pout_buf,const t_u8 * pin_ie)169 static t_u32 wlan_11h_convert_ieee_to_mrvl_ie(mlan_adapter *pmadapter,
170 					      t_u8 *pout_buf,
171 					      const t_u8 *pin_ie)
172 {
173 	MrvlIEtypesHeader_t mrvl_ie_hdr;
174 	t_u8 *ptmp_buf = pout_buf;
175 
176 	ENTER();
177 	/* Assign the Element Id and Len to the NXP struct attributes */
178 	mrvl_ie_hdr.type = wlan_cpu_to_le16(pin_ie[0]);
179 	mrvl_ie_hdr.len = wlan_cpu_to_le16(pin_ie[1]);
180 
181 	/* If the element ID is zero, return without doing any copying */
182 	if (!mrvl_ie_hdr.type) {
183 		LEAVE();
184 		return 0;
185 	}
186 
187 	/* Copy the header to the buffer pointer */
188 	memcpy_ext(pmadapter, ptmp_buf, &mrvl_ie_hdr, sizeof(mrvl_ie_hdr),
189 		   sizeof(mrvl_ie_hdr));
190 
191 	/* Increment the temp buffer pointer by the size appended */
192 	ptmp_buf += sizeof(mrvl_ie_hdr);
193 
194 	/* Append the data section of the IE; length given by the IEEE IE length
195 	 */
196 	memcpy_ext(pmadapter, ptmp_buf, pin_ie + 2, pin_ie[1], pin_ie[1]);
197 
198 	LEAVE();
199 	/* Return the number of bytes appended to pout_buf */
200 	return sizeof(mrvl_ie_hdr) + pin_ie[1];
201 }
202 
203 /**
204  *  @brief find all bonded channel.
205  *
206  *  @param pri_chan   primary channel
207  *  @param bw         channel bandwidth
208  *  @param chan_list  buffer to return channel list.
209  *
210  *  @return           number of channel
211  */
woal_get_bonded_channels(t_u8 pri_chan,t_u8 bw,t_u8 * chan_list)212 static t_u8 woal_get_bonded_channels(t_u8 pri_chan, t_u8 bw, t_u8 *chan_list)
213 {
214 	t_u8 ht40_plus[] = {52, 60, 100, 108, 116, 124, 132, 140};
215 	t_u8 ht40_minus[] = {56, 64, 104, 112, 120, 128, 136, 144};
216 	t_u8 vht80_dfs[4][4] = {{52, 56, 60, 64},
217 				{100, 104, 108, 112},
218 				{116, 120, 124, 128},
219 				{132, 136, 140, 144}};
220 	t_u8 find = MFALSE;
221 	int j;
222 	int i;
223 	t_u8 sec_chan = 0;
224 	t_u8 n_chan = 1;
225 	ENTER();
226 
227 	if (bw == CHAN_BW_20MHZ) {
228 		chan_list[0] = pri_chan;
229 	} else if (bw == CHAN_BW_40MHZ) {
230 		chan_list[0] = pri_chan;
231 		for (i = 0; i < sizeof(ht40_minus); i++) {
232 			if (pri_chan == (t_u8)ht40_plus[i]) {
233 				sec_chan = pri_chan + 4;
234 				n_chan = 2;
235 				break;
236 			}
237 		}
238 		for (i = 0; i < sizeof(ht40_minus); i++) {
239 			if (pri_chan == (t_u8)ht40_minus[i]) {
240 				sec_chan = pri_chan - 4;
241 				n_chan = 2;
242 				break;
243 			}
244 		}
245 		chan_list[1] = sec_chan;
246 	} else if (bw == CHAN_BW_80MHZ) {
247 		for (i = 0; i < 4; i++) {
248 			for (j = 0; j < 4; j++) {
249 				if (pri_chan == (t_u8)vht80_dfs[i][j]) {
250 					find = MTRUE;
251 					break;
252 				}
253 			}
254 			if (find)
255 				break;
256 		}
257 		if (find) {
258 			n_chan = 4;
259 			for (j = 0; j < n_chan; j++) {
260 				chan_list[j] = (t_u8)vht80_dfs[i][j];
261 			}
262 		}
263 	}
264 	LEAVE();
265 	return n_chan;
266 }
267 
268 /**
269  *  @brief Set channel's dfs state
270  *
271  *  @param priv         Private driver information structure
272  *  @param chan         primary channel
273  *  @param bw           channel bandwidth
274  *  @param dfs_state    dfs state
275  *
276  *  @return  N/A
277  */
wlan_11h_set_chan_dfs_state(mlan_private * priv,t_u8 chan,t_u8 bw,dfs_state_t dfs_state)278 t_void wlan_11h_set_chan_dfs_state(mlan_private *priv, t_u8 chan, t_u8 bw,
279 				   dfs_state_t dfs_state)
280 {
281 	t_u8 n_chan;
282 	t_u8 chan_list[4];
283 	t_u8 i;
284 	n_chan = woal_get_bonded_channels(chan, bw, chan_list);
285 	for (i = 0; i < n_chan; i++)
286 		wlan_set_chan_dfs_state(priv, BAND_A, chan_list[i], dfs_state);
287 }
288 
289 #ifdef STA_SUPPORT
290 /**
291  *  @brief Setup the IBSS DFS element passed to the firmware in adhoc start
292  *         and join commands
293  *
294  *  The DFS Owner and recovery fields are set to be our MAC address and
295  *    a predetermined constant recovery value.  If we are joining an adhoc
296  *    network, these values are replaced with the existing IBSS values.
297  *    They are valid only when starting a new IBSS.
298  *
299  *  The IBSS DFS Element is variable in size based on the number of
300  *    channels supported in our current region.
301  *
302  *  @param priv Private driver information structure
303  *  @param pdfs Output parameter: Pointer to the IBSS DFS element setup by
304  *              this function.
305  *
306  *  @return
307  *    - Length of the returned element in pdfs output parameter
308  *    - 0 if returned element is not setup
309  */
wlan_11h_set_ibss_dfs_ie(mlan_private * priv,IEEEtypes_IBSS_DFS_t * pdfs)310 static t_u32 wlan_11h_set_ibss_dfs_ie(mlan_private *priv,
311 				      IEEEtypes_IBSS_DFS_t *pdfs)
312 {
313 	t_u8 num_chans = 0;
314 	MeasRptBasicMap_t initial_map;
315 	mlan_adapter *adapter = priv->adapter;
316 
317 	ENTER();
318 
319 	memset(adapter, pdfs, 0x00, sizeof(IEEEtypes_IBSS_DFS_t));
320 
321 	/*
322 	 * A basic measurement report is included with each channel in the
323 	 *   map field.  Initial value for the map for each supported channel
324 	 *   is with only the unmeasured bit set.
325 	 */
326 	memset(adapter, &initial_map, 0x00, sizeof(initial_map));
327 	initial_map.unmeasured = 1;
328 
329 	/* Set the DFS Owner and recovery interval fields */
330 	memcpy_ext(adapter, pdfs->dfs_owner, priv->curr_addr,
331 		   sizeof(pdfs->dfs_owner), sizeof(pdfs->dfs_owner));
332 	pdfs->dfs_recovery_interval = WLAN_11H_DEFAULT_DFS_RECOVERY_INTERVAL;
333 
334 	for (; (num_chans < adapter->parsed_region_chan.no_of_chan) &&
335 	       (num_chans < WLAN_11H_MAX_IBSS_DFS_CHANNELS);
336 	     num_chans++) {
337 		pdfs->channel_map[num_chans].channel_number =
338 			adapter->parsed_region_chan.chan_pwr[num_chans].chan;
339 
340 		/*
341 		 * Set the initial map field with a basic measurement
342 		 */
343 		pdfs->channel_map[num_chans].rpt_map = initial_map;
344 	}
345 
346 	/*
347 	 * If we have an established channel map, include it and return
348 	 *   a valid DFS element
349 	 */
350 	if (num_chans) {
351 		PRINTM(MINFO, "11h: Added %d channels to IBSS DFS Map\n",
352 		       num_chans);
353 
354 		pdfs->element_id = IBSS_DFS;
355 		pdfs->len = (sizeof(pdfs->dfs_owner) +
356 			     sizeof(pdfs->dfs_recovery_interval) +
357 			     num_chans * sizeof(IEEEtypes_ChannelMap_t));
358 
359 		LEAVE();
360 		return pdfs->len + sizeof(pdfs->len) + sizeof(pdfs->element_id);
361 	}
362 
363 	/* Ensure the element is zeroed out for an invalid return */
364 	memset(adapter, pdfs, 0x00, sizeof(IEEEtypes_IBSS_DFS_t));
365 
366 	LEAVE();
367 	return 0;
368 }
369 #endif
370 
371 /**
372  *  @brief Setup the Supported Channel IE sent in association requests
373  *
374  *  The Supported Channels IE is required to be sent when the spectrum
375  *    management capability (11h) is enabled.  The element contains a
376  *    starting channel and number of channels tuple for each sub-band
377  *    the STA supports.  This information is based on the operating region.
378  *
379  *  @param priv      Private driver information structure
380  *  @param band      Band in use
381  *  @param psup_chan Output parameter: Pointer to the Supported Chan element
382  *                   setup by this function.
383  *
384  *  @return
385  *    - Length of the returned element in psup_chan output parameter
386  *    - 0 if returned element is not setup
387  */
388 static t_u16
wlan_11h_set_supp_channels_ie(mlan_private * priv,t_u16 band,IEEEtypes_SupportedChannels_t * psup_chan)389 wlan_11h_set_supp_channels_ie(mlan_private *priv, t_u16 band,
390 			      IEEEtypes_SupportedChannels_t *psup_chan)
391 {
392 	t_u16 num_subbands = 0;
393 	t_u16 ret_len = 0;
394 	t_u8 cfp_bg, cfp_a;
395 
396 	ENTER();
397 	memset(priv->adapter, psup_chan, 0x00,
398 	       sizeof(IEEEtypes_SupportedChannels_t));
399 
400 	cfp_bg = cfp_a = priv->adapter->region_code;
401 	if (!priv->adapter->region_code) {
402 		/* Invalid region code, use CFP code */
403 		cfp_bg = priv->adapter->cfp_code_bg;
404 		cfp_a = priv->adapter->cfp_code_a;
405 	}
406 
407 	if ((band & BAND_B) || (band & BAND_G)) {
408 		/*
409 		 * Channels are contiguous in 2.4GHz, usually only one subband.
410 		 */
411 		switch (cfp_bg) {
412 		case 0x10: /* USA FCC   */
413 		case 0x20: /* Canada IC */
414 		default:
415 			psup_chan->subband[num_subbands++] =
416 				wlan_11h_2_4G_region_FCC;
417 			break;
418 		case 0x30: /* Europe ETSI */
419 		case 0x41: /* Japan  */
420 		case 0x50: /* China  */
421 			psup_chan->subband[num_subbands++] =
422 				wlan_11h_2_4G_region_EU;
423 			break;
424 		case 0x40: /* Japan  */
425 			psup_chan->subband[num_subbands++] =
426 				wlan_11h_2_4G_region_JPN40;
427 			break;
428 		case 0xff: /* Japan special */
429 			psup_chan->subband[num_subbands++] =
430 				wlan_11h_2_4G_region_EU;
431 			psup_chan->subband[num_subbands++] =
432 				wlan_11h_2_4G_region_JPN40;
433 			break;
434 		}
435 	} else if (band & BAND_A) {
436 		/*
437 		 * Set the supported channel elements based on the region code,
438 		 * incrementing num_subbands for each sub-band we append to the
439 		 * element.
440 		 */
441 		switch (cfp_a) {
442 		case 0x10: /* USA FCC   */
443 			psup_chan->subband[num_subbands++] =
444 				wlan_11h_unii_lower_band;
445 			psup_chan->subband[num_subbands++] =
446 				wlan_11h_unii_middle_band;
447 			psup_chan->subband[num_subbands++] =
448 				wlan_11h_unii_mid_upper_band;
449 			psup_chan->subband[num_subbands++] =
450 				wlan_11h_unii_upper_band;
451 			psup_chan->subband[num_subbands++] =
452 				wlan_11h_unii_4_band;
453 			break;
454 		case 0x20: /* Canada IC */
455 		case 0x30: /* Europe ETSI */
456 		default:
457 			psup_chan->subband[num_subbands++] =
458 				wlan_11h_unii_lower_band;
459 			psup_chan->subband[num_subbands++] =
460 				wlan_11h_unii_middle_band;
461 			psup_chan->subband[num_subbands++] =
462 				wlan_11h_unii_mid_upper_band;
463 			psup_chan->subband[num_subbands++] =
464 				wlan_11h_unii_upper_band;
465 			break;
466 		case 0x50: /* China */
467 			psup_chan->subband[num_subbands++] =
468 				wlan_11h_unii_lower_band;
469 			psup_chan->subband[num_subbands++] =
470 				wlan_11h_unii_middle_band;
471 			psup_chan->subband[num_subbands++] =
472 				wlan_11h_unii_upper_band;
473 			break;
474 		case 0x40: /* Japan */
475 		case 0x41: /* Japan */
476 		case 0xff: /* Japan special */
477 			psup_chan->subband[num_subbands++] =
478 				wlan_11h_JPN_bottom_band;
479 			psup_chan->subband[num_subbands++] =
480 				wlan_11h_unii_lower_band;
481 			psup_chan->subband[num_subbands++] =
482 				wlan_11h_unii_middle_band;
483 			psup_chan->subband[num_subbands++] =
484 				wlan_11h_unii_mid_upper_band;
485 			break;
486 		case 0x1: /* Low band (5150-5250 MHz) channels */
487 			psup_chan->subband[num_subbands++] =
488 				wlan_11h_unii_lower_band;
489 			break;
490 		case 0x2: /* Lower middle band (5250-5350 MHz) channels */
491 			psup_chan->subband[num_subbands++] =
492 				wlan_11h_unii_middle_band;
493 			break;
494 		case 0x3: /* Upper middle band (5470-5725 MHz) channels */
495 			psup_chan->subband[num_subbands++] =
496 				wlan_11h_unii_mid_upper_band;
497 			break;
498 		case 0x4: /* High band (5725-5850 MHz) channels */
499 			psup_chan->subband[num_subbands++] =
500 				wlan_11h_unii_upper_band;
501 			break;
502 		case 0x5: /* Low band (5150-5250 MHz) and High band (5725-5850
503 			     MHz) channels */
504 			psup_chan->subband[num_subbands++] =
505 				wlan_11h_unii_lower_band;
506 			psup_chan->subband[num_subbands++] =
507 				wlan_11h_unii_upper_band;
508 			break;
509 		case 0x6: /* Low band (5150-5250 MHz) and Lower middle band
510 			     (5250-5350 MHz) and High band (5725-5850 MHz)
511 			     channels */
512 			psup_chan->subband[num_subbands++] =
513 				wlan_11h_unii_lower_band;
514 			psup_chan->subband[num_subbands++] =
515 				wlan_11h_unii_middle_band;
516 			psup_chan->subband[num_subbands++] =
517 				wlan_11h_unii_upper_band;
518 			break;
519 		case 0x7:
520 			/* 36-48 */
521 			psup_chan->subband[num_subbands++] =
522 				wlan_11h_unii_lower_band;
523 			/* 52-64 */
524 			psup_chan->subband[num_subbands++] =
525 				wlan_11h_unii_middle_band;
526 			/* 100-116 */
527 			psup_chan->subband[num_subbands++] =
528 				wlan_11h_unii_mid_upper_band_0;
529 			/* 132-140 */
530 			psup_chan->subband[num_subbands++] =
531 				wlan_11h_unii_mid_upper_band_1;
532 			/* 149-165 */
533 			psup_chan->subband[num_subbands++] =
534 				wlan_11h_unii_upper_band;
535 			break;
536 		}
537 	}
538 
539 	/*
540 	 * If we have setup any supported subbands in the element, return a
541 	 *    valid IE along with its size, else return 0.
542 	 */
543 	if (num_subbands) {
544 		psup_chan->element_id = SUPPORTED_CHANNELS;
545 		psup_chan->len =
546 			num_subbands * sizeof(IEEEtypes_SupportChan_Subband_t);
547 
548 		ret_len = (t_u16)(psup_chan->len + sizeof(psup_chan->len) +
549 				  sizeof(psup_chan->element_id));
550 
551 		HEXDUMP("11h: SupChan", (t_u8 *)psup_chan, ret_len);
552 	}
553 
554 	LEAVE();
555 	return ret_len;
556 }
557 
558 /**
559  *  @brief Prepare CMD_802_11_TPC_ADAPT_REQ firmware command
560  *
561  *  @param priv      Private driver information structure
562  *  @param pcmd_ptr  Output parameter: Pointer to the command being prepared
563  *                   for the firmware
564  *  @param pinfo_buf HostCmd_DS_802_11_TPC_ADAPT_REQ passed as void data block
565  *
566  *  @return          MLAN_STATUS_SUCCESS
567  */
wlan_11h_cmd_tpc_request(mlan_private * priv,HostCmd_DS_COMMAND * pcmd_ptr,const t_void * pinfo_buf)568 static mlan_status wlan_11h_cmd_tpc_request(mlan_private *priv,
569 					    HostCmd_DS_COMMAND *pcmd_ptr,
570 					    const t_void *pinfo_buf)
571 {
572 	ENTER();
573 
574 	memcpy_ext(priv->adapter, &pcmd_ptr->params.tpc_req, pinfo_buf,
575 		   sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ),
576 		   sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ));
577 
578 	pcmd_ptr->params.tpc_req.req.timeout =
579 		wlan_cpu_to_le16(pcmd_ptr->params.tpc_req.req.timeout);
580 
581 	/* Converted to little endian in wlan_11h_cmd_process */
582 	pcmd_ptr->size = sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ) + S_DS_GEN;
583 
584 	HEXDUMP("11h: 11_TPC_ADAPT_REQ:", (t_u8 *)pcmd_ptr,
585 		(t_u32)pcmd_ptr->size);
586 
587 	LEAVE();
588 	return MLAN_STATUS_SUCCESS;
589 }
590 
591 /**
592  *  @brief Prepare CMD_802_11_TPC_INFO firmware command
593  *
594  *  @param priv      Private driver information structure
595  *  @param pcmd_ptr  Output parameter: Pointer to the command being prepared
596  *                   for the firmware
597  *  @param pinfo_buf wlan_11h_tpc_info_param_t passed as void data block
598  *
599  *  @return          MLAN_STATUS_SUCCESS
600  */
wlan_11h_cmd_tpc_info(mlan_private * priv,HostCmd_DS_COMMAND * pcmd_ptr,const t_void * pinfo_buf)601 static mlan_status wlan_11h_cmd_tpc_info(mlan_private *priv,
602 					 HostCmd_DS_COMMAND *pcmd_ptr,
603 					 const t_void *pinfo_buf)
604 {
605 	HostCmd_DS_802_11_TPC_INFO *ptpc_info = &pcmd_ptr->params.tpc_info;
606 	MrvlIEtypes_LocalPowerConstraint_t *pconstraint =
607 		&ptpc_info->local_constraint;
608 	MrvlIEtypes_PowerCapability_t *pcap = &ptpc_info->power_cap;
609 
610 	wlan_11h_device_state_t *pstate = &priv->adapter->state_11h;
611 	const wlan_11h_tpc_info_param_t *ptpc_info_param =
612 		(wlan_11h_tpc_info_param_t *)pinfo_buf;
613 
614 	ENTER();
615 
616 	pcap->min_power = pstate->min_tx_power_capability;
617 	pcap->max_power = pstate->max_tx_power_capability;
618 	pcap->header.len = wlan_cpu_to_le16(2);
619 	pcap->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CAPABILITY);
620 
621 	pconstraint->chan = ptpc_info_param->chan;
622 	pconstraint->constraint = ptpc_info_param->power_constraint;
623 	pconstraint->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CONSTRAINT);
624 	pconstraint->header.len = wlan_cpu_to_le16(2);
625 
626 	/* Converted to little endian in wlan_11h_cmd_process */
627 	pcmd_ptr->size = sizeof(HostCmd_DS_802_11_TPC_INFO) + S_DS_GEN;
628 
629 	HEXDUMP("11h: TPC INFO", (t_u8 *)pcmd_ptr, (t_u32)pcmd_ptr->size);
630 
631 	LEAVE();
632 	return MLAN_STATUS_SUCCESS;
633 }
634 
635 /**
636  *  @brief  Prepare CMD_802_11_CHAN_SW_ANN firmware command
637  *
638  *  @param priv      Private driver information structure
639  *  @param pcmd_ptr  Output parameter: Pointer to the command being
640  *                   prepared to for firmware
641  *  @param pinfo_buf HostCmd_DS_802_11_CHAN_SW_ANN passed as void data block
642  *
643  *  @return          MLAN_STATUS_SUCCESS
644  */
wlan_11h_cmd_chan_sw_ann(mlan_private * priv,HostCmd_DS_COMMAND * pcmd_ptr,const t_void * pinfo_buf)645 static mlan_status wlan_11h_cmd_chan_sw_ann(mlan_private *priv,
646 					    HostCmd_DS_COMMAND *pcmd_ptr,
647 					    const t_void *pinfo_buf)
648 {
649 	const HostCmd_DS_802_11_CHAN_SW_ANN *pch_sw_ann =
650 		(HostCmd_DS_802_11_CHAN_SW_ANN *)pinfo_buf;
651 
652 	ENTER();
653 
654 	/* Converted to little endian in wlan_11h_cmd_process */
655 	pcmd_ptr->size = sizeof(HostCmd_DS_802_11_CHAN_SW_ANN) + S_DS_GEN;
656 
657 	memcpy_ext(priv->adapter, &pcmd_ptr->params.chan_sw_ann, pch_sw_ann,
658 		   sizeof(HostCmd_DS_802_11_CHAN_SW_ANN),
659 		   sizeof(HostCmd_DS_802_11_CHAN_SW_ANN));
660 
661 	PRINTM(MINFO, "11h: ChSwAnn: %#x-%u, Seq=%u, Ret=%u\n",
662 	       pcmd_ptr->command, pcmd_ptr->size, pcmd_ptr->seq_num,
663 	       pcmd_ptr->result);
664 	PRINTM(MINFO, "11h: ChSwAnn: Ch=%d, Cnt=%d, Mode=%d\n",
665 	       pch_sw_ann->new_chan, pch_sw_ann->switch_count,
666 	       pch_sw_ann->switch_mode);
667 
668 	LEAVE();
669 	return MLAN_STATUS_SUCCESS;
670 }
671 
672 /**
673  *  @brief  Prepare CMD_CHAN_REPORT_REQUEST firmware command
674  *
675  *  @param priv      Private driver information structure
676  *  @param pcmd_ptr  Output parameter: Pointer to the command being
677  *                   prepared to for firmware
678  *  @param pinfo_buf HostCmd_DS_CHAN_RPT_REQ passed as void data block
679  *
680  *  @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING
681  */
wlan_11h_cmd_chan_rpt_req(mlan_private * priv,HostCmd_DS_COMMAND * pcmd_ptr,const t_void * pinfo_buf)682 static mlan_status wlan_11h_cmd_chan_rpt_req(mlan_private *priv,
683 					     HostCmd_DS_COMMAND *pcmd_ptr,
684 					     const t_void *pinfo_buf)
685 {
686 	HostCmd_DS_CHAN_RPT_REQ *pchan_rpt_req =
687 		(HostCmd_DS_CHAN_RPT_REQ *)pinfo_buf;
688 	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
689 	MrvlIEtypes_ChanRpt11hBasic_t *ptlv_basic;
690 	t_bool is_cancel_req = MFALSE;
691 	MrvlIEtypes_ZeroDfsOperation_t *ptlv_zero_dfs;
692 	t_u8 dfs53cfg = priv->adapter->dfs53cfg;
693 	MrvlIEtypes_DfsW53Cfg_t *ptlv_dfs53cfg;
694 
695 	ENTER();
696 
697 	/*
698 	 * pchan_rpt_req->millisec_dwell_time would be zero if the chan_rpt_req
699 	 * is to cancel current ongoing report
700 	 */
701 	if (pchan_rpt_req->millisec_dwell_time == 0)
702 		is_cancel_req = MTRUE;
703 
704 	if (pstate_dfs->dfs_check_pending && !is_cancel_req &&
705 	    priv->bss_type != MLAN_BSS_TYPE_DFS) {
706 		PRINTM(MERROR,
707 		       "11h: ChanRptReq - previous CMD_CHAN_REPORT_REQUEST has"
708 		       " not returned its result yet (as EVENT_CHANNEL_READY)."
709 		       "  This command will be dropped.\n");
710 		LEAVE();
711 		return MLAN_STATUS_PENDING;
712 	}
713 
714 	/* Converted to little endian in wlan_11h_cmd_process */
715 	pcmd_ptr->size = sizeof(HostCmd_DS_CHAN_RPT_REQ) + S_DS_GEN;
716 
717 	memcpy_ext(priv->adapter, &pcmd_ptr->params.chan_rpt_req, pchan_rpt_req,
718 		   sizeof(HostCmd_DS_CHAN_RPT_REQ),
719 		   sizeof(HostCmd_DS_CHAN_RPT_REQ));
720 	pcmd_ptr->params.chan_rpt_req.chan_desc.startFreq =
721 		wlan_cpu_to_le16(pchan_rpt_req->chan_desc.startFreq);
722 	pcmd_ptr->params.chan_rpt_req.millisec_dwell_time =
723 		wlan_cpu_to_le32(pchan_rpt_req->millisec_dwell_time);
724 
725 	/* if DFS channel, add BASIC report TLV, and set radar bit */
726 	if (!is_cancel_req && wlan_11h_radar_detect_required(
727 				      priv, pchan_rpt_req->chan_desc.chanNum)) {
728 		ptlv_basic =
729 			(MrvlIEtypes_ChanRpt11hBasic_t *)(((t_u8 *)(pcmd_ptr)) +
730 							  pcmd_ptr->size);
731 		ptlv_basic->Header.type =
732 			wlan_cpu_to_le16(TLV_TYPE_CHANRPT_11H_BASIC);
733 		ptlv_basic->Header.len =
734 			wlan_cpu_to_le16(sizeof(MeasRptBasicMap_t));
735 		memset(priv->adapter, &ptlv_basic->map, 0,
736 		       sizeof(MeasRptBasicMap_t));
737 		ptlv_basic->map.radar = 1;
738 		pcmd_ptr->size += sizeof(MrvlIEtypes_ChanRpt11hBasic_t);
739 	}
740 
741 	if ((priv->adapter->region_code == COUNTRY_CODE_JP_40 ||
742 	     priv->adapter->region_code == COUNTRY_CODE_JP_FF) &&
743 	    (dfs53cfg != DFS_W53_DEFAULT_FW)) {
744 		ptlv_dfs53cfg =
745 			(MrvlIEtypes_DfsW53Cfg_t *)(((t_u8 *)(pcmd_ptr)) +
746 						    pcmd_ptr->size);
747 		ptlv_dfs53cfg->Header.type =
748 			wlan_cpu_to_le16(TLV_TYPE_DFS_W53_CFG);
749 		ptlv_dfs53cfg->Header.len = wlan_cpu_to_le16(sizeof(t_u8));
750 		ptlv_dfs53cfg->dfs53cfg = dfs53cfg;
751 		pcmd_ptr->size += sizeof(MrvlIEtypes_DfsW53Cfg_t);
752 	}
753 
754 	if (priv->bss_type == MLAN_BSS_TYPE_DFS) {
755 		memcpy_ext(priv->adapter, &priv->chan_rep_req, pchan_rpt_req,
756 			   sizeof(mlan_ds_11h_chan_rep_req),
757 			   sizeof(priv->chan_rep_req));
758 		ptlv_zero_dfs =
759 			(MrvlIEtypes_ZeroDfsOperation_t *)(((t_u8 *)(pcmd_ptr)) +
760 							   pcmd_ptr->size);
761 		ptlv_zero_dfs->Header.type =
762 			wlan_cpu_to_le16(TLV_TYPE_ZERO_DFS_OPERATION);
763 		ptlv_zero_dfs->Header.len = wlan_cpu_to_le16(sizeof(t_u8));
764 		if (!is_cancel_req) {
765 			ptlv_zero_dfs->zero_dfs_enbl = MTRUE;
766 			PRINTM(MCMND, "DFS: START: chan=%d bw=%d\n",
767 			       pchan_rpt_req->chan_desc.chanNum,
768 			       pchan_rpt_req->chan_desc.bandcfg.chanWidth);
769 		} else {
770 			ptlv_zero_dfs->zero_dfs_enbl = MFALSE;
771 			PRINTM(MCMND, "DFS: STOP\n");
772 		}
773 		pcmd_ptr->size += sizeof(MrvlIEtypes_ZeroDfsOperation_t);
774 		LEAVE();
775 		return MLAN_STATUS_SUCCESS;
776 	}
777 
778 	/* update dfs sturcture.
779 	 * dfs_check_pending is set when we receive CMD_RESP == SUCCESS */
780 	pstate_dfs->dfs_check_pending = MFALSE;
781 	pstate_dfs->dfs_radar_found = MFALSE;
782 	pstate_dfs->dfs_check_priv = MNULL;
783 	if (!is_cancel_req) {
784 		pstate_dfs->dfs_check_channel =
785 			pchan_rpt_req->chan_desc.chanNum;
786 		pstate_dfs->dfs_check_bandwidth =
787 			pchan_rpt_req->chan_desc.bandcfg.chanWidth;
788 	}
789 
790 	LEAVE();
791 	return MLAN_STATUS_SUCCESS;
792 }
793 
794 /**
795  *  @brief Set the local power capability and constraint TLV
796  *
797  *  @param ppbuffer                The buffer to add these two TLVs
798  *  @param channel                 Channel to which the power constraint applies
799  *  @param power_constraint        Power constraint to be applied on the channel
800  *  @param min_tx_power_capability Min. Tx Power in Power Capability IE
801  *  @param max_tx_power_capability Max. Tx Power in Power Capability IE
802  *
803  *  @return                        The len increased
804  */
wlan_11h_set_local_power_constraint_tlv(t_u8 ** ppbuffer,t_u8 channel,t_u8 power_constraint,t_u8 min_tx_power_capability,t_u8 max_tx_power_capability)805 static t_u32 wlan_11h_set_local_power_constraint_tlv(
806 	t_u8 **ppbuffer, t_u8 channel, t_u8 power_constraint,
807 	t_u8 min_tx_power_capability, t_u8 max_tx_power_capability)
808 {
809 	MrvlIEtypes_PowerCapability_t *pcap;
810 	MrvlIEtypes_LocalPowerConstraint_t *pconstraint;
811 	t_u8 *start_ptr = MNULL;
812 
813 	ENTER();
814 
815 	/* Null Checks */
816 	if ((ppbuffer == MNULL) || (((t_u8 *)(*ppbuffer)) == MNULL)) {
817 		LEAVE();
818 		return 0;
819 	}
820 
821 	start_ptr = (t_u8 *)(*ppbuffer);
822 
823 	PRINTM(MINFO,
824 	       "11h: Set local power constraint = %d channel=%d min_tx_pwr=%d max_tx_pwr=%d\n",
825 	       power_constraint, channel, min_tx_power_capability,
826 	       max_tx_power_capability);
827 
828 	pcap = (MrvlIEtypes_PowerCapability_t *)*ppbuffer;
829 	pcap->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CAPABILITY);
830 	pcap->header.len = wlan_cpu_to_le16(2);
831 	pcap->min_power = min_tx_power_capability;
832 	pcap->max_power = max_tx_power_capability;
833 	*ppbuffer += sizeof(MrvlIEtypesHeader_t) + 2;
834 
835 	pconstraint = (MrvlIEtypes_LocalPowerConstraint_t *)*ppbuffer;
836 	pconstraint->header.type = wlan_cpu_to_le16(TLV_TYPE_POWER_CONSTRAINT);
837 	pconstraint->header.len = wlan_cpu_to_le16(2);
838 	pconstraint->chan = channel;
839 	pconstraint->constraint = power_constraint;
840 	*ppbuffer += sizeof(MrvlIEtypesHeader_t) + 2;
841 
842 	LEAVE();
843 	return (t_u32)(*ppbuffer - start_ptr);
844 }
845 
846 /**
847  *  @brief  Utility function to process a join to an infrastructure BSS
848  *
849  *  @param priv          Private driver information structure
850  *  @param ppbuffer      Output parameter: Pointer to the TLV output buffer,
851  *                       modified on return to point after the appended 11h TLVs
852  *  @param band          Band on which we are joining the BSS
853  *  @param channel       Channel on which we are joining the BSS
854  *  @param p11h_bss_info Pointer to the 11h BSS information for this network
855  *                       that was parsed out of the scan response.
856  *
857  *  @return              Integer number of bytes appended to the TLV output
858  *                       buffer (ppbuffer)
859  */
wlan_11h_process_infra_join(mlan_private * priv,t_u8 ** ppbuffer,t_u16 band,t_u32 channel,wlan_11h_bss_info_t * p11h_bss_info)860 static t_u32 wlan_11h_process_infra_join(mlan_private *priv, t_u8 **ppbuffer,
861 					 t_u16 band, t_u32 channel,
862 					 wlan_11h_bss_info_t *p11h_bss_info)
863 {
864 	MrvlIEtypesHeader_t ie_header;
865 	IEEEtypes_SupportedChannels_t sup_chan_ie;
866 	t_u32 ret_len = 0;
867 	t_u16 sup_chan_len = 0;
868 
869 	ENTER();
870 
871 	/* Null Checks */
872 	if ((ppbuffer == MNULL) || (((t_u8 *)(*ppbuffer)) == MNULL)) {
873 		LEAVE();
874 		return 0;
875 	}
876 
877 	ret_len += wlan_11h_set_local_power_constraint_tlv(
878 		ppbuffer, (t_u8)channel,
879 		(t_u8)p11h_bss_info->power_constraint.local_constraint,
880 		(t_u8)priv->adapter->state_11h.min_tx_power_capability,
881 		(t_u8)priv->adapter->state_11h.max_tx_power_capability);
882 
883 	/* Setup the Supported Channels IE */
884 	sup_chan_len = wlan_11h_set_supp_channels_ie(priv, band, &sup_chan_ie);
885 
886 	/*
887 	 * If we returned a valid Supported Channels IE, wrap and append it
888 	 */
889 	if (sup_chan_len) {
890 		/* Wrap the supported channels IE with a passthrough TLV type */
891 		ie_header.type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH);
892 		ie_header.len = wlan_cpu_to_le16(sup_chan_len);
893 		memcpy_ext(priv->adapter, *ppbuffer, &ie_header,
894 			   sizeof(ie_header), sizeof(ie_header));
895 
896 		/*
897 		 * Increment the return size and the return buffer
898 		 * pointer param
899 		 */
900 		*ppbuffer += sizeof(ie_header);
901 		ret_len += sizeof(ie_header);
902 
903 		/*
904 		 * Copy the supported channels IE to the output buf,
905 		 * advance pointer
906 		 */
907 		memcpy_ext(priv->adapter, *ppbuffer, &sup_chan_ie, sup_chan_len,
908 			   sup_chan_len);
909 		*ppbuffer += sup_chan_len;
910 		ret_len += sup_chan_len;
911 	}
912 
913 	LEAVE();
914 	return ret_len;
915 }
916 
917 /**
918  *  @brief Utility function to process a start or join to an adhoc network
919  *
920  *  Add the elements to the TLV buffer needed in the start/join adhoc commands:
921  *       - IBSS DFS IE
922  *       - Quiet IE
923  *
924  *  Also send the local constraint to the firmware in a TPC_INFO command.
925  *
926  *  @param priv          Private driver information structure
927  *  @param ppbuffer      Output parameter: Pointer to the TLV output buffer,
928  *                       modified on return to point after the appended 11h TLVs
929  *  @param channel       Channel on which we are starting/joining the IBSS
930  *  @param p11h_bss_info Pointer to the 11h BSS information for this network
931  *                       that was parsed out of the scan response.  NULL
932  *                       indicates we are starting the adhoc network
933  *
934  *  @return              Integer number of bytes appended to the TLV output
935  *                       buffer (ppbuffer)
936  */
wlan_11h_process_adhoc(mlan_private * priv,t_u8 ** ppbuffer,t_u32 channel,wlan_11h_bss_info_t * p11h_bss_info)937 static t_u32 wlan_11h_process_adhoc(mlan_private *priv, t_u8 **ppbuffer,
938 				    t_u32 channel,
939 				    wlan_11h_bss_info_t *p11h_bss_info)
940 {
941 	IEEEtypes_IBSS_DFS_t dfs_elem;
942 	t_u32 size_appended;
943 	t_u32 ret_len = 0;
944 	t_s8 local_constraint = 0;
945 	mlan_adapter *adapter = priv->adapter;
946 
947 	ENTER();
948 
949 #ifdef STA_SUPPORT
950 	/* Format our own IBSS DFS Element.  Include our channel map fields */
951 	wlan_11h_set_ibss_dfs_ie(priv, &dfs_elem);
952 #endif
953 
954 	if (p11h_bss_info) {
955 		/*
956 		 * Copy the DFS Owner/Recovery Interval from the BSS
957 		 * we are joining
958 		 */
959 		memcpy_ext(adapter, dfs_elem.dfs_owner,
960 			   p11h_bss_info->ibss_dfs.dfs_owner,
961 			   sizeof(dfs_elem.dfs_owner),
962 			   sizeof(dfs_elem.dfs_owner));
963 		dfs_elem.dfs_recovery_interval =
964 			p11h_bss_info->ibss_dfs.dfs_recovery_interval;
965 	}
966 
967 	/* Append the dfs element to the TLV buffer */
968 	size_appended = wlan_11h_convert_ieee_to_mrvl_ie(
969 		adapter, (t_u8 *)*ppbuffer, (t_u8 *)&dfs_elem);
970 
971 	HEXDUMP("11h: IBSS-DFS", (t_u8 *)*ppbuffer, size_appended);
972 	*ppbuffer += size_appended;
973 	ret_len += size_appended;
974 
975 	/*
976 	 * Check to see if we are joining a network.  Join is indicated by the
977 	 *   BSS Info pointer being valid (not NULL)
978 	 */
979 	if (p11h_bss_info) {
980 		/*
981 		 * If there was a quiet element, include it in
982 		 * adhoc join command
983 		 */
984 		if (p11h_bss_info->quiet.element_id == QUIET) {
985 			size_appended = wlan_11h_convert_ieee_to_mrvl_ie(
986 				adapter, (t_u8 *)*ppbuffer,
987 				(t_u8 *)&p11h_bss_info->quiet);
988 			HEXDUMP("11h: Quiet", (t_u8 *)*ppbuffer, size_appended);
989 			*ppbuffer += size_appended;
990 			ret_len += size_appended;
991 		}
992 
993 		/* Copy the local constraint from the network */
994 		local_constraint =
995 			p11h_bss_info->power_constraint.local_constraint;
996 	} else {
997 		/*
998 		 * If we are the adhoc starter, we can add a quiet element
999 		 */
1000 		if (adapter->state_11h.quiet_ie.quiet_period) {
1001 			size_appended = wlan_11h_convert_ieee_to_mrvl_ie(
1002 				adapter, (t_u8 *)*ppbuffer,
1003 				(t_u8 *)&adapter->state_11h.quiet_ie);
1004 			HEXDUMP("11h: Quiet", (t_u8 *)*ppbuffer, size_appended);
1005 			*ppbuffer += size_appended;
1006 			ret_len += size_appended;
1007 		}
1008 		/* Use the local_constraint configured in the driver state */
1009 		local_constraint = adapter->state_11h.usr_def_power_constraint;
1010 	}
1011 
1012 	PRINTM(MINFO, "WEILIE 1: ppbuffer = %p\n", *ppbuffer);
1013 
1014 	ret_len += wlan_11h_set_local_power_constraint_tlv(
1015 		ppbuffer, (t_u8)channel, (t_u8)local_constraint,
1016 		(t_u8)priv->adapter->state_11h.min_tx_power_capability,
1017 		(t_u8)priv->adapter->state_11h.max_tx_power_capability);
1018 	PRINTM(MINFO, "WEILIE 2: ppbuffer = %p\n", *ppbuffer);
1019 
1020 	LEAVE();
1021 	return ret_len;
1022 }
1023 
1024 /**
1025  *  @brief Return whether the driver has enabled 11h for the interface
1026  *
1027  *  Association/Join commands are dynamic in that they enable 11h in the
1028  *    driver/firmware when they are detected in the existing BSS.
1029  *
1030  *  @param priv  Private driver information structure
1031  *
1032  *  @return
1033  *    - MTRUE if 11h is enabled
1034  *    - MFALSE otherwise
1035  */
wlan_11h_is_enabled(mlan_private * priv)1036 static t_bool wlan_11h_is_enabled(mlan_private *priv)
1037 {
1038 	ENTER();
1039 	LEAVE();
1040 	return priv->intf_state_11h.is_11h_enabled;
1041 }
1042 
1043 /**
1044  *  @brief Return whether the device has activated slave radar detection.
1045  *
1046  *  @param priv  Private driver information structure
1047  *
1048  *  @return
1049  *    - MTRUE if slave radar detection is enabled in firmware
1050  *    - MFALSE otherwise
1051  */
wlan_11h_is_slave_radar_det_active(mlan_private * priv)1052 static t_bool wlan_11h_is_slave_radar_det_active(mlan_private *priv)
1053 {
1054 	ENTER();
1055 	LEAVE();
1056 	return priv->adapter->state_11h.is_slave_radar_det_active;
1057 }
1058 /**
1059  *  @brief Return whether the slave interface is active, and on DFS channel.
1060  *  priv is assumed to already be a dfs slave interface, doesn't check this.
1061  *
1062  *  @param priv  Private driver information structure
1063  *
1064  *  @return
1065  *    - MTRUE if priv is slave, and meets both conditions
1066  *    - MFALSE otherwise
1067  */
wlan_11h_is_slave_active_on_dfs_chan(mlan_private * priv)1068 static t_bool wlan_11h_is_slave_active_on_dfs_chan(mlan_private *priv)
1069 {
1070 	t_bool ret = MFALSE;
1071 
1072 	ENTER();
1073 	if ((priv->media_connected == MTRUE) &&
1074 	    (priv->curr_bss_params.band & BAND_A) &&
1075 	    wlan_11h_radar_detect_required(
1076 		    priv, priv->curr_bss_params.bss_descriptor.channel))
1077 		ret = MTRUE;
1078 
1079 	LEAVE();
1080 	return ret;
1081 }
1082 
1083 /**
1084  *  @brief Check if the current input channel is on radar channel
1085  *
1086  *
1087  *  @param priv    Private driver information structure
1088  *  @param channel Channel to determine radar detection requirements
1089  *
1090  *  @return
1091  *    - MTRUE if radar detection is required
1092  *    - MFALSE otherwise
1093  */
wlan_11h_is_radar_channel(mlan_private * priv,t_u8 channel)1094 t_bool wlan_11h_is_radar_channel(mlan_private *priv, t_u8 channel)
1095 {
1096 	t_bool required = MFALSE;
1097 
1098 	ENTER();
1099 
1100 	/*
1101 	 * No checks for 11h or measurement code being enabled is placed here
1102 	 * since regulatory requirements exist whether we support them or not.
1103 	 */
1104 
1105 	required = wlan_get_cfp_radar_detect(priv, channel);
1106 
1107 	LEAVE();
1108 	return required;
1109 }
1110 
1111 /**
1112  *  @brief Return whether the master interface is active, and on DFS channel.
1113  *  priv is assumed to already be a dfs master interface, doesn't check this.
1114  *
1115  *  @param priv  Private driver information structure
1116  *
1117  *  @return
1118  *    - MTRUE if priv is master, and meets both conditions
1119  *    - MFALSE otherwise
1120  */
wlan_11h_is_master_active_on_dfs_chan(mlan_private * priv)1121 static t_bool wlan_11h_is_master_active_on_dfs_chan(mlan_private *priv)
1122 {
1123 	t_bool ret = MFALSE;
1124 
1125 	ENTER();
1126 	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
1127 		/* Ad-hoc creator */
1128 		if (((priv->media_connected == MTRUE) ||
1129 		     (priv->adhoc_state == ADHOC_STARTING)) &&
1130 		    (priv->adapter->adhoc_start_band & BAND_A) &&
1131 		    wlan_11h_radar_detect_required(priv, priv->adhoc_channel))
1132 			ret = MTRUE;
1133 	} else if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
1134 		/* UAP */
1135 #ifdef UAP_SUPPORT
1136 		if ((priv->uap_bss_started == MTRUE) &&
1137 		    (priv->uap_state_chan_cb.bandcfg.chanBand == BAND_5GHZ) &&
1138 		    wlan_11h_radar_detect_required(
1139 			    priv, priv->uap_state_chan_cb.channel))
1140 			ret = MTRUE;
1141 #endif
1142 	}
1143 	LEAVE();
1144 	return ret;
1145 }
1146 
1147 /**
1148  *  @brief Determine if priv is DFS Master interface
1149  *
1150  *  @param priv Pointer to mlan_private
1151  *
1152  *  @return MTRUE or MFALSE
1153  */
wlan_11h_is_dfs_master(mlan_private * priv)1154 static t_bool wlan_11h_is_dfs_master(mlan_private *priv)
1155 {
1156 	t_bool ret = MFALSE;
1157 
1158 	ENTER();
1159 	/* UAP: all are master */
1160 	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
1161 		ret = MTRUE;
1162 
1163 	/* STA: only ad-hoc creator is master */
1164 	else if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1165 		 (priv->bss_mode == MLAN_BSS_MODE_IBSS) &&
1166 		 (priv->adhoc_state == ADHOC_STARTED ||
1167 		  priv->adhoc_state == ADHOC_STARTING))
1168 		ret = MTRUE;
1169 
1170 	/* all other cases = slave interface */
1171 	LEAVE();
1172 	return ret;
1173 }
1174 
1175 /* Need this as function to pass to wlan_count_priv_cond() */
1176 /**
1177  *  @brief Determine if priv is DFS Slave interface
1178  *
1179  *  @param priv Pointer to mlan_private
1180  *
1181  *  @return MTRUE or MFALSE
1182  */
1183 
wlan_11h_is_dfs_slave(mlan_private * priv)1184 static t_bool wlan_11h_is_dfs_slave(mlan_private *priv)
1185 {
1186 	t_bool ret = MFALSE;
1187 	ENTER();
1188 	ret = !wlan_11h_is_dfs_master(priv);
1189 	LEAVE();
1190 	return ret;
1191 }
1192 
1193 /**
1194  *  @brief This function checks if interface is active.
1195  *
1196  *  @param pmpriv       A pointer to mlan_private structure
1197  *
1198  *  @return             MTRUE or MFALSE
1199  */
wlan_is_intf_active(mlan_private * pmpriv)1200 t_bool wlan_is_intf_active(mlan_private *pmpriv)
1201 {
1202 	t_bool ret = MFALSE;
1203 	ENTER();
1204 
1205 #ifdef UAP_SUPPORT
1206 	if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
1207 		/*
1208 		 * NOTE: UAP's media_connected == true only after first STA
1209 		 * associated. Need different variable to tell if UAP
1210 		 * has been started.
1211 		 */
1212 		ret = pmpriv->uap_bss_started;
1213 	else
1214 #endif
1215 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
1216 		ret = pmpriv->media_connected;
1217 
1218 	LEAVE();
1219 	return ret;
1220 }
1221 
1222 /**
1223  *  @brief This function gets current radar detect flags
1224  *
1225  *  @param pmadapter    A pointer to mlan_adapter structure
1226  *
1227  *  @return             11H MIB setting for radar detect
1228  */
wlan_11h_get_current_radar_detect_flags(mlan_adapter * pmadapter)1229 static t_u32 wlan_11h_get_current_radar_detect_flags(mlan_adapter *pmadapter)
1230 {
1231 	t_u32 radar_det_flags = 0;
1232 
1233 	ENTER();
1234 	if (pmadapter->state_11h.is_master_radar_det_active)
1235 		radar_det_flags |= MASTER_RADAR_DET_MASK;
1236 	if (pmadapter->state_11h.is_slave_radar_det_active)
1237 		radar_det_flags |= SLAVE_RADAR_DET_MASK;
1238 
1239 	PRINTM(MINFO, "%s: radar_det_state_curr=0x%x\n", __func__,
1240 	       radar_det_flags);
1241 
1242 	LEAVE();
1243 	return radar_det_flags;
1244 }
1245 
1246 /**
1247  *  @brief This function checks if radar detect flags have/should be changed.
1248  *
1249  *  @param pmadapter    A pointer to mlan_adapter structure
1250  *  @param pnew_state   Output param with new state, if return MTRUE.
1251  *
1252  *  @return             MTRUE (need update) or MFALSE (no change in flags)
1253  */
wlan_11h_check_radar_det_state(mlan_adapter * pmadapter,t_u32 * pnew_state)1254 static t_bool wlan_11h_check_radar_det_state(mlan_adapter *pmadapter,
1255 					     t_u32 *pnew_state)
1256 {
1257 	t_u32 radar_det_state_new = 0;
1258 	t_bool ret;
1259 
1260 	ENTER();
1261 	PRINTM(MINFO,
1262 	       "%s: master_radar_det_pending=%d, "
1263 	       " slave_radar_det_pending=%d\n",
1264 	       __func__, pmadapter->state_11h.master_radar_det_enable_pending,
1265 	       pmadapter->state_11h.slave_radar_det_enable_pending);
1266 
1267 	/* new state comes from evaluating interface states & pending starts */
1268 	if (pmadapter->state_11h.master_radar_det_enable_pending ||
1269 	    (wlan_count_priv_cond(pmadapter,
1270 				  wlan_11h_is_master_active_on_dfs_chan,
1271 				  wlan_11h_is_dfs_master) > 0))
1272 		radar_det_state_new |= MASTER_RADAR_DET_MASK;
1273 	if (pmadapter->state_11h.slave_radar_det_enable_pending ||
1274 	    (wlan_count_priv_cond(pmadapter,
1275 				  wlan_11h_is_slave_active_on_dfs_chan,
1276 				  wlan_11h_is_dfs_slave) > 0))
1277 		radar_det_state_new |= SLAVE_RADAR_DET_MASK;
1278 
1279 	PRINTM(MINFO, "%s: radar_det_state_new=0x%x\n", __func__,
1280 	       radar_det_state_new);
1281 
1282 	/* now compare flags with current state */
1283 	ret = (wlan_11h_get_current_radar_detect_flags(pmadapter) !=
1284 	       radar_det_state_new) ?
1285 		      MTRUE :
1286 		      MFALSE;
1287 	if (ret)
1288 		*pnew_state = radar_det_state_new;
1289 
1290 	LEAVE();
1291 	return ret;
1292 }
1293 
1294 /**
1295  *  @brief generate the channel center frequency index
1296  *
1297  *  @param channel_num       channel number
1298  *
1299  *  @return                 frenquency index
1300  */
wlan_11h_get_channel_freq_idx(t_u8 channel_num)1301 static t_u8 wlan_11h_get_channel_freq_idx(t_u8 channel_num)
1302 {
1303 	t_u8 index;
1304 	t_u8 center_freq[] = {42, 58, 106, 122, 138, 155};
1305 	t_u8 chan_idx, ret = 0;
1306 
1307 	chan_idx = channel_num - 100;
1308 
1309 	for (index = 0; index < sizeof(center_freq); index++) {
1310 		if ((chan_idx >= (center_freq[index] - 6)) &&
1311 		    (chan_idx <= (center_freq[index] + 6))) {
1312 			ret = center_freq[index];
1313 			break;
1314 		}
1315 	}
1316 
1317 	return ret;
1318 }
1319 
1320 /**
1321  *  @brief Prepare ioctl for add/remove CHAN_SW IE - RADAR_DETECTED event
1322  * handling
1323  *
1324  *  @param pmadapter        Pointer to mlan_adapter
1325  *  @param pioctl_req       Pointer to completed mlan_ioctl_req (allocated
1326  * inside)
1327  *  @param ppcust_chansw_ie Poniter to customer ie
1328  *  @param is_adding_ie     CHAN_SW IE is to be added (MTRUE), or removed
1329  * (MFALSE)
1330  *
1331  *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1332  */
1333 static mlan_status
wlan_11h_prepare_custom_ie_chansw(mlan_adapter * pmadapter,mlan_ioctl_req ** ppioctl_req,t_bool is_adding_ie)1334 wlan_11h_prepare_custom_ie_chansw(mlan_adapter *pmadapter,
1335 				  mlan_ioctl_req **ppioctl_req,
1336 				  t_bool is_adding_ie)
1337 {
1338 	mlan_ioctl_req *pioctl_req = MNULL;
1339 	mlan_ds_misc_cfg *pds_misc_cfg = MNULL;
1340 	custom_ie *pcust_chansw_ie = MNULL;
1341 	IEEEtypes_ChanSwitchAnn_t *pchansw_ie = MNULL;
1342 	mlan_status ret;
1343 	IEEEtypes_Header_t *pChanSwWrap_ie = MNULL;
1344 	IEEEtypes_WideBWChanSwitch_t *pbwchansw_ie = MNULL;
1345 	IEEEtypes_VhtTpcEnvelope_t *pvhttpcEnv_ie = MNULL;
1346 	t_u8 index;
1347 	mlan_private *pmpriv = MNULL;
1348 
1349 	ENTER();
1350 
1351 	if (pmadapter == MNULL || ppioctl_req == MNULL) {
1352 		LEAVE();
1353 		return MLAN_STATUS_FAILURE;
1354 	}
1355 
1356 	/* allocate buffer for mlan_ioctl_req and mlan_ds_misc_cfg */
1357 	/* FYI - will be freed as part of cmd_response handler */
1358 	ret = pmadapter->callbacks.moal_malloc(
1359 		pmadapter->pmoal_handle,
1360 		sizeof(mlan_ioctl_req) + sizeof(mlan_ds_misc_cfg), MLAN_MEM_DEF,
1361 		(t_u8 **)&pioctl_req);
1362 	if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
1363 		PRINTM(MERROR, "%s(): Could not allocate ioctl req\n",
1364 		       __func__);
1365 		LEAVE();
1366 		return MLAN_STATUS_FAILURE;
1367 	}
1368 	pds_misc_cfg = (mlan_ds_misc_cfg *)((t_u8 *)pioctl_req +
1369 					    sizeof(mlan_ioctl_req));
1370 
1371 	/* prepare mlan_ioctl_req */
1372 	memset(pmadapter, pioctl_req, 0x00, sizeof(mlan_ioctl_req));
1373 	pioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
1374 	pioctl_req->action = MLAN_ACT_SET;
1375 	pioctl_req->pbuf = (t_u8 *)pds_misc_cfg;
1376 	pioctl_req->buf_len = sizeof(mlan_ds_misc_cfg);
1377 
1378 	/* prepare mlan_ds_misc_cfg */
1379 	memset(pmadapter, pds_misc_cfg, 0x00, sizeof(mlan_ds_misc_cfg));
1380 	pds_misc_cfg->sub_command = MLAN_OID_MISC_CUSTOM_IE;
1381 	pds_misc_cfg->param.cust_ie.type = TLV_TYPE_MGMT_IE;
1382 	pds_misc_cfg->param.cust_ie.len = (sizeof(custom_ie) - MAX_IE_SIZE);
1383 
1384 	/* configure custom_ie api settings */
1385 	pcust_chansw_ie =
1386 		(custom_ie *)&pds_misc_cfg->param.cust_ie.ie_data_list[0];
1387 	pcust_chansw_ie->ie_index = 0xffff; /* Auto index */
1388 	pcust_chansw_ie->ie_length = sizeof(IEEEtypes_ChanSwitchAnn_t);
1389 	pcust_chansw_ie->mgmt_subtype_mask =
1390 		(is_adding_ie) ? MBIT(8) | MBIT(5) /* add IE for BEACON |
1391 						      PROBE_RSP */
1392 				 :
1393 				 0; /* remove IE */
1394 
1395 	/* prepare CHAN_SW IE inside ioctl */
1396 	pchansw_ie = (IEEEtypes_ChanSwitchAnn_t *)pcust_chansw_ie->ie_buffer;
1397 	pchansw_ie->element_id = CHANNEL_SWITCH_ANN;
1398 	pchansw_ie->len =
1399 		sizeof(IEEEtypes_ChanSwitchAnn_t) - sizeof(IEEEtypes_Header_t);
1400 	pchansw_ie->chan_switch_mode = 1; /* STA should not transmit */
1401 	pchansw_ie->new_channel_num = pmadapter->state_rdh.new_channel;
1402 
1403 	pchansw_ie->chan_switch_count = pmadapter->dfs_cs_count;
1404 	PRINTM(MCMD_D, "New Channel = %d Channel switch count = %d\n",
1405 	       pmadapter->state_rdh.new_channel, pchansw_ie->chan_switch_count);
1406 
1407 	for (index = 0; index < pmadapter->state_rdh.priv_list_count; index++) {
1408 		pmpriv = pmadapter->state_rdh.priv_list[index];
1409 		/*find the first AP interface*/
1410 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
1411 			if (pmpriv->is_11ac_enabled) {
1412 				pChanSwWrap_ie =
1413 					(IEEEtypes_Header_t
1414 						 *)((t_u8 *)pchansw_ie +
1415 						    sizeof(IEEEtypes_ChanSwitchAnn_t));
1416 				pChanSwWrap_ie->element_id = EXT_POWER_CONSTR;
1417 				/*will have multiple sub IEs*/
1418 				pChanSwWrap_ie->len = 0;
1419 
1420 				/* prepare the Wide Bandwidth Channel Switch IE
1421 				 * Channel Switch IE */
1422 				pbwchansw_ie =
1423 					(IEEEtypes_WideBWChanSwitch_t
1424 						 *)((t_u8 *)pChanSwWrap_ie +
1425 						    sizeof(IEEEtypes_Header_t));
1426 				pbwchansw_ie->ieee_hdr.element_id =
1427 					BW_CHANNEL_SWITCH;
1428 				pbwchansw_ie->ieee_hdr.len =
1429 					sizeof(IEEEtypes_WideBWChanSwitch_t) -
1430 					sizeof(IEEEtypes_Header_t);
1431 				/*fix 80MHZ now*/
1432 				pbwchansw_ie->new_channel_width =
1433 					VHT_OPER_CHWD_80MHZ;
1434 				pbwchansw_ie->new_channel_center_freq0 =
1435 					wlan_11h_get_channel_freq_idx(
1436 						pmadapter->state_rdh
1437 							.new_channel);
1438 				pbwchansw_ie->new_channel_center_freq1 =
1439 					wlan_11h_get_channel_freq_idx(
1440 						pmadapter->state_rdh
1441 							.new_channel);
1442 				pChanSwWrap_ie->len +=
1443 					sizeof(IEEEtypes_WideBWChanSwitch_t);
1444 
1445 				/*prepare the VHT Transmit Power Envelope IE*/
1446 				pvhttpcEnv_ie =
1447 					(IEEEtypes_VhtTpcEnvelope_t
1448 						 *)((t_u8 *)pChanSwWrap_ie +
1449 						    sizeof(IEEEtypes_Header_t) +
1450 						    sizeof(IEEEtypes_WideBWChanSwitch_t));
1451 				pvhttpcEnv_ie->ieee_hdr.element_id =
1452 					VHT_TX_POWER_ENV;
1453 				pvhttpcEnv_ie->ieee_hdr.len =
1454 					sizeof(IEEEtypes_VhtTpcEnvelope_t) -
1455 					sizeof(IEEEtypes_Header_t);
1456 				/* Local Max TX Power Count= 3,
1457 				 * Local TX Power Unit Inter=EIP(0) */
1458 				pvhttpcEnv_ie->tpc_info = 3;
1459 				pvhttpcEnv_ie->local_max_tp_20mhz = 0xff;
1460 				pvhttpcEnv_ie->local_max_tp_40mhz = 0xff;
1461 				pvhttpcEnv_ie->local_max_tp_80mhz = 0xff;
1462 				pvhttpcEnv_ie->local_max_tp_160mhz_80_80mhz =
1463 					0xff;
1464 				pChanSwWrap_ie->len +=
1465 					sizeof(IEEEtypes_VhtTpcEnvelope_t);
1466 
1467 				pcust_chansw_ie->ie_length +=
1468 					sizeof(IEEEtypes_WideBWChanSwitch_t) +
1469 					sizeof(IEEEtypes_VhtTpcEnvelope_t) +
1470 					sizeof(IEEEtypes_Header_t);
1471 
1472 				PRINTM(MINFO,
1473 				       "Append Wide Bandwidth Channel Switch IE\n");
1474 				break;
1475 			}
1476 		}
1477 	}
1478 
1479 	pds_misc_cfg->param.cust_ie.len += pcust_chansw_ie->ie_length;
1480 	DBG_HEXDUMP(MCMD_D, "11h: custom_ie containing CHAN_SW IE",
1481 		    (t_u8 *)pcust_chansw_ie, pds_misc_cfg->param.cust_ie.len);
1482 
1483 	/* assign output pointer before returning */
1484 	*ppioctl_req = pioctl_req;
1485 	LEAVE();
1486 	return MLAN_STATUS_SUCCESS;
1487 }
1488 
1489 #ifdef UAP_SUPPORT
1490 /**
1491  *  @brief Check if start channel 165 is allowed to operate in
1492  *  previous uAP channel's band config
1493  *
1494  *  @param priv          a pointer to mlan_private structure
1495  *  @param start_chn     Random Start channel choosen after radar detection
1496  *  @param uap_band_cfg  Private driver uAP band configuration information
1497  * structure
1498  *
1499  *  @return MFALSE if the channel is not allowed in given band
1500  */
wlan_11h_is_band_valid(mlan_private * priv,t_u8 start_chn,Band_Config_t uap_band_cfg)1501 static t_bool wlan_11h_is_band_valid(mlan_private *priv, t_u8 start_chn,
1502 				     Band_Config_t uap_band_cfg)
1503 {
1504 	/* if band width is not 20MHZ (either 40 or 80MHz)
1505 	 * return MFALSE, 165 is not allowed in bands other than 20MHZ
1506 	 */
1507 	if (start_chn == 165) {
1508 		if (priv->adapter->region_code == COUNTRY_CODE_US)
1509 			return MTRUE;
1510 		if (uap_band_cfg.chanWidth != CHAN_BW_20MHZ)
1511 			return MFALSE;
1512 	}
1513 	return MTRUE;
1514 }
1515 
1516 /**
1517  *  @brief Retrieve a randomly selected starting channel if needed for 11h
1518  *
1519  *  If 11h is enabled and 5GHz band is selected in band_config
1520  *    return a random channel in A band, else one from BG band.
1521  *
1522  *  @param priv          Private driver information structure
1523  *  @param uap_band_cfg  Private driver information structure
1524  *
1525  *  @return      Starting channel
1526  */
wlan_11h_get_uap_start_channel(mlan_private * priv,Band_Config_t uap_band_cfg)1527 static t_u8 wlan_11h_get_uap_start_channel(mlan_private *priv,
1528 					   Band_Config_t uap_band_cfg)
1529 {
1530 	t_u8 start_chn;
1531 	mlan_adapter *adapter = priv->adapter;
1532 	t_u32 region;
1533 	t_u32 rand_entry;
1534 	region_chan_t *chn_tbl;
1535 	t_u8 rand_tries = 0;
1536 
1537 	/*TODO:  right now mostly a copy of wlan_11h_get_adhoc_start_channel.
1538 	 *       Improve to be more specfic to UAP, e.g.
1539 	 *       1. take into account COUNTRY_CODE -> region_code
1540 	 *       2. check domain_info for value channels
1541 	 */
1542 	ENTER();
1543 
1544 	/*
1545 	 * Set start_chn to the Default.
1546 	 * Used if 11h is disabled or the band
1547 	 * does not require 11h support.
1548 	 */
1549 	start_chn = DEFAULT_AD_HOC_CHANNEL;
1550 
1551 	/*
1552 	 * Check that we are looking for a channel in the A Band
1553 	 */
1554 	if (uap_band_cfg.chanBand == BAND_5GHZ) {
1555 		/*
1556 		 * Set default to the A Band default.
1557 		 * Used if random selection fails
1558 		 * or if 11h is not enabled
1559 		 */
1560 		start_chn = DEFAULT_AD_HOC_CHANNEL_A;
1561 
1562 		/*
1563 		 * Check that 11h is enabled in the driver
1564 		 */
1565 		if (wlan_11h_is_enabled(priv)) {
1566 			/*
1567 			 * Search the region_channel tables for a channel table
1568 			 * that is marked for the A Band.
1569 			 */
1570 			for (region = 0; (region < MAX_REGION_CHANNEL_NUM);
1571 			     region++) {
1572 				chn_tbl = &adapter->region_channel[region];
1573 
1574 				/* Check if table is valid and marked for A Band
1575 				 */
1576 				if (chn_tbl->valid &&
1577 				    chn_tbl->region == adapter->region_code &&
1578 				    chn_tbl->band & BAND_A) {
1579 					/*
1580 					 * Set the start channel.  Get a random
1581 					 * number and use it to pick an entry
1582 					 * in the table between 0 and the number
1583 					 * of channels in the table (NumCFP).
1584 					 */
1585 					rand_entry = wlan_11h_get_random_num(
1586 							     adapter) %
1587 						     chn_tbl->num_cfp;
1588 					start_chn =
1589 						(t_u8)chn_tbl->pcfp[rand_entry]
1590 							.channel;
1591 					/* Loop until a non-dfs channel is found
1592 					 * with compatible band bounded by
1593 					 * chn_tbl->num_cfp entries in the
1594 					 * channel table
1595 					 */
1596 					while (((chn_tbl->pcfp[rand_entry]
1597 							 .dynamic.flags &
1598 						 NXP_CHANNEL_DISABLED) ||
1599 						(wlan_11h_is_channel_under_nop(
1600 							 adapter, start_chn) ||
1601 						 ((adapter->state_rdh.stage ==
1602 						   RDH_GET_INFO_CHANNEL) &&
1603 						  wlan_11h_radar_detect_required(
1604 							  priv, start_chn)) ||
1605 						 !(wlan_11h_is_band_valid(
1606 							 priv, start_chn,
1607 							 uap_band_cfg)))) &&
1608 					       (++rand_tries <
1609 						chn_tbl->num_cfp)) {
1610 						rand_entry++;
1611 						rand_entry = rand_entry %
1612 							     chn_tbl->num_cfp;
1613 						start_chn =
1614 							(t_u8)chn_tbl
1615 								->pcfp[rand_entry]
1616 								.channel;
1617 						PRINTM(MINFO,
1618 						       "start chan=%d rand_entry=%d\n",
1619 						       start_chn, rand_entry);
1620 					}
1621 
1622 					if (rand_tries == chn_tbl->num_cfp) {
1623 						PRINTM(MERROR,
1624 						       "Failed to get UAP start channel\n");
1625 						start_chn = 0;
1626 					}
1627 				}
1628 			}
1629 		}
1630 	}
1631 
1632 	PRINTM(MCMD_D, "11h: UAP Get Start Channel %d\n", start_chn);
1633 	LEAVE();
1634 	return start_chn;
1635 }
1636 #endif /* UAP_SUPPORT */
1637 
1638 #ifdef DEBUG_LEVEL1
1639 static const char *DFS_TS_REPR_STRINGS[] = {"", "NOP_start", "CAC_completed"};
1640 #endif
1641 
1642 /**
1643  *  @brief Search for a dfs timestamp in the list with desired channel.
1644  *
1645  *  Assumes there will only be one timestamp per channel in the list.
1646  *
1647  *  @param pmadapter  Pointer to mlan_adapter
1648  *  @param channel    Channel number
1649  *
1650  *  @return           Pointer to timestamp if found, or MNULL
1651  */
1652 static wlan_dfs_timestamp_t *
wlan_11h_find_dfs_timestamp(mlan_adapter * pmadapter,t_u8 channel)1653 wlan_11h_find_dfs_timestamp(mlan_adapter *pmadapter, t_u8 channel)
1654 {
1655 	wlan_dfs_timestamp_t *pts = MNULL, *pts_found = MNULL;
1656 
1657 	ENTER();
1658 	pts = (wlan_dfs_timestamp_t *)util_peek_list(
1659 		pmadapter->pmoal_handle, &pmadapter->state_dfs.dfs_ts_head,
1660 		MNULL, MNULL);
1661 
1662 	while (pts && pts != (wlan_dfs_timestamp_t *)&pmadapter->state_dfs
1663 				      .dfs_ts_head) {
1664 		PRINTM(MINFO,
1665 		       "dfs_timestamp(@ %p) - chan=%d, repr=%d(%s),"
1666 		       " time(sec.usec)=%lu.%06lu\n",
1667 		       pts, pts->channel, pts->represents,
1668 		       DFS_TS_REPR_STRINGS[pts->represents], pts->ts_sec,
1669 		       pts->ts_usec);
1670 
1671 		if (pts->channel == channel) {
1672 			pts_found = pts;
1673 			break;
1674 		}
1675 		pts = pts->pnext;
1676 	}
1677 
1678 	LEAVE();
1679 	return pts_found;
1680 }
1681 
1682 /**
1683  *  @brief Removes dfs timestamp from list.
1684  *
1685  *  @param pmadapter  Pointer to mlan_adapter
1686  *  @param pdfs_ts    Pointer to dfs_timestamp to remove
1687  */
wlan_11h_remove_dfs_timestamp(mlan_adapter * pmadapter,wlan_dfs_timestamp_t * pdfs_ts)1688 static t_void wlan_11h_remove_dfs_timestamp(mlan_adapter *pmadapter,
1689 					    wlan_dfs_timestamp_t *pdfs_ts)
1690 {
1691 	ENTER();
1692 	/* dequeue and delete timestamp */
1693 	util_unlink_list(pmadapter->pmoal_handle,
1694 			 &pmadapter->state_dfs.dfs_ts_head,
1695 			 (pmlan_linked_list)pdfs_ts, MNULL, MNULL);
1696 	pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
1697 					(t_u8 *)pdfs_ts);
1698 	LEAVE();
1699 }
1700 
1701 /**
1702  *  @brief Add a dfs timestamp to the list
1703  *
1704  *  Assumes there will only be one timestamp per channel in the list,
1705  *  and that timestamp modes (represents) are mutually exclusive.
1706  *
1707  *  @param pmadapter  Pointer to mlan_adapter
1708  *  @param repr       Timestamp 'represents' value (see _dfs_timestamp_repr_e)
1709  *  @param channel    Channel number
1710  *
1711  *  @return           Pointer to timestamp if found, or MNULL
1712  */
wlan_11h_add_dfs_timestamp(mlan_adapter * pmadapter,t_u8 repr,t_u8 channel)1713 static mlan_status wlan_11h_add_dfs_timestamp(mlan_adapter *pmadapter,
1714 					      t_u8 repr, t_u8 channel)
1715 {
1716 	wlan_dfs_timestamp_t *pdfs_ts = MNULL;
1717 	mlan_status ret = MLAN_STATUS_SUCCESS;
1718 
1719 	ENTER();
1720 	pdfs_ts = wlan_11h_find_dfs_timestamp(pmadapter, channel);
1721 
1722 	if (!pdfs_ts) {
1723 		/* need to allocate new timestamp */
1724 		ret = pmadapter->callbacks.moal_malloc(
1725 			pmadapter->pmoal_handle, sizeof(wlan_dfs_timestamp_t),
1726 			MLAN_MEM_DEF, (t_u8 **)&pdfs_ts);
1727 		if ((ret != MLAN_STATUS_SUCCESS) || !pdfs_ts) {
1728 			PRINTM(MERROR, "%s(): Could not allocate dfs_ts\n",
1729 			       __func__);
1730 			LEAVE();
1731 			return MLAN_STATUS_FAILURE;
1732 		}
1733 
1734 		memset(pmadapter, (t_u8 *)pdfs_ts, 0,
1735 		       sizeof(wlan_dfs_timestamp_t));
1736 
1737 		util_enqueue_list_tail(pmadapter->pmoal_handle,
1738 				       &pmadapter->state_dfs.dfs_ts_head,
1739 				       (pmlan_linked_list)pdfs_ts, MNULL,
1740 				       MNULL);
1741 		pdfs_ts->channel = channel;
1742 	}
1743 	/* (else, use existing timestamp for channel; see assumptions above) */
1744 
1745 	/* update params */
1746 	pmadapter->callbacks.moal_get_system_time(
1747 		pmadapter->pmoal_handle, &pdfs_ts->ts_sec, &pdfs_ts->ts_usec);
1748 	pdfs_ts->represents = repr;
1749 
1750 	PRINTM(MCMD_D,
1751 	       "11h: add/update dfs_timestamp - chan=%d, repr=%d(%s),"
1752 	       " time(sec.usec)=%lu.%06lu\n",
1753 	       pdfs_ts->channel, pdfs_ts->represents,
1754 	       DFS_TS_REPR_STRINGS[pdfs_ts->represents], pdfs_ts->ts_sec,
1755 	       pdfs_ts->ts_usec);
1756 
1757 	LEAVE();
1758 	return ret;
1759 }
1760 
1761 /**
1762  *  @brief Add all bonded channel's dfs timestamp to the list
1763  *
1764  *  @param pmadapter  Pointer to mlan_adapter
1765  *  @param repr       Timestamp 'represents' value (see _dfs_timestamp_repr_e)
1766  *  @param channel    Channel number
1767  *  @param bandwidth  Channel bandwidth
1768  *
1769  *  @return           Pointer to timestamp if found, or MNULL
1770  */
wlan_11h_add_all_dfs_timestamp(mlan_adapter * pmadapter,t_u8 repr,t_u8 channel,t_u8 bandwidth)1771 static void wlan_11h_add_all_dfs_timestamp(mlan_adapter *pmadapter, t_u8 repr,
1772 					   t_u8 channel, t_u8 bandwidth)
1773 {
1774 	t_u8 n_chan;
1775 	t_u8 chan_list[4];
1776 	t_u8 i;
1777 	n_chan = woal_get_bonded_channels(channel, bandwidth, chan_list);
1778 	for (i = 0; i < n_chan; i++)
1779 		wlan_11h_add_dfs_timestamp(pmadapter, repr, chan_list[i]);
1780 }
1781 
1782 /********************************************************
1783 			Global functions
1784 ********************************************************/
1785 
1786 /**
1787  *  @brief Return whether the device has activated master radar detection.
1788  *
1789  *  @param priv  Private driver information structure
1790  *
1791  *  @return
1792  *    - MTRUE if master radar detection is enabled in firmware
1793  *    - MFALSE otherwise
1794  */
wlan_11h_is_master_radar_det_active(mlan_private * priv)1795 t_bool wlan_11h_is_master_radar_det_active(mlan_private *priv)
1796 {
1797 	ENTER();
1798 	LEAVE();
1799 	return priv->adapter->state_11h.is_master_radar_det_active;
1800 }
1801 
1802 /**
1803  *  @brief Configure master radar detection.
1804  *  Call wlan_11h_check_update_radar_det_state() afterwards
1805  *    to push this to firmware.
1806  *
1807  *  @param priv  Private driver information structure
1808  *  @param enable Whether to enable or disable master radar detection
1809  *
1810  *  @return  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1811  *
1812  *  @sa wlan_11h_check_update_radar_det_state
1813  */
wlan_11h_config_master_radar_det(mlan_private * priv,t_bool enable)1814 mlan_status wlan_11h_config_master_radar_det(mlan_private *priv, t_bool enable)
1815 {
1816 	mlan_status ret = MLAN_STATUS_FAILURE;
1817 
1818 	/* Force disable master radar detection on in-AP interfaces */
1819 	if (priv->adapter->dfs_repeater)
1820 		enable = MFALSE;
1821 
1822 	ENTER();
1823 	if (wlan_11h_is_dfs_master(priv) &&
1824 	    priv->adapter->init_para.dfs_master_radar_det_en) {
1825 		priv->adapter->state_11h.master_radar_det_enable_pending =
1826 			enable;
1827 		ret = MLAN_STATUS_SUCCESS;
1828 	}
1829 
1830 	LEAVE();
1831 	return ret;
1832 }
1833 
1834 /**
1835  *  @brief Configure slave radar detection.
1836  *  Call wlan_11h_check_update_radar_det_state() afterwards
1837  *    to push this to firmware.
1838  *
1839  *  @param priv  Private driver information structure
1840  *  @param enable Whether to enable or disable slave radar detection
1841  *
1842  *  @return  MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1843  *
1844  *  @sa wlan_11h_check_update_radar_det_state
1845  */
wlan_11h_config_slave_radar_det(mlan_private * priv,t_bool enable)1846 mlan_status wlan_11h_config_slave_radar_det(mlan_private *priv, t_bool enable)
1847 {
1848 	mlan_status ret = MLAN_STATUS_FAILURE;
1849 
1850 	/* Force disable radar detection on STA interfaces */
1851 	if (priv->adapter->dfs_repeater)
1852 		enable = MFALSE;
1853 
1854 	ENTER();
1855 	if (wlan_11h_is_dfs_slave(priv) &&
1856 	    priv->adapter->init_para.dfs_slave_radar_det_en) {
1857 		priv->adapter->state_11h.slave_radar_det_enable_pending =
1858 			enable;
1859 		ret = MLAN_STATUS_SUCCESS;
1860 	}
1861 	LEAVE();
1862 	return ret;
1863 }
1864 
1865 #ifdef UAP_SUPPORT
1866 /**
1867  *  @brief Return whether the slave interface is on DFS channel.
1868  *  priv is assumed to already be a dfs slave interface, doesn't check this.
1869  *
1870  *  @param priv  Private driver information structure
1871  *
1872  *  @return
1873  *    - MTRUE if priv is slave, and meets both conditions
1874  *    - MFALSE otherwise
1875  */
wlan_11h_is_slave_on_dfs_chan(mlan_private * priv)1876 static t_bool wlan_11h_is_slave_on_dfs_chan(mlan_private *priv)
1877 {
1878 	t_bool ret = MFALSE;
1879 
1880 	ENTER();
1881 	if ((priv->media_connected == MTRUE) &&
1882 	    (priv->curr_bss_params.band & BAND_A) &&
1883 	    wlan_11h_is_radar_channel(
1884 		    priv, priv->curr_bss_params.bss_descriptor.channel))
1885 		ret = MTRUE;
1886 
1887 	LEAVE();
1888 	return ret;
1889 }
1890 
1891 /**
1892  *  @brief check if dfs_master and dfs_slave are in same channel
1893  *
1894  *  @param pmadapter Pointer to mlan_adapter structure
1895  *
1896  *  @return        MTRUE-dfs_master and dfs_slave interface on same DFS channel
1897  *
1898  */
wlan_11h_check_dfs_channel(mlan_adapter * pmadapter)1899 t_u8 static wlan_11h_check_dfs_channel(mlan_adapter *pmadapter)
1900 {
1901 	mlan_private *priv_master = MNULL;
1902 	mlan_private *priv_slave = MNULL;
1903 	mlan_private *priv_list[MLAN_MAX_BSS_NUM] = {MNULL};
1904 
1905 	if (wlan_get_privs_by_two_cond(
1906 		    pmadapter, wlan_11h_is_master_active_on_dfs_chan,
1907 		    wlan_11h_is_dfs_master, MTRUE, priv_list)) {
1908 		priv_master = priv_list[0];
1909 		PRINTM(MINFO, "%s: found dfs_master priv=%p\n", __func__,
1910 		       priv_master);
1911 	}
1912 	if (wlan_get_privs_by_two_cond(pmadapter, wlan_11h_is_slave_on_dfs_chan,
1913 				       wlan_11h_is_dfs_slave, MTRUE,
1914 				       priv_list)) {
1915 		priv_slave = priv_list[0];
1916 		PRINTM(MINFO, "%s: found dfs_slave priv=%p\n", __func__,
1917 		       priv_slave);
1918 	}
1919 	if (!priv_slave || !priv_master)
1920 		return MFALSE;
1921 	if (priv_master->uap_state_chan_cb.channel !=
1922 	    priv_slave->curr_bss_params.bss_descriptor.channel)
1923 		return MFALSE;
1924 	return MTRUE;
1925 }
1926 
1927 /**
1928  *   @brief disable 11h and DFS function
1929  *
1930  *  @param priv         Private driver information structure
1931  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
1932  *
1933  *  @return      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1934  */
wlan_11h_disable_dfs(mlan_private * priv,t_void * pioctl_buf)1935 mlan_status static wlan_11h_disable_dfs(mlan_private *priv, t_void *pioctl_buf)
1936 {
1937 	t_u32 enable = 0;
1938 	mlan_status ret = MLAN_STATUS_SUCCESS;
1939 
1940 	ENTER();
1941 
1942 	/*
1943 	 * Send cmd to FW to enable/disable 11h function in firmware
1944 	 */
1945 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
1946 			       HostCmd_ACT_GEN_SET, Dot11H_i,
1947 			       (t_void *)pioctl_buf, &enable);
1948 	if (ret)
1949 		ret = MLAN_STATUS_FAILURE;
1950 	else
1951 		/* Set boolean flag in driver 11h state */
1952 		priv->intf_state_11h.is_11h_active = MFALSE;
1953 
1954 	PRINTM(MINFO, "11h: DFS %s\n", "Deactivate");
1955 
1956 	LEAVE();
1957 	return ret;
1958 }
1959 
1960 /**
1961  *  @brief check if we need enable dfs_master
1962  *
1963  *  @param priv  Pointer to mlan_private structure
1964  *				 priv should be UAP priv
1965  *
1966  *  @return      N/A
1967  *
1968  */
wlan_11h_update_dfs_master_state_by_uap(mlan_private * pmpriv)1969 void wlan_11h_update_dfs_master_state_by_uap(mlan_private *pmpriv)
1970 {
1971 	mlan_adapter *pmadapter = pmpriv->adapter;
1972 	mlan_status ret = MLAN_STATUS_SUCCESS;
1973 	if (pmadapter->dfs_mode && wlan_11h_check_dfs_channel(pmadapter)) {
1974 		PRINTM(MCMND,
1975 		       "11h: disable DFS master when AP+STA on same DFS channel\n");
1976 		ret = wlan_11h_disable_dfs(pmpriv, MNULL);
1977 		return;
1978 	}
1979 	if (!wlan_11h_is_active(pmpriv)) {
1980 		/* active 11h extention in Fw */
1981 		PRINTM(MCMND,
1982 		       "11h: Enable DFS master after AP up or chan_switch\n");
1983 		ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
1984 		ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
1985 		ret = wlan_11h_check_update_radar_det_state(pmpriv);
1986 	}
1987 	if (pmpriv->uap_host_based && !pmpriv->adapter->init_para.dfs_offload)
1988 		pmpriv->intf_state_11h.is_11h_host = MTRUE;
1989 	wlan_11h_set_dfs_check_chan(pmpriv, pmpriv->uap_channel,
1990 				    pmpriv->uap_bandwidth);
1991 	return;
1992 }
1993 
1994 /**
1995  *  @brief check if dfs_master and dfs_slave are in same channel
1996  *
1997  *  @param pmadapter Pointer to mlan_adapter structure
1998  *
1999  *  @return        MTRUE-dfs_master and dfs_slave interface on same DFS channel
2000  *
2001  */
wlan_11h_update_dfs_master_state_by_sta(mlan_private * pmpriv)2002 void wlan_11h_update_dfs_master_state_by_sta(mlan_private *pmpriv)
2003 {
2004 	mlan_private *priv_master = MNULL;
2005 	mlan_private *priv_slave = MNULL;
2006 	mlan_private *priv_list[MLAN_MAX_BSS_NUM] = {MNULL};
2007 	mlan_adapter *pmadapter = pmpriv->adapter;
2008 	mlan_status ret = MLAN_STATUS_SUCCESS;
2009 
2010 	if (wlan_get_privs_by_two_cond(
2011 		    pmadapter, wlan_11h_is_master_active_on_dfs_chan,
2012 		    wlan_11h_is_dfs_master, MTRUE, priv_list)) {
2013 		priv_master = priv_list[0];
2014 		PRINTM(MINFO, "%s: found dfs_master priv=%p\n", __func__,
2015 		       priv_master);
2016 	}
2017 	if (wlan_get_privs_by_two_cond(pmadapter, wlan_11h_is_slave_on_dfs_chan,
2018 				       wlan_11h_is_dfs_slave, MTRUE,
2019 				       priv_list)) {
2020 		priv_slave = priv_list[0];
2021 		PRINTM(MINFO, "%s: found dfs_slave priv=%p\n", __func__,
2022 		       priv_slave);
2023 	}
2024 	if (!priv_slave || !priv_master)
2025 		return;
2026 	if (priv_master->uap_state_chan_cb.channel ==
2027 	    priv_slave->curr_bss_params.bss_descriptor.channel) {
2028 		PRINTM(MCMND,
2029 		       "11h: disable DFS master when AP+STA on same DFS channel\n");
2030 		ret = wlan_11h_disable_dfs(priv_master, MNULL);
2031 	}
2032 	return;
2033 }
2034 
2035 /**
2036  *  @brief update the dfs master state on station disconnect
2037  *
2038  *  @param priv  Pointer to mlan_private structure
2039  *				 priv should be UAP priv
2040  *
2041  *  @return      N/A
2042  *
2043  */
wlan_11h_update_dfs_master_state_on_disconect(mlan_private * priv)2044 void wlan_11h_update_dfs_master_state_on_disconect(mlan_private *priv)
2045 {
2046 	mlan_private *priv_master = MNULL;
2047 	mlan_private *priv_list[MLAN_MAX_BSS_NUM] = {MNULL};
2048 	mlan_adapter *pmadapter = priv->adapter;
2049 	mlan_status ret = MLAN_STATUS_SUCCESS;
2050 	if (wlan_get_privs_by_two_cond(
2051 		    pmadapter, wlan_11h_is_master_active_on_dfs_chan,
2052 		    wlan_11h_is_dfs_master, MTRUE, priv_list)) {
2053 		priv_master = priv_list[0];
2054 		PRINTM(MINFO, "%s: found dfs_master priv=%p\n", __func__,
2055 		       priv_master);
2056 	}
2057 	if (!priv_master) {
2058 		wlan_11h_check_update_radar_det_state(priv);
2059 		return;
2060 	}
2061 	if (!wlan_11h_is_active(priv_master)) {
2062 		PRINTM(MCMND, "11h: Enable DFS master after STA disconnect\n");
2063 		/* active 11h extention in Fw */
2064 		ret = wlan_11h_activate(priv_master, MNULL, MTRUE);
2065 		ret = wlan_11h_config_master_radar_det(priv_master, MTRUE);
2066 		ret = wlan_11h_check_update_radar_det_state(priv_master);
2067 	}
2068 	if (priv_master->uap_host_based && !pmadapter->init_para.dfs_offload)
2069 		priv_master->intf_state_11h.is_11h_host = MTRUE;
2070 	wlan_11h_set_dfs_check_chan(priv_master, priv_master->uap_channel,
2071 				    priv_master->uap_bandwidth);
2072 	return;
2073 }
2074 #endif
2075 
2076 /**
2077  *  @brief Checks all interfaces and determines if radar_detect flag states
2078  *         have/should be changed.  If so, sends SNMP_MIB 11H command to FW.
2079  *         Call this function on any interface enable/disable/channel change.
2080  *
2081  *  @param pmpriv  Pointer to mlan_private structure
2082  *
2083  *  @return        MLAN_STATUS_SUCCESS (update or not)
2084  *              or MLAN_STATUS_FAILURE (cmd failure)
2085  *
2086  *  @sa    wlan_11h_check_radar_det_state
2087  */
wlan_11h_check_update_radar_det_state(mlan_private * pmpriv)2088 mlan_status wlan_11h_check_update_radar_det_state(mlan_private *pmpriv)
2089 {
2090 	t_u32 new_radar_det_state = 0;
2091 	t_u32 mib_11h = 0;
2092 	mlan_status ret = MLAN_STATUS_SUCCESS;
2093 
2094 	ENTER();
2095 
2096 	if (wlan_11h_check_radar_det_state(pmpriv->adapter,
2097 					   &new_radar_det_state)) {
2098 		PRINTM(MCMD_D, "%s: radar_det_state being updated.\n",
2099 		       __func__);
2100 
2101 		mib_11h |= new_radar_det_state;
2102 		/* keep priv's existing 11h state */
2103 		if (pmpriv->intf_state_11h.is_11h_active)
2104 			mib_11h |= ENABLE_11H_MASK;
2105 
2106 		/* Send cmd to FW to enable/disable 11h function in firmware */
2107 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
2108 				       HostCmd_ACT_GEN_SET, Dot11H_i, MNULL,
2109 				       &mib_11h);
2110 		if (ret)
2111 			ret = MLAN_STATUS_FAILURE;
2112 	}
2113 
2114 	/* updated state sent OR no change, thus no longer pending */
2115 	pmpriv->adapter->state_11h.master_radar_det_enable_pending = MFALSE;
2116 	pmpriv->adapter->state_11h.slave_radar_det_enable_pending = MFALSE;
2117 
2118 	LEAVE();
2119 	return ret;
2120 }
2121 
2122 /**
2123  *  @brief Query 11h firmware enabled state.
2124  *
2125  *  Return whether the firmware currently has 11h extensions enabled
2126  *
2127  *  @param priv  Private driver information structure
2128  *
2129  *  @return
2130  *    - MTRUE if 11h has been activated in the firmware
2131  *    - MFALSE otherwise
2132  *
2133  *  @sa wlan_11h_activate
2134  */
wlan_11h_is_active(mlan_private * priv)2135 t_bool wlan_11h_is_active(mlan_private *priv)
2136 {
2137 	ENTER();
2138 	LEAVE();
2139 	return priv->intf_state_11h.is_11h_active;
2140 }
2141 
2142 /**
2143  *  @brief Enable the transmit interface and record the state.
2144  *
2145  *  @param priv  Private driver information structure
2146  *
2147  *  @return      N/A
2148  */
wlan_11h_tx_enable(mlan_private * priv)2149 t_void wlan_11h_tx_enable(mlan_private *priv)
2150 {
2151 	ENTER();
2152 	if (priv->intf_state_11h.tx_disabled) {
2153 		if (priv->media_connected == MTRUE) {
2154 			wlan_recv_event(priv, MLAN_EVENT_ID_FW_START_TX, MNULL);
2155 			priv->intf_state_11h.tx_disabled = MFALSE;
2156 		}
2157 	}
2158 	LEAVE();
2159 }
2160 
2161 /**
2162  *  @brief Disable the transmit interface and record the state.
2163  *
2164  *  @param priv  Private driver information structure
2165  *
2166  *  @return      N/A
2167  */
wlan_11h_tx_disable(mlan_private * priv)2168 t_void wlan_11h_tx_disable(mlan_private *priv)
2169 {
2170 	ENTER();
2171 	if (!priv->intf_state_11h.tx_disabled) {
2172 		if (priv->media_connected == MTRUE) {
2173 			priv->intf_state_11h.tx_disabled = MTRUE;
2174 			wlan_recv_event(priv, MLAN_EVENT_ID_FW_STOP_TX, MNULL);
2175 		}
2176 	}
2177 	LEAVE();
2178 }
2179 
2180 /**
2181  *  @brief Enable or Disable the 11h extensions in the firmware
2182  *
2183  *  @param priv         Private driver information structure
2184  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
2185  *  @param flag         Enable 11h if MTRUE, disable otherwise
2186  *
2187  *  @return      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2188  */
wlan_11h_activate(mlan_private * priv,t_void * pioctl_buf,t_bool flag)2189 mlan_status wlan_11h_activate(mlan_private *priv, t_void *pioctl_buf,
2190 			      t_bool flag)
2191 {
2192 	t_u32 enable = flag & ENABLE_11H_MASK;
2193 	mlan_status ret = MLAN_STATUS_SUCCESS;
2194 
2195 	ENTER();
2196 	/* add bits for master/slave radar detect into enable. */
2197 	enable |= wlan_11h_get_current_radar_detect_flags(priv->adapter);
2198 
2199 	/* Whenever repeater mode is on make sure
2200 	 * we do not enable master or slave radar det mode.
2201 	 * HW will not detect radar in dfs_repeater mode.
2202 	 */
2203 	if (priv->adapter->dfs_repeater) {
2204 		enable &= ~(MASTER_RADAR_DET_MASK | SLAVE_RADAR_DET_MASK);
2205 	}
2206 
2207 	/*
2208 	 * Send cmd to FW to enable/disable 11h function in firmware
2209 	 */
2210 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
2211 			       HostCmd_ACT_GEN_SET, Dot11H_i,
2212 			       (t_void *)pioctl_buf, &enable);
2213 	if (ret)
2214 		ret = MLAN_STATUS_FAILURE;
2215 	else
2216 		/* Set boolean flag in driver 11h state */
2217 		priv->intf_state_11h.is_11h_active = flag;
2218 
2219 	PRINTM(MINFO, "11h: %s\n", flag ? "Activate" : "Deactivate");
2220 
2221 	LEAVE();
2222 	return ret;
2223 }
2224 
2225 /**
2226  *  @brief Initialize the 11h parameters and enable 11h when starting an IBSS
2227  *
2228  *  @param adapter mlan_adapter structure
2229  *
2230  *  @return      N/A
2231  */
wlan_11h_init(mlan_adapter * adapter)2232 t_void wlan_11h_init(mlan_adapter *adapter)
2233 {
2234 	wlan_11h_device_state_t *pstate_11h = &adapter->state_11h;
2235 	IEEEtypes_Quiet_t *pquiet = &adapter->state_11h.quiet_ie;
2236 	wlan_dfs_device_state_t *pstate_dfs = &adapter->state_dfs;
2237 	wlan_radar_det_hndlg_state_t *pstate_rdh = &adapter->state_rdh;
2238 	wlan_dfs_testing_settings_t *pdfs_test = &adapter->dfs_test_params;
2239 
2240 	ENTER();
2241 
2242 	/* Initialize 11H struct */
2243 	pstate_11h->usr_def_power_constraint = WLAN_11H_TPC_POWERCONSTRAINT;
2244 	pstate_11h->min_tx_power_capability = WLAN_11H_TPC_POWERCAPABILITY_MIN;
2245 	pstate_11h->max_tx_power_capability = WLAN_11H_TPC_POWERCAPABILITY_MAX;
2246 
2247 	pstate_11h->recvd_chanswann_event = MFALSE;
2248 	pstate_11h->master_radar_det_enable_pending = MFALSE;
2249 	pstate_11h->slave_radar_det_enable_pending = MFALSE;
2250 	pstate_11h->is_master_radar_det_active = MFALSE;
2251 	pstate_11h->is_slave_radar_det_active = MFALSE;
2252 
2253 	/*Initialize quiet_ie*/
2254 	memset(adapter, pquiet, 0, sizeof(IEEEtypes_Quiet_t));
2255 	pquiet->element_id = QUIET;
2256 	pquiet->len =
2257 		(sizeof(pquiet->quiet_count) + sizeof(pquiet->quiet_period) +
2258 		 sizeof(pquiet->quiet_duration) + sizeof(pquiet->quiet_offset));
2259 
2260 	/* Initialize DFS struct */
2261 	pstate_dfs->dfs_check_pending = MFALSE;
2262 	pstate_dfs->dfs_radar_found = MFALSE;
2263 	pstate_dfs->dfs_check_channel = 0;
2264 	pstate_dfs->dfs_report_time_sec = 0;
2265 	util_init_list((pmlan_linked_list)&pstate_dfs->dfs_ts_head);
2266 
2267 	/* Initialize RDH struct */
2268 	pstate_rdh->stage = RDH_OFF;
2269 	pstate_rdh->priv_list_count = 0;
2270 	pstate_rdh->priv_curr_idx = 0;
2271 	pstate_rdh->curr_channel = 0;
2272 	pstate_rdh->new_channel = 0;
2273 	memset(adapter, &(pstate_rdh->uap_band_cfg), 0,
2274 	       sizeof(pstate_rdh->uap_band_cfg));
2275 	pstate_rdh->max_bcn_dtim_ms = 0;
2276 	memset(adapter, pstate_rdh->priv_list, 0,
2277 	       sizeof(pstate_rdh->priv_list));
2278 
2279 	/* Initialize dfs channel switch count */
2280 #define DFS_CS_COUNT 5
2281 	adapter->dfs_cs_count = DFS_CS_COUNT;
2282 
2283 	/* Initialize DFS testing struct */
2284 	pdfs_test->user_cac_period_msec = 0;
2285 	pdfs_test->user_nop_period_sec = 0;
2286 	pdfs_test->no_channel_change_on_radar = MFALSE;
2287 	pdfs_test->fixed_new_channel_on_radar = 0;
2288 	pdfs_test->cac_restart = 0;
2289 	pdfs_test->millisec_dwell_time = 0;
2290 	adapter->dfs53cfg = adapter->init_para.dfs53cfg;
2291 
2292 	LEAVE();
2293 }
2294 
2295 /**
2296  *  @brief Cleanup for the 11h parameters that allocated memory, etc.
2297  *
2298  *  @param adapter mlan_adapter structure
2299  *
2300  *  @return      N/A
2301  */
wlan_11h_cleanup(mlan_adapter * adapter)2302 t_void wlan_11h_cleanup(mlan_adapter *adapter)
2303 {
2304 	wlan_dfs_device_state_t *pstate_dfs = &adapter->state_dfs;
2305 	wlan_dfs_timestamp_t *pdfs_ts;
2306 
2307 	ENTER();
2308 
2309 	/* cleanup dfs_timestamp list */
2310 	pdfs_ts = (wlan_dfs_timestamp_t *)util_peek_list(
2311 		adapter->pmoal_handle, &pstate_dfs->dfs_ts_head, MNULL, MNULL);
2312 	while (pdfs_ts) {
2313 		util_unlink_list(adapter->pmoal_handle,
2314 				 &pstate_dfs->dfs_ts_head,
2315 				 (pmlan_linked_list)pdfs_ts, MNULL, MNULL);
2316 		adapter->callbacks.moal_mfree(adapter->pmoal_handle,
2317 					      (t_u8 *)pdfs_ts);
2318 
2319 		pdfs_ts = (wlan_dfs_timestamp_t *)util_peek_list(
2320 			adapter->pmoal_handle, &pstate_dfs->dfs_ts_head, MNULL,
2321 			MNULL);
2322 	}
2323 	LEAVE();
2324 }
2325 
2326 /**
2327  *  @brief Initialize the 11h parameters and enable 11h when starting an IBSS
2328  *
2329  *  @param pmpriv Pointer to mlan_private structure
2330  *
2331  *  @return      N/A
2332  */
wlan_11h_priv_init(mlan_private * pmpriv)2333 t_void wlan_11h_priv_init(mlan_private *pmpriv)
2334 {
2335 	wlan_11h_interface_state_t *pistate_11h = &pmpriv->intf_state_11h;
2336 
2337 	ENTER();
2338 
2339 	pistate_11h->is_11h_enabled = MTRUE;
2340 	pistate_11h->is_11h_active = MFALSE;
2341 	pistate_11h->adhoc_auto_sel_chan = MTRUE;
2342 	pistate_11h->tx_disabled = MFALSE;
2343 	pistate_11h->dfs_slave_csa_chan = 0;
2344 	pistate_11h->dfs_slave_csa_expire_at_sec = 0;
2345 
2346 	LEAVE();
2347 }
2348 
2349 /**
2350  *  @brief Retrieve a randomly selected starting channel if needed for 11h
2351  *
2352  *  If 11h is enabled and an A-Band channel start band preference
2353  *    configured in the driver, the start channel must be random in order
2354  *    to meet with
2355  *
2356  *  @param priv  Private driver information structure
2357  *
2358  *  @return      Starting channel
2359  */
wlan_11h_get_adhoc_start_channel(mlan_private * priv)2360 t_u8 wlan_11h_get_adhoc_start_channel(mlan_private *priv)
2361 {
2362 	t_u8 start_chn;
2363 	mlan_adapter *adapter = priv->adapter;
2364 	t_u32 region;
2365 	t_u32 rand_entry;
2366 	region_chan_t *chn_tbl;
2367 	t_u8 rand_tries = 0;
2368 
2369 	ENTER();
2370 
2371 	/*
2372 	 * Set start_chn to the Default.  Used if 11h is disabled or the band
2373 	 *   does not require 11h support.
2374 	 */
2375 	start_chn = DEFAULT_AD_HOC_CHANNEL;
2376 
2377 	/*
2378 	 * Check that we are looking for a channel in the A Band
2379 	 */
2380 	if ((adapter->adhoc_start_band & BAND_A)) {
2381 		/*
2382 		 * Set default to the A Band default.
2383 		 * Used if random selection fails
2384 		 * or if 11h is not enabled
2385 		 */
2386 		start_chn = DEFAULT_AD_HOC_CHANNEL_A;
2387 
2388 		/*
2389 		 * Check that 11h is enabled in the driver
2390 		 */
2391 		if (wlan_11h_is_enabled(priv)) {
2392 			/*
2393 			 * Search the region_channel tables for a channel table
2394 			 *   that is marked for the A Band.
2395 			 */
2396 			for (region = 0; (region < MAX_REGION_CHANNEL_NUM);
2397 			     region++) {
2398 				chn_tbl = &adapter->region_channel[region];
2399 
2400 				/* Check if table is valid and marked for A Band
2401 				 */
2402 				if (chn_tbl->valid &&
2403 				    chn_tbl->region == adapter->region_code &&
2404 				    chn_tbl->band & BAND_A) {
2405 					/*
2406 					 * Set the start channel.  Get a random
2407 					 * number and use it to pick an entry
2408 					 * in the table between 0 and the number
2409 					 * of channels in the table (NumCFP).
2410 					 */
2411 					do {
2412 						rand_entry =
2413 							wlan_11h_get_random_num(
2414 								adapter) %
2415 							chn_tbl->num_cfp;
2416 						start_chn =
2417 							(t_u8)chn_tbl
2418 								->pcfp[rand_entry]
2419 								.channel;
2420 					} while (
2421 						(wlan_11h_is_channel_under_nop(
2422 							 adapter, start_chn) ||
2423 						 ((adapter->state_rdh.stage ==
2424 						   RDH_GET_INFO_CHANNEL) &&
2425 						  wlan_11h_radar_detect_required(
2426 							  priv, start_chn))) &&
2427 						(++rand_tries <
2428 						 MAX_RANDOM_CHANNEL_RETRIES));
2429 				}
2430 			}
2431 		}
2432 	}
2433 
2434 	PRINTM(MINFO, "11h: %s: AdHoc Channel set to %u\n",
2435 	       wlan_11h_is_enabled(priv) ? "Enabled" : "Disabled", start_chn);
2436 
2437 	LEAVE();
2438 	return start_chn;
2439 }
2440 
2441 /**
2442  *  @brief Retrieve channel closed for operation by Channel Switch Announcement
2443  *
2444  *  After receiving CSA, we must not transmit in any form on the original
2445  *    channel for a certain duration.  This checks the time, and returns
2446  *    the channel if valid.
2447  *
2448  *  @param priv  Private driver information structure
2449  *
2450  *  @return      Closed channel, else 0
2451  */
wlan_11h_get_csa_closed_channel(mlan_private * priv)2452 t_u8 wlan_11h_get_csa_closed_channel(mlan_private *priv)
2453 {
2454 	t_u32 sec, usec;
2455 
2456 	ENTER();
2457 
2458 	if (!priv->intf_state_11h.dfs_slave_csa_chan) {
2459 		LEAVE();
2460 		return 0;
2461 	}
2462 
2463 	/* have csa channel, check if expired or not */
2464 	priv->adapter->callbacks.moal_get_system_time(
2465 		priv->adapter->pmoal_handle, &sec, &usec);
2466 	if (sec > priv->intf_state_11h.dfs_slave_csa_expire_at_sec) {
2467 		/* expired:  remove channel from blacklist table, and clear vars
2468 		 */
2469 		wlan_set_chan_blacklist(priv, BAND_A,
2470 					priv->intf_state_11h.dfs_slave_csa_chan,
2471 					MFALSE);
2472 		priv->intf_state_11h.dfs_slave_csa_chan = 0;
2473 		priv->intf_state_11h.dfs_slave_csa_expire_at_sec = 0;
2474 	}
2475 
2476 	LEAVE();
2477 	return priv->intf_state_11h.dfs_slave_csa_chan;
2478 }
2479 
2480 /**
2481  *  @brief Check if the current region's regulations require the input channel
2482  *         to be scanned for radar.
2483  *
2484  *  Based on statically defined requirements for sub-bands per regulatory
2485  *    agency requirements.
2486  *
2487  *  Used in adhoc start to determine if channel availability check is required
2488  *
2489  *  @param priv    Private driver information structure
2490  *  @param channel Channel to determine radar detection requirements
2491  *
2492  *  @return
2493  *    - MTRUE if radar detection is required
2494  *    - MFALSE otherwise
2495  */
2496 /**  @sa wlan_11h_issue_radar_detect
2497  */
wlan_11h_radar_detect_required(mlan_private * priv,t_u8 channel)2498 t_bool wlan_11h_radar_detect_required(mlan_private *priv, t_u8 channel)
2499 {
2500 	t_bool required = MFALSE;
2501 
2502 	ENTER();
2503 
2504 	/*
2505 	 * No checks for 11h or measurement code being enabled is placed here
2506 	 * since regulatory requirements exist whether we support them or not.
2507 	 */
2508 
2509 	required = wlan_get_cfp_radar_detect(priv, channel);
2510 
2511 	if (!priv->adapter->region_code) {
2512 		PRINTM(MINFO,
2513 		       "11h: Radar detection in CFP code BG:%#x "
2514 		       ", A:%#x "
2515 		       "is %srequired for channel %d\n",
2516 		       priv->adapter->cfp_code_bg, priv->adapter->cfp_code_a,
2517 		       (required ? "" : "not "), channel);
2518 	} else
2519 		PRINTM(MINFO,
2520 		       "11h: Radar detection in region %#02x "
2521 		       "is %srequired for channel %d\n",
2522 		       priv->adapter->region_code, (required ? "" : "not "),
2523 		       channel);
2524 
2525 	if (required == MTRUE && priv->media_connected == MTRUE &&
2526 	    priv->curr_bss_params.bss_descriptor.channel == channel) {
2527 		required = MFALSE;
2528 
2529 		PRINTM(MINFO, "11h: Radar detection not required. "
2530 			      "Already operating on the channel\n");
2531 	}
2532 
2533 	LEAVE();
2534 	return required;
2535 }
2536 
wlan_11h_cancel_radar_detect(mlan_private * priv)2537 t_s32 wlan_11h_cancel_radar_detect(mlan_private *priv)
2538 {
2539 	t_s32 ret;
2540 	HostCmd_DS_CHAN_RPT_REQ chan_rpt_req;
2541 	memset(priv->adapter, &chan_rpt_req, 0x00, sizeof(chan_rpt_req));
2542 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
2543 			       HostCmd_ACT_GEN_SET, 0, (t_void *)MNULL,
2544 			       (t_void *)&chan_rpt_req);
2545 	return ret;
2546 }
2547 
2548 /**
2549  *  @brief Perform a radar measurement if required on given channel
2550  *
2551  *  Check to see if the provided channel requires a channel availability
2552  *    check (60 second radar detection measurement).  If required, perform
2553  *    measurement, stalling calling thread until the measurement completes
2554  *    and then report result.
2555  *
2556  *  Used when starting an adhoc or AP network.
2557  *
2558  *  @param priv         Private driver information structure
2559  *  @param pioctl_req   Pointer to IOCTL request buffer
2560  *  @param channel      Channel on which to perform radar measurement
2561  *  @param bandcfg      Channel Band config structure
2562  *
2563  *  @return
2564  *    - MTRUE  if radar measurement request was successfully issued
2565  *    - MFALSE if radar detection is not required
2566  *    - < 0 for error during radar detection (if performed)
2567  *
2568  *  @sa wlan_11h_radar_detect_required
2569  */
wlan_11h_issue_radar_detect(mlan_private * priv,pmlan_ioctl_req pioctl_req,t_u8 channel,Band_Config_t bandcfg)2570 t_s32 wlan_11h_issue_radar_detect(mlan_private *priv,
2571 				  pmlan_ioctl_req pioctl_req, t_u8 channel,
2572 				  Band_Config_t bandcfg)
2573 {
2574 	t_s32 ret;
2575 	HostCmd_DS_CHAN_RPT_REQ chan_rpt_req;
2576 	mlan_adapter *pmadapter = priv->adapter;
2577 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
2578 
2579 	ENTER();
2580 
2581 	ret = wlan_11h_radar_detect_required(priv, channel);
2582 	if (ret) {
2583 		/* Prepare and issue CMD_CHAN_RPT_REQ. */
2584 		memset(priv->adapter, &chan_rpt_req, 0x00,
2585 		       sizeof(chan_rpt_req));
2586 
2587 		chan_rpt_req.chan_desc.startFreq = START_FREQ_11A_BAND;
2588 
2589 		if (pmadapter->chanrpt_param_bandcfg) {
2590 			chan_rpt_req.chan_desc.bandcfg = bandcfg;
2591 		} else {
2592 			*((t_u8 *)&chan_rpt_req.chan_desc.bandcfg) =
2593 				(t_u8)bandcfg.chanWidth;
2594 		}
2595 
2596 		chan_rpt_req.chan_desc.chanNum = channel;
2597 		chan_rpt_req.millisec_dwell_time =
2598 			WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION;
2599 
2600 		/* ETSI new requirement for ch 120, 124 and 128 */
2601 		if (wlan_is_etsi_country(pmadapter, pmadapter->country_code)) {
2602 			if (channel == 120 || channel == 124 ||
2603 			    channel == 128) {
2604 				chan_rpt_req.millisec_dwell_time =
2605 					WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION *
2606 					10;
2607 			}
2608 			if (channel == 116 &&
2609 			    ((bandcfg.chanWidth == CHAN_BW_40MHZ) ||
2610 			     (bandcfg.chanWidth == CHAN_BW_80MHZ))) {
2611 				chan_rpt_req.millisec_dwell_time =
2612 					WLAN_11H_CHANNEL_AVAIL_CHECK_DURATION *
2613 					10;
2614 			}
2615 		}
2616 
2617 		/* Save dwell time information to be used later in moal */
2618 		if (pioctl_req) {
2619 			ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
2620 			if (!ds_11hcfg->param.chan_rpt_req.host_based) {
2621 				ds_11hcfg->param.chan_rpt_req
2622 					.millisec_dwell_time =
2623 					chan_rpt_req.millisec_dwell_time;
2624 			}
2625 		}
2626 
2627 		if (priv->adapter->dfs_test_params.user_cac_period_msec) {
2628 			PRINTM(MCMD_D,
2629 			       "dfs_testing - user CAC period=%d (msec)\n",
2630 			       priv->adapter->dfs_test_params
2631 				       .user_cac_period_msec);
2632 			chan_rpt_req.millisec_dwell_time =
2633 				priv->adapter->dfs_test_params
2634 					.user_cac_period_msec;
2635 		}
2636 		if (priv->adapter->dfs_test_params.cac_restart) {
2637 			priv->adapter->dfs_test_params.chan =
2638 				chan_rpt_req.chan_desc.chanNum;
2639 			if (chan_rpt_req.millisec_dwell_time)
2640 				priv->adapter->dfs_test_params
2641 					.millisec_dwell_time =
2642 					chan_rpt_req.millisec_dwell_time;
2643 			else
2644 				chan_rpt_req.millisec_dwell_time =
2645 					priv->adapter->dfs_test_params
2646 						.millisec_dwell_time;
2647 			memcpy_ext(priv->adapter,
2648 				   &priv->adapter->dfs_test_params.bandcfg,
2649 				   &bandcfg, sizeof(bandcfg), sizeof(bandcfg));
2650 		}
2651 		PRINTM(MMSG,
2652 		       "11h: issuing DFS Radar check for channel=%d."
2653 		       "  Please wait for response...\n",
2654 		       channel);
2655 
2656 		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
2657 				       HostCmd_ACT_GEN_SET, 0,
2658 				       (t_void *)pioctl_req,
2659 				       (t_void *)&chan_rpt_req);
2660 	}
2661 
2662 	LEAVE();
2663 	return ret;
2664 }
2665 
2666 /**
2667  *  @brief Checks if a radar measurement was performed on channel,
2668  *         and if so, whether radar was detected on it.
2669  *
2670  *  Used when starting an adhoc network.
2671  *
2672  *  @param priv         Private driver information structure
2673  *  @param chan         Channel to check upon
2674  *
2675  *  @return
2676  *    - MLAN_STATUS_SUCCESS if no radar on channel
2677  *    - MLAN_STATUS_FAILURE if radar was found on channel
2678  *    - (TBD??) MLAN_STATUS_PENDING if radar report NEEDS TO BE REISSUED
2679  *
2680  *  @sa wlan_11h_issue_radar_detect
2681  *  @sa wlan_11h_process_start
2682  */
wlan_11h_check_chan_report(mlan_private * priv,t_u8 chan)2683 mlan_status wlan_11h_check_chan_report(mlan_private *priv, t_u8 chan)
2684 {
2685 	mlan_status ret = MLAN_STATUS_SUCCESS;
2686 	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
2687 	t_u32 sec, usec;
2688 
2689 	ENTER();
2690 
2691 	/* check report we hold is valid or not */
2692 	priv->adapter->callbacks.moal_get_system_time(
2693 		priv->adapter->pmoal_handle, &sec, &usec);
2694 
2695 	PRINTM(MINFO, "11h: %s()\n", __func__);
2696 	PRINTM(MINFO, "- sec_now=%d, sec_report=%d.\n", sec,
2697 	       pstate_dfs->dfs_report_time_sec);
2698 	PRINTM(MINFO, "- rpt_channel=%d, rpt_radar=%d.\n",
2699 	       pstate_dfs->dfs_check_channel, pstate_dfs->dfs_radar_found);
2700 
2701 	if ((!pstate_dfs->dfs_check_pending) &&
2702 	    (chan == pstate_dfs->dfs_check_channel) &&
2703 	    ((sec - pstate_dfs->dfs_report_time_sec) <
2704 	     MAX_DFS_REPORT_USABLE_AGE_SEC)) {
2705 		/* valid and not out-dated, check if radar */
2706 		if (pstate_dfs->dfs_radar_found) {
2707 			PRINTM(MMSG, "Radar was detected on channel %d.\n",
2708 			       chan);
2709 			ret = MLAN_STATUS_FAILURE;
2710 		}
2711 	} else {
2712 		/* When Cache is not valid. This is required during extending
2713 		 * cache validity during bss_stop
2714 		 */
2715 		pstate_dfs->dfs_check_channel = 0;
2716 
2717 		/*TODO:  reissue report request if not pending.
2718 		 *       BUT HOW to make the code wait for it???
2719 		 * For now, just fail since we don't have the info. */
2720 
2721 		ret = MLAN_STATUS_PENDING;
2722 	}
2723 
2724 	LEAVE();
2725 	return ret;
2726 }
2727 
2728 /**
2729  *  @brief Process an TLV buffer for a pending BSS Adhoc start command.
2730  *
2731  *  Activate 11h functionality in the firmware if driver has is enabled
2732  *    for 11h (configured by the application via IOCTL).
2733  *
2734  *  @param priv          Private driver information structure
2735  *  @param ppbuffer      Output parameter: Pointer to the TLV output buffer,
2736  *                       modified on return to point after the appended 11h TLVs
2737  *  @param pcap_info     Pointer to the capability info for the BSS to join
2738  *  @param channel       Channel on which we are starting the IBSS
2739  *  @param p11h_bss_info Input/Output parameter: Pointer to the 11h BSS
2740  *                       information for this network that we are establishing.
2741  *                       11h sensed flag set on output if warranted.
2742  *
2743  *  @return
2744  *      - MLAN_STATUS_SUCCESS if 11h is disabled
2745  *      - Integer number of bytes appended to the TLV output buffer (ppbuffer)
2746  *      - < 0 for error (e.g. radar detected on channel)
2747  */
wlan_11h_process_start(mlan_private * priv,t_u8 ** ppbuffer,IEEEtypes_CapInfo_t * pcap_info,t_u32 channel,wlan_11h_bss_info_t * p11h_bss_info)2748 t_s32 wlan_11h_process_start(mlan_private *priv, t_u8 **ppbuffer,
2749 			     IEEEtypes_CapInfo_t *pcap_info, t_u32 channel,
2750 			     wlan_11h_bss_info_t *p11h_bss_info)
2751 {
2752 	mlan_adapter *adapter = priv->adapter;
2753 	t_s32 ret = MLAN_STATUS_SUCCESS;
2754 	t_bool is_dfs_chan = MFALSE;
2755 
2756 	ENTER();
2757 	if (wlan_11h_is_enabled(priv) &&
2758 	    ((adapter->adhoc_start_band & BAND_A))) {
2759 		if (!wlan_fw_11d_is_enabled(priv)) {
2760 			/* No use having 11h enabled without 11d enabled */
2761 			if (wlan_11d_enable(priv, MNULL, ENABLE_11D)) {
2762 				ret = MLAN_STATUS_FAILURE;
2763 				LEAVE();
2764 				return ret;
2765 			}
2766 #ifdef STA_SUPPORT
2767 			wlan_11d_create_dnld_countryinfo(
2768 				priv, adapter->adhoc_start_band);
2769 #endif
2770 		}
2771 
2772 		/*
2773 		 * Activate 11h functions in firmware,
2774 		 * turns on capability bit
2775 		 */
2776 		wlan_11h_activate(priv, MNULL, MTRUE);
2777 		pcap_info->spectrum_mgmt = MTRUE;
2778 
2779 		/* If using a DFS channel, enable radar detection. */
2780 		is_dfs_chan = wlan_11h_radar_detect_required(priv, channel);
2781 		if (is_dfs_chan) {
2782 			if (!wlan_11h_is_master_radar_det_active(priv))
2783 				wlan_11h_config_master_radar_det(priv, MTRUE);
2784 		}
2785 		wlan_11h_check_update_radar_det_state(priv);
2786 
2787 		/* Set flag indicating this BSS we are starting is using 11h */
2788 		p11h_bss_info->sensed_11h = MTRUE;
2789 
2790 		if (is_dfs_chan) {
2791 			/* check if this channel is under NOP */
2792 			if (wlan_11h_is_channel_under_nop(adapter, channel))
2793 				ret = MLAN_STATUS_FAILURE;
2794 			/* check last channel report, if this channel is free of
2795 			 * radar */
2796 			if (ret == MLAN_STATUS_SUCCESS)
2797 				ret = wlan_11h_check_chan_report(priv, channel);
2798 		}
2799 		if (ret == MLAN_STATUS_SUCCESS)
2800 			ret = wlan_11h_process_adhoc(priv, ppbuffer, channel,
2801 						     MNULL);
2802 		else
2803 			ret = MLAN_STATUS_FAILURE;
2804 	} else {
2805 		/* Deactivate 11h functions in the firmware */
2806 		wlan_11h_activate(priv, MNULL, MFALSE);
2807 		pcap_info->spectrum_mgmt = MFALSE;
2808 		wlan_11h_check_update_radar_det_state(priv);
2809 	}
2810 	LEAVE();
2811 	return ret;
2812 }
2813 
2814 /**
2815  *  @brief Process an TLV buffer for a pending BSS Join command for
2816  *         both adhoc and infra networks
2817  *
2818  *  The TLV command processing for a BSS join for either adhoc or
2819  *    infrastructure network is performed with this function.  The
2820  *    capability bits are inspected for the IBSS flag and the appropriate
2821  *    local routines are called to setup the necessary TLVs.
2822  *
2823  *  Activate 11h functionality in the firmware if the spectrum management
2824  *    capability bit is found in the network information for the BSS we are
2825  *    joining.
2826  *
2827  *  @param priv          Private driver information structure
2828  *  @param ppbuffer      Output parameter: Pointer to the TLV output buffer,
2829  *                       modified on return to point after the appended 11h TLVs
2830  *  @param pcap_info     Pointer to the capability info for the BSS to join
2831  *  @param band          Band on which we are joining the BSS
2832  *  @param channel       Channel on which we are joining the BSS
2833  *  @param p11h_bss_info Pointer to the 11h BSS information for this
2834  *                       network that was parsed out of the scan response.
2835  *
2836  *  @return              Integer number of bytes appended to the TLV output
2837  *                       buffer (ppbuffer)
2838  */
wlan_11h_process_join(mlan_private * priv,t_u8 ** ppbuffer,IEEEtypes_CapInfo_t * pcap_info,t_u16 band,t_u32 channel,wlan_11h_bss_info_t * p11h_bss_info)2839 t_s32 wlan_11h_process_join(mlan_private *priv, t_u8 **ppbuffer,
2840 			    IEEEtypes_CapInfo_t *pcap_info, t_u16 band,
2841 			    t_u32 channel, wlan_11h_bss_info_t *p11h_bss_info)
2842 {
2843 	t_s32 ret = 0;
2844 
2845 	ENTER();
2846 
2847 	if (priv->media_connected == MTRUE) {
2848 		if (wlan_11h_is_active(priv) == p11h_bss_info->sensed_11h) {
2849 			/*
2850 			 * Assume DFS parameters are the same for roaming as
2851 			 * long as the current & next APs have the same spectrum
2852 			 * mgmt capability bit setting
2853 			 */
2854 			PRINTM(MINFO,
2855 			       "Assume DFS parameters are the same for roaming\n");
2856 		} else {
2857 			/* No support for roaming between DFS/non-DFS yet */
2858 			PRINTM(MINFO,
2859 			       "No support for roaming between DFS/non-DFS yet\n");
2860 		}
2861 
2862 		LEAVE();
2863 		return ret;
2864 	}
2865 
2866 	if (p11h_bss_info->sensed_11h) {
2867 		if (!wlan_fw_11d_is_enabled(priv)) {
2868 			/* No use having 11h enabled without 11d enabled */
2869 			if (wlan_11d_enable(priv, MNULL, ENABLE_11D)) {
2870 				PRINTM(MERROR, "Fail to enable 11D\n");
2871 				LEAVE();
2872 				return ret;
2873 			}
2874 #ifdef STA_SUPPORT
2875 			wlan_11d_parse_dnld_countryinfo(
2876 				priv, priv->pattempted_bss_desc);
2877 #endif
2878 		}
2879 		/*
2880 		 * Activate 11h functions in firmware,
2881 		 * turns on capability bit
2882 		 */
2883 		wlan_11h_activate(priv, MNULL, MTRUE);
2884 		pcap_info->spectrum_mgmt = MTRUE;
2885 
2886 		/* If using a DFS channel, enable radar detection. */
2887 		if ((band & BAND_A) &&
2888 		    wlan_11h_radar_detect_required(priv, channel)) {
2889 			if (!wlan_11h_is_slave_radar_det_active(priv))
2890 				wlan_11h_config_slave_radar_det(priv, MTRUE);
2891 		}
2892 		wlan_11h_check_update_radar_det_state(priv);
2893 
2894 		if (pcap_info->ibss) {
2895 			PRINTM(MINFO, "11h: Adhoc join: Sensed\n");
2896 			ret = wlan_11h_process_adhoc(priv, ppbuffer, channel,
2897 						     p11h_bss_info);
2898 		} else {
2899 			PRINTM(MINFO, "11h: Infra join: Sensed\n");
2900 			ret = wlan_11h_process_infra_join(
2901 				priv, ppbuffer, band, channel, p11h_bss_info);
2902 		}
2903 	} else {
2904 		if (pcap_info->ibss) {
2905 			/* Deactivate 11h functions in the firmware */
2906 			wlan_11h_activate(priv, MNULL, MFALSE);
2907 			pcap_info->spectrum_mgmt = MFALSE;
2908 			wlan_11h_check_update_radar_det_state(priv);
2909 		}
2910 	}
2911 
2912 	LEAVE();
2913 	return ret;
2914 }
2915 
2916 /**
2917  *
2918  *  @brief  Prepare the HostCmd_DS_Command structure for an 11h command.
2919  *
2920  *  Use the Command field to determine if the command being set up is for
2921  *     11h and call one of the local command handlers accordingly for:
2922  *
2923  *        - HostCmd_CMD_802_11_TPC_ADAPT_REQ
2924  *        - HostCmd_CMD_802_11_TPC_INFO
2925  *        - HostCmd_CMD_802_11_CHAN_SW_ANN
2926  */
2927 /**       - HostCmd_CMD_CHAN_REPORT_REQUEST
2928  */
2929 /**
2930  *  @param priv      Private driver information structure
2931  *  @param pcmd_ptr  Output parameter: Pointer to the command being prepared
2932  *                   for the firmware
2933  *  @param pinfo_buf Void buffer pass through with data necessary for a
2934  *                   specific command type
2935  */
2936 /**  @return          MLAN_STATUS_SUCCESS, MLAN_STATUS_FAILURE
2937  *                    or MLAN_STATUS_PENDING
2938  */
2939 /**  @sa wlan_11h_cmd_tpc_request
2940  *  @sa wlan_11h_cmd_tpc_info
2941  *  @sa wlan_11h_cmd_chan_sw_ann
2942  */
2943 /** @sa wlan_11h_cmd_chan_report_req
2944  */
wlan_11h_cmd_process(mlan_private * priv,HostCmd_DS_COMMAND * pcmd_ptr,const t_void * pinfo_buf)2945 mlan_status wlan_11h_cmd_process(mlan_private *priv,
2946 				 HostCmd_DS_COMMAND *pcmd_ptr,
2947 				 const t_void *pinfo_buf)
2948 {
2949 	mlan_status ret = MLAN_STATUS_SUCCESS;
2950 
2951 	ENTER();
2952 	switch (pcmd_ptr->command) {
2953 	case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
2954 		ret = wlan_11h_cmd_tpc_request(priv, pcmd_ptr, pinfo_buf);
2955 		break;
2956 	case HostCmd_CMD_802_11_TPC_INFO:
2957 		ret = wlan_11h_cmd_tpc_info(priv, pcmd_ptr, pinfo_buf);
2958 		break;
2959 	case HostCmd_CMD_802_11_CHAN_SW_ANN:
2960 		ret = wlan_11h_cmd_chan_sw_ann(priv, pcmd_ptr, pinfo_buf);
2961 		break;
2962 	case HostCmd_CMD_CHAN_REPORT_REQUEST:
2963 		ret = wlan_11h_cmd_chan_rpt_req(priv, pcmd_ptr, pinfo_buf);
2964 		break;
2965 	default:
2966 		ret = MLAN_STATUS_FAILURE;
2967 	}
2968 
2969 	pcmd_ptr->command = wlan_cpu_to_le16(pcmd_ptr->command);
2970 	pcmd_ptr->size = wlan_cpu_to_le16(pcmd_ptr->size);
2971 
2972 	LEAVE();
2973 	return ret;
2974 }
2975 
2976 /**
2977  *  @brief Handle the command response from the firmware if from an 11h command
2978  *
2979  *  Use the Command field to determine if the command response being
2980  *    is for 11h.  Call the local command response handler accordingly for:
2981  *
2982  *        - HostCmd_CMD_802_11_TPC_ADAPT_REQ
2983  *        - HostCmd_CMD_802_11_TPC_INFO
2984  *        - HostCmd_CMD_802_11_CHAN_SW_ANN
2985  */
2986 /**       - HostCmd_CMD_CHAN_REPORT_REQUEST
2987  */
2988 /**
2989  *  @param priv  Private driver information structure
2990  *  @param resp  HostCmd_DS_COMMAND struct returned from the firmware
2991  *               command
2992  *
2993  *  @return      MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2994  */
wlan_11h_cmdresp_process(mlan_private * priv,const HostCmd_DS_COMMAND * resp)2995 mlan_status wlan_11h_cmdresp_process(mlan_private *priv,
2996 				     const HostCmd_DS_COMMAND *resp)
2997 {
2998 	mlan_status ret = MLAN_STATUS_SUCCESS;
2999 
3000 	ENTER();
3001 	switch (resp->command) {
3002 	case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
3003 		HEXDUMP("11h: TPC REQUEST Rsp:", (t_u8 *)resp,
3004 			(t_u32)resp->size);
3005 		memcpy_ext(priv->adapter, priv->adapter->curr_cmd->pdata_buf,
3006 			   &resp->params.tpc_req,
3007 			   sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ),
3008 			   sizeof(HostCmd_DS_802_11_TPC_ADAPT_REQ));
3009 		break;
3010 
3011 	case HostCmd_CMD_802_11_TPC_INFO:
3012 		HEXDUMP("11h: TPC INFO Rsp Data:", (t_u8 *)resp,
3013 			(t_u32)resp->size);
3014 		break;
3015 
3016 	case HostCmd_CMD_802_11_CHAN_SW_ANN:
3017 		PRINTM(MINFO, "11h: Ret ChSwAnn: Sz=%u, Seq=%u, Ret=%u\n",
3018 		       resp->size, resp->seq_num, resp->result);
3019 		break;
3020 
3021 	case HostCmd_CMD_CHAN_REPORT_REQUEST:
3022 		if (priv->bss_type == MLAN_BSS_TYPE_DFS)
3023 			break;
3024 		priv->adapter->state_dfs.dfs_check_priv = priv;
3025 		priv->adapter->state_dfs.dfs_check_pending = MTRUE;
3026 
3027 		if (resp->params.chan_rpt_req.millisec_dwell_time == 0) {
3028 			/* from wlan_11h_ioctl_dfs_chan_report */
3029 			priv->adapter->state_dfs.dfs_check_pending = MFALSE;
3030 			priv->adapter->state_dfs.dfs_check_priv = MNULL;
3031 			priv->adapter->state_dfs.dfs_check_channel = 0;
3032 			PRINTM(MINFO, "11h: Cancelling Chan Report \n");
3033 		} else {
3034 			PRINTM(MERROR,
3035 			       "11h: Ret ChanRptReq.  Set dfs_check_pending and wait"
3036 			       " for EVENT_CHANNEL_REPORT.\n");
3037 		}
3038 
3039 		break;
3040 
3041 	default:
3042 		ret = MLAN_STATUS_FAILURE;
3043 	}
3044 
3045 	LEAVE();
3046 	return ret;
3047 }
3048 
3049 /**
3050  *  @brief Process an element from a scan response, copy relevant info for 11h
3051  *
3052  *  @param pmadapter Pointer to mlan_adapter
3053  *  @param p11h_bss_info Output parameter: Pointer to the 11h BSS information
3054  *                       for the network that is being processed
3055  *  @param pelement      Pointer to the current IE we are inspecting for 11h
3056  *                       relevance
3057  *
3058  *  @return              MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3059  */
wlan_11h_process_bss_elem(mlan_adapter * pmadapter,wlan_11h_bss_info_t * p11h_bss_info,const t_u8 * pelement)3060 mlan_status wlan_11h_process_bss_elem(mlan_adapter *pmadapter,
3061 				      wlan_11h_bss_info_t *p11h_bss_info,
3062 				      const t_u8 *pelement)
3063 {
3064 	mlan_status ret = MLAN_STATUS_SUCCESS;
3065 	t_u8 element_len = *((t_u8 *)pelement + 1);
3066 
3067 	ENTER();
3068 	switch (*pelement) {
3069 	case POWER_CONSTRAINT:
3070 		PRINTM(MINFO, "11h: Power Constraint IE Found\n");
3071 		p11h_bss_info->sensed_11h = MTRUE;
3072 		memcpy_ext(pmadapter, &p11h_bss_info->power_constraint,
3073 			   pelement, element_len + sizeof(IEEEtypes_Header_t),
3074 			   sizeof(IEEEtypes_PowerConstraint_t));
3075 		p11h_bss_info->power_constraint.len =
3076 			MIN(element_len, (sizeof(IEEEtypes_PowerConstraint_t) -
3077 					  sizeof(IEEEtypes_Header_t)));
3078 		break;
3079 
3080 	case POWER_CAPABILITY:
3081 		PRINTM(MINFO, "11h: Power Capability IE Found\n");
3082 		p11h_bss_info->sensed_11h = MTRUE;
3083 		memcpy_ext(pmadapter, &p11h_bss_info->power_capability,
3084 			   pelement, element_len + sizeof(IEEEtypes_Header_t),
3085 			   sizeof(IEEEtypes_PowerCapability_t));
3086 		p11h_bss_info->power_capability.len =
3087 			MIN(element_len, (sizeof(IEEEtypes_PowerCapability_t) -
3088 					  sizeof(IEEEtypes_Header_t)));
3089 		break;
3090 
3091 	case TPC_REPORT:
3092 		PRINTM(MINFO, "11h: Tpc Report IE Found\n");
3093 		p11h_bss_info->sensed_11h = MTRUE;
3094 		memcpy_ext(pmadapter, &p11h_bss_info->tpc_report, pelement,
3095 			   element_len + sizeof(IEEEtypes_Header_t),
3096 			   sizeof(IEEEtypes_TPCReport_t));
3097 		p11h_bss_info->tpc_report.len =
3098 			MIN(element_len, (sizeof(IEEEtypes_TPCReport_t) -
3099 					  sizeof(IEEEtypes_Header_t)));
3100 		break;
3101 
3102 	case CHANNEL_SWITCH_ANN:
3103 		PRINTM(MINFO, "11h: Channel Switch Ann IE Found\n");
3104 		p11h_bss_info->sensed_11h = MTRUE;
3105 		memcpy_ext(pmadapter, &p11h_bss_info->chan_switch_ann, pelement,
3106 			   element_len + sizeof(IEEEtypes_Header_t),
3107 			   sizeof(IEEEtypes_ChanSwitchAnn_t));
3108 		p11h_bss_info->chan_switch_ann.len =
3109 			MIN(element_len, (sizeof(IEEEtypes_ChanSwitchAnn_t) -
3110 					  sizeof(IEEEtypes_Header_t)));
3111 		break;
3112 
3113 	case QUIET:
3114 		PRINTM(MINFO, "11h: Quiet IE Found\n");
3115 		p11h_bss_info->sensed_11h = MTRUE;
3116 		memcpy_ext(pmadapter, &p11h_bss_info->quiet, pelement,
3117 			   element_len + sizeof(IEEEtypes_Header_t),
3118 			   sizeof(IEEEtypes_Quiet_t));
3119 		p11h_bss_info->quiet.len =
3120 			MIN(element_len, (sizeof(IEEEtypes_Quiet_t) -
3121 					  sizeof(IEEEtypes_Header_t)));
3122 		break;
3123 
3124 	case IBSS_DFS:
3125 		PRINTM(MINFO, "11h: Ibss Dfs IE Found\n");
3126 		p11h_bss_info->sensed_11h = MTRUE;
3127 		memcpy_ext(pmadapter, &p11h_bss_info->ibss_dfs, pelement,
3128 			   element_len + sizeof(IEEEtypes_Header_t),
3129 			   sizeof(IEEEtypes_IBSS_DFS_t));
3130 		p11h_bss_info->ibss_dfs.len =
3131 			MIN(element_len, (sizeof(IEEEtypes_IBSS_DFS_t) -
3132 					  sizeof(IEEEtypes_Header_t)));
3133 		break;
3134 
3135 	case SUPPORTED_CHANNELS:
3136 	case TPC_REQUEST:
3137 		/*
3138 		 * These elements are not in beacons/probe responses.
3139 		 * Included here to cover set of enumerated 11h elements.
3140 		 */
3141 		break;
3142 
3143 	default:
3144 		ret = MLAN_STATUS_FAILURE;
3145 	}
3146 
3147 	LEAVE();
3148 	return ret;
3149 }
3150 
3151 /**
3152  *  @brief Driver handling for CHANNEL_SWITCH_ANN event
3153  *
3154  *  @param priv Pointer to mlan_private
3155  *
3156  *  @return MLAN_STATUS_SUCCESS, MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
3157  */
wlan_11h_handle_event_chanswann(mlan_private * priv)3158 mlan_status wlan_11h_handle_event_chanswann(mlan_private *priv)
3159 {
3160 	mlan_status ret = MLAN_STATUS_SUCCESS;
3161 #ifdef STA_SUPPORT
3162 	mlan_deauth_param deauth_param;
3163 #endif
3164 	t_u32 sec, usec;
3165 #ifdef UAP_SUPPORT
3166 	mlan_adapter *pmadapter = priv->adapter;
3167 	int i;
3168 	t_u8 radar_detected = MFALSE;
3169 	mlan_private *pmpriv = MNULL;
3170 #endif
3171 
3172 	ENTER();
3173 #ifdef UAP_SUPPORT
3174 	if (priv->adapter->state_11h.is_master_radar_det_active) {
3175 		for (i = 0; i < MIN(pmadapter->priv_num, MLAN_MAX_BSS_NUM);
3176 		     i++) {
3177 			if (pmadapter->priv[i] &&
3178 			    (pmadapter->priv[i]->bss_role ==
3179 			     MLAN_BSS_ROLE_UAP) &&
3180 			    pmadapter->priv[i]->uap_bss_started &&
3181 			    (priv->curr_bss_params.bss_descriptor.channel ==
3182 			     pmadapter->priv[i]->uap_channel)) {
3183 				PRINTM(MCMND,
3184 				       "Receive channel switch Ann event on uap_channel=%d\n",
3185 				       pmadapter->priv[i]->uap_channel);
3186 				radar_detected = MTRUE;
3187 				pmpriv = pmadapter->priv[i];
3188 				break;
3189 			}
3190 		}
3191 		if (radar_detected) {
3192 			if (!pmpriv->intf_state_11h.is_11h_host) {
3193 				if (pmadapter->state_rdh.stage == RDH_OFF) {
3194 					pmadapter->state_rdh.stage =
3195 						RDH_CHK_INTFS;
3196 					wlan_11h_radar_detected_handling(
3197 						pmadapter, pmpriv);
3198 					if (pmpriv->uap_host_based)
3199 						wlan_recv_event(
3200 							pmpriv,
3201 							MLAN_EVENT_ID_FW_RADAR_DETECTED,
3202 							MNULL);
3203 				} else {
3204 					PRINTM(MEVENT,
3205 					       "Ignore Event Radar Detected - handling already in progress.\n");
3206 				}
3207 			} else {
3208 				if (pmpriv->adapter->dfs_test_params
3209 					    .no_channel_change_on_radar ||
3210 				    pmpriv->adapter->dfs_test_params
3211 					    .fixed_new_channel_on_radar) {
3212 					if (pmadapter->state_rdh.stage ==
3213 						    RDH_OFF ||
3214 					    pmadapter->state_rdh.stage ==
3215 						    RDH_SET_CUSTOM_IE) {
3216 						pmadapter->state_rdh.stage =
3217 							RDH_CHK_INTFS;
3218 						wlan_11h_radar_detected_handling(
3219 							pmadapter, pmpriv);
3220 					} else
3221 						PRINTM(MEVENT,
3222 						       "Ignore Event Radar Detected - handling already in progress.\n");
3223 				} else {
3224 					pmpriv->intf_state_11h.tx_disabled =
3225 						MTRUE;
3226 					wlan_recv_event(
3227 						pmpriv,
3228 						MLAN_EVENT_ID_FW_RADAR_DETECTED,
3229 						MNULL);
3230 				}
3231 			}
3232 		}
3233 	}
3234 #endif /* UAP_SUPPORT */
3235 	if (priv->adapter->ecsa_enable) {
3236 		t_u8 stop_tx = *(t_u8 *)priv->adapter->event_body;
3237 		if (stop_tx)
3238 			priv->adapter->state_rdh.tx_block = MTRUE;
3239 		LEAVE();
3240 		return ret;
3241 	}
3242 	priv->adapter->state_11h.recvd_chanswann_event = MTRUE;
3243 
3244 	/* unlikely:  clean up previous csa if still on-going */
3245 	if (priv->intf_state_11h.dfs_slave_csa_chan) {
3246 		wlan_set_chan_blacklist(priv, BAND_A,
3247 					priv->intf_state_11h.dfs_slave_csa_chan,
3248 					MFALSE);
3249 	}
3250 
3251 	/* record channel and time of occurence */
3252 	priv->intf_state_11h.dfs_slave_csa_chan =
3253 		priv->curr_bss_params.bss_descriptor.channel;
3254 	priv->adapter->callbacks.moal_get_system_time(
3255 		priv->adapter->pmoal_handle, &sec, &usec);
3256 	priv->intf_state_11h.dfs_slave_csa_expire_at_sec =
3257 		sec + DFS_CHAN_MOVE_TIME;
3258 
3259 #ifdef STA_SUPPORT
3260 	/* do directed deauth.  recvd_chanswann_event flag will cause different
3261 	 * reason code */
3262 	PRINTM(MINFO, "11h: handle_event_chanswann() - sending deauth\n");
3263 	memcpy_ext(priv->adapter, deauth_param.mac_addr,
3264 		   &priv->curr_bss_params.bss_descriptor.mac_address,
3265 		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
3266 	deauth_param.reason_code = DEF_DEAUTH_REASON_CODE;
3267 	ret = wlan_disconnect(priv, MNULL, &deauth_param);
3268 
3269 	/* clear region table so next scan will be all passive */
3270 	PRINTM(MINFO, "11h: handle_event_chanswann() - clear region table\n");
3271 	wlan_11d_clear_parsedtable(priv);
3272 
3273 	/* add channel to blacklist table */
3274 	PRINTM(MINFO,
3275 	       "11h: handle_event_chanswann() - scan blacklist csa channel\n");
3276 	wlan_set_chan_blacklist(priv, BAND_A,
3277 				priv->intf_state_11h.dfs_slave_csa_chan, MTRUE);
3278 #endif /* STA_SUPPORT */
3279 
3280 	priv->adapter->state_11h.recvd_chanswann_event = MFALSE;
3281 	LEAVE();
3282 	return ret;
3283 }
3284 
3285 /**
3286  *  @brief 802.11h DFS Testing configuration
3287  *
3288  *  @param pmadapter    Pointer to mlan_adapter
3289  *  @param pioctl_req   Pointer to mlan_ioctl_req
3290  *
3291  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3292  */
wlan_11h_ioctl_dfs_testing(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3293 mlan_status wlan_11h_ioctl_dfs_testing(pmlan_adapter pmadapter,
3294 				       pmlan_ioctl_req pioctl_req)
3295 {
3296 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3297 	mlan_ds_11h_dfs_testing *dfs_test = MNULL;
3298 	wlan_dfs_testing_settings_t *pdfs_test_params = MNULL;
3299 
3300 	ENTER();
3301 
3302 	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3303 	dfs_test = &ds_11hcfg->param.dfs_testing;
3304 	pdfs_test_params = &pmadapter->dfs_test_params;
3305 
3306 	if (pioctl_req->action == MLAN_ACT_GET) {
3307 		dfs_test->usr_cac_period_msec =
3308 			pdfs_test_params->user_cac_period_msec;
3309 		dfs_test->usr_nop_period_sec =
3310 			pdfs_test_params->user_nop_period_sec;
3311 		dfs_test->usr_no_chan_change =
3312 			pdfs_test_params->no_channel_change_on_radar;
3313 		dfs_test->usr_fixed_new_chan =
3314 			pdfs_test_params->fixed_new_channel_on_radar;
3315 		dfs_test->usr_cac_restart = pdfs_test_params->cac_restart;
3316 	} else {
3317 		pdfs_test_params->user_cac_period_msec =
3318 			dfs_test->usr_cac_period_msec;
3319 		pdfs_test_params->user_nop_period_sec =
3320 			dfs_test->usr_nop_period_sec;
3321 		pdfs_test_params->no_channel_change_on_radar =
3322 			dfs_test->usr_no_chan_change;
3323 		pdfs_test_params->fixed_new_channel_on_radar =
3324 			dfs_test->usr_fixed_new_chan;
3325 		pdfs_test_params->cac_restart = dfs_test->usr_cac_restart;
3326 	}
3327 
3328 	LEAVE();
3329 	return MLAN_STATUS_SUCCESS;
3330 }
3331 
3332 /**
3333  *  @brief 802.11h IOCTL to get nop channel list
3334  *
3335  *  @param pmadapter    Pointer to mlan_adapter
3336  *  @param pioctl_req   Pointer to mlan_ioctl_req
3337  *
3338  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3339  */
wlan_11h_ioctl_nop_channel_list(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3340 mlan_status wlan_11h_ioctl_nop_channel_list(pmlan_adapter pmadapter,
3341 					    pmlan_ioctl_req pioctl_req)
3342 {
3343 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3344 	int i, j;
3345 	chan_freq_power_t *pcfp = MNULL;
3346 	t_u8 num_chan = 0;
3347 	ENTER();
3348 
3349 	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3350 	/*get the cfp table first */
3351 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
3352 		if (pmadapter->region_channel[i].band == BAND_A) {
3353 			pcfp = pmadapter->region_channel[i].pcfp;
3354 			break;
3355 		}
3356 	}
3357 	if (!pcfp) {
3358 		/* This means operation in BAND-A is not support, we can
3359 		 * just return false here, it's harmless
3360 		 */
3361 		goto done;
3362 	}
3363 	/*get the radar detection requirements according to chan num */
3364 	for (j = 0; j < pmadapter->region_channel[i].num_cfp; j++) {
3365 		if (pcfp[j].passive_scan_or_radar_detect) {
3366 			if (wlan_11h_is_channel_under_nop(pmadapter,
3367 							  pcfp[j].channel)) {
3368 				ds_11hcfg->param.nop_chan_list
3369 					.chan_list[num_chan] = pcfp[j].channel;
3370 				num_chan++;
3371 			}
3372 		}
3373 	}
3374 done:
3375 	ds_11hcfg->param.nop_chan_list.num_chan = num_chan;
3376 	return MLAN_STATUS_SUCCESS;
3377 }
3378 
3379 /**
3380  *  @brief 802.11h IOCTL to handle channel NOP status check/clear
3381  *  @brief If given channel is under NOP, return a new non-dfs
3382  *  @brief channel
3383  *
3384  *  @param pmadapter    Pointer to mlan_adapter
3385  *  @param pioctl_req   Pointer to mlan_ioctl_req
3386  *
3387  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3388  */
wlan_11h_ioctl_channel_nop_info(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3389 mlan_status wlan_11h_ioctl_channel_nop_info(pmlan_adapter pmadapter,
3390 					    pmlan_ioctl_req pioctl_req)
3391 {
3392 	pmlan_private pmpriv = MNULL;
3393 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3394 	t_s32 ret = MLAN_STATUS_FAILURE;
3395 	mlan_ds_11h_chan_nop_info *ch_nop_info = MNULL;
3396 
3397 	ENTER();
3398 
3399 	if (pioctl_req) {
3400 		pmpriv = pmadapter->priv[pioctl_req->bss_index];
3401 		ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3402 		ch_nop_info = &ds_11hcfg->param.ch_nop_info;
3403 
3404 		if (pioctl_req->action == MLAN_ACT_GET) {
3405 			ch_nop_info->chan_under_nop =
3406 				wlan_11h_is_channel_under_nop(
3407 					pmadapter, ch_nop_info->curr_chan);
3408 			if (ch_nop_info->chan_under_nop &&
3409 			    ch_nop_info->check_new_chan) {
3410 				wlan_11h_switch_non_dfs_chan(
3411 					pmpriv, &ch_nop_info->new_chan.channel);
3412 				if (ch_nop_info->chan_width == CHAN_BW_80MHZ ||
3413 				    ch_nop_info->chan_width == CHAN_BW_40MHZ)
3414 					wlan_11h_update_bandcfg(
3415 						pmpriv,
3416 						&ch_nop_info->new_chan.bandcfg,
3417 						ch_nop_info->new_chan.channel);
3418 				if (ch_nop_info->chan_width == CHAN_BW_80MHZ)
3419 					ch_nop_info->new_chan.center_chan =
3420 						wlan_get_center_freq_idx(
3421 							pmpriv, BAND_AAC,
3422 							ch_nop_info->new_chan
3423 								.channel,
3424 							ch_nop_info->chan_width);
3425 			}
3426 		} else if (pioctl_req->action == MLAN_ACT_CLEAR) {
3427 			wlan_11h_cleanup(pmadapter);
3428 			wlan_reset_all_chan_dfs_state(pmpriv, BAND_A,
3429 						      DFS_USABLE);
3430 		}
3431 		ret = MLAN_STATUS_SUCCESS;
3432 	}
3433 
3434 	LEAVE();
3435 	return ret;
3436 }
3437 
3438 /**
3439  *  @brief 802.11h DFS Channel Switch Count Configuration
3440  *
3441  *  @param pmadapter    Pointer to mlan_adapter
3442  *  @param pioctl_req   Pointer to mlan_ioctl_req
3443  *
3444  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3445  */
wlan_11h_ioctl_chan_switch_count(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3446 mlan_status wlan_11h_ioctl_chan_switch_count(pmlan_adapter pmadapter,
3447 					     pmlan_ioctl_req pioctl_req)
3448 {
3449 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3450 	t_s32 ret = MLAN_STATUS_FAILURE;
3451 
3452 	ENTER();
3453 
3454 	if (pioctl_req) {
3455 		ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3456 
3457 		if (pioctl_req->action == MLAN_ACT_GET) {
3458 			ds_11hcfg->param.cs_count = pmadapter->dfs_cs_count;
3459 		} else {
3460 			pmadapter->dfs_cs_count = ds_11hcfg->param.cs_count;
3461 		}
3462 		ret = MLAN_STATUS_SUCCESS;
3463 	}
3464 
3465 	LEAVE();
3466 	return ret;
3467 }
3468 
3469 /**
3470  *  @brief Get/Set 802.11h  channel dfs state
3471  *
3472  *  @param pmadapter    Pointer to mlan_adapter
3473  *  @param pioctl_req   Pointer to mlan_ioctl_req
3474  *
3475  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3476  */
wlan_11h_ioctl_chan_dfs_state(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3477 mlan_status wlan_11h_ioctl_chan_dfs_state(pmlan_adapter pmadapter,
3478 					  pmlan_ioctl_req pioctl_req)
3479 {
3480 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3481 	t_s32 ret = MLAN_STATUS_FAILURE;
3482 	pmlan_private priv = MNULL;
3483 
3484 	ENTER();
3485 
3486 	if (pioctl_req) {
3487 		ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3488 		priv = pmadapter->priv[pioctl_req->bss_index];
3489 
3490 		if (pioctl_req->action == MLAN_ACT_GET) {
3491 			if (MFALSE ==
3492 			    wlan_11h_is_channel_under_nop(
3493 				    pmadapter,
3494 				    ds_11hcfg->param.ch_dfs_state.channel))
3495 				PRINTM(MINFO, "Channel is not in NOP\n");
3496 			ds_11hcfg->param.ch_dfs_state.dfs_required =
3497 				wlan_11h_radar_detect_required(
3498 					priv,
3499 					ds_11hcfg->param.ch_dfs_state.channel);
3500 			if (ds_11hcfg->param.ch_dfs_state.dfs_required)
3501 				ds_11hcfg->param.ch_dfs_state
3502 					.dfs_state = wlan_get_chan_dfs_state(
3503 					priv, BAND_A,
3504 					ds_11hcfg->param.ch_dfs_state.channel);
3505 		} else {
3506 			wlan_set_chan_dfs_state(
3507 				priv, BAND_A,
3508 				ds_11hcfg->param.ch_dfs_state.channel,
3509 				ds_11hcfg->param.ch_dfs_state.dfs_state);
3510 		}
3511 		ret = MLAN_STATUS_SUCCESS;
3512 	}
3513 
3514 	LEAVE();
3515 	return ret;
3516 }
3517 
3518 /**
3519  *  @brief 802.11h DFS chan report
3520  *
3521  *  @param priv         Pointer to mlan_private
3522  *  @param pioctl_req   Pointer to mlan_ioctl_req
3523  *
3524  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3525  */
wlan_11h_ioctl_dfs_chan_report(mlan_private * priv,pmlan_ioctl_req pioctl_req)3526 mlan_status wlan_11h_ioctl_dfs_chan_report(mlan_private *priv,
3527 					   pmlan_ioctl_req pioctl_req)
3528 {
3529 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3530 	HostCmd_DS_CHAN_RPT_REQ *chan_rpt_req = MNULL;
3531 	t_s32 ret;
3532 
3533 	ENTER();
3534 
3535 	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3536 
3537 	chan_rpt_req =
3538 		(HostCmd_DS_CHAN_RPT_REQ *)&ds_11hcfg->param.chan_rpt_req;
3539 
3540 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
3541 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
3542 			       (t_void *)chan_rpt_req);
3543 
3544 	if (ret == MLAN_STATUS_SUCCESS)
3545 		ret = MLAN_STATUS_PENDING;
3546 
3547 	LEAVE();
3548 	return ret;
3549 }
3550 /**
3551  *  @brief Check if channel is under NOP (Non-Occupancy Period)
3552  *  If so, the channel should not be used until the period expires.
3553  *
3554  *  @param pmadapter  Pointer to mlan_adapter
3555  *  @param channel    Channel number
3556  *
3557  *  @return MTRUE or MFALSE
3558  */
wlan_11h_is_channel_under_nop(mlan_adapter * pmadapter,t_u8 channel)3559 t_bool wlan_11h_is_channel_under_nop(mlan_adapter *pmadapter, t_u8 channel)
3560 {
3561 	wlan_dfs_timestamp_t *pdfs_ts = MNULL;
3562 	t_u32 now_sec, now_usec;
3563 	t_bool ret = MFALSE;
3564 	mlan_private *priv;
3565 	ENTER();
3566 	pdfs_ts = wlan_11h_find_dfs_timestamp(pmadapter, channel);
3567 
3568 	if (pdfs_ts && (pdfs_ts->channel == channel) &&
3569 	    (pdfs_ts->represents == DFS_TS_REPR_NOP_START)) {
3570 		/* found NOP_start timestamp entry on channel */
3571 		pmadapter->callbacks.moal_get_system_time(
3572 			pmadapter->pmoal_handle, &now_sec, &now_usec);
3573 		if (pmadapter->dfs_test_params.user_nop_period_sec) {
3574 			PRINTM(MCMD_D,
3575 			       "dfs_testing - user NOP period=%d (sec)\n",
3576 			       pmadapter->dfs_test_params.user_nop_period_sec);
3577 			if ((now_sec - pdfs_ts->ts_sec) <=
3578 			    pmadapter->dfs_test_params.user_nop_period_sec) {
3579 				ret = MTRUE;
3580 			}
3581 		} else {
3582 			if ((now_sec - pdfs_ts->ts_sec) <=
3583 			    WLAN_11H_NON_OCCUPANCY_PERIOD)
3584 				ret = MTRUE;
3585 		}
3586 
3587 		/* if entry is expired, remove it */
3588 		if (!ret) {
3589 			wlan_11h_remove_dfs_timestamp(pmadapter, pdfs_ts);
3590 			priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
3591 			if (priv)
3592 				wlan_set_chan_dfs_state(priv, BAND_A, channel,
3593 							DFS_USABLE);
3594 		} else
3595 			PRINTM(MMSG,
3596 			       "11h: channel %d is under NOP - can't use.\n",
3597 			       channel);
3598 	}
3599 
3600 	LEAVE();
3601 	return ret;
3602 }
3603 
3604 /**
3605  *  @brief Driver handling for CHANNEL_REPORT_RDY event
3606  *  This event will have the channel report data appended.
3607  *
3608  *  @param priv     Pointer to mlan_private
3609  *  @param pevent   Pointer to mlan_event
3610  *  @param radar_chan 	Pointer to radar channel
3611  *  @param bandwidth    Pointer to band width
3612  *
3613  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3614  */
wlan_11h_handle_event_chanrpt_ready(mlan_private * priv,mlan_event * pevent,t_u8 * radar_chan,t_u8 * bandwidth)3615 mlan_status wlan_11h_handle_event_chanrpt_ready(mlan_private *priv,
3616 						mlan_event *pevent,
3617 						t_u8 *radar_chan,
3618 						t_u8 *bandwidth)
3619 {
3620 	mlan_status ret = MLAN_STATUS_SUCCESS;
3621 	HostCmd_DS_CHAN_RPT_RSP *pchan_rpt_rsp;
3622 	MrvlIEtypes_Data_t *ptlv;
3623 	MeasRptBasicMap_t *pmeas_rpt_basic;
3624 	t_u8 *pbuffer;
3625 	t_s32 evt_len;
3626 	t_u16 tlv_len;
3627 	t_u32 sec, usec;
3628 	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
3629 	t_u8 dfs_radar_found = MFALSE;
3630 	t_u8 dfs_check_channel = pstate_dfs->dfs_check_channel;
3631 	t_u8 dfs_check_bandwidth = pstate_dfs->dfs_check_bandwidth;
3632 	MrvlIEtypes_channel_band_t *tlv;
3633 
3634 	ENTER();
3635 	pchan_rpt_rsp = (HostCmd_DS_CHAN_RPT_RSP *)&pevent->event_buf;
3636 	DBG_HEXDUMP(MCMD_D, "11h: Event ChanRptReady (HostCmd_DS_CHAN_RPT_RSP)",
3637 		    (t_u8 *)pchan_rpt_rsp, pevent->event_len);
3638 
3639 	if (priv->bss_type == MLAN_BSS_TYPE_DFS) {
3640 		dfs_check_channel = priv->chan_rep_req.chanNum;
3641 		dfs_check_bandwidth = priv->chan_rep_req.bandcfg.chanWidth;
3642 	}
3643 
3644 	if (wlan_le32_to_cpu(pchan_rpt_rsp->cmd_result) ==
3645 	    MLAN_CMD_RESULT_SUCCESS) {
3646 		pbuffer = (t_u8 *)&pchan_rpt_rsp->tlv_buffer;
3647 		evt_len = pevent->event_len;
3648 		evt_len -= sizeof(HostCmd_DS_CHAN_RPT_RSP) -
3649 			   sizeof(pchan_rpt_rsp->tlv_buffer);
3650 
3651 		while (evt_len >= (t_s32)sizeof(MrvlIEtypesHeader_t)) {
3652 			ptlv = (MrvlIEtypes_Data_t *)pbuffer;
3653 			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
3654 
3655 			switch (wlan_le16_to_cpu(ptlv->header.type)) {
3656 			case TLV_TYPE_CHANRPT_11H_BASIC:
3657 				pmeas_rpt_basic =
3658 					(MeasRptBasicMap_t *)&ptlv->data;
3659 				if (pmeas_rpt_basic->radar)
3660 					dfs_radar_found = MTRUE;
3661 				break;
3662 			case TLV_TYPE_CHANNELBANDLIST:
3663 				tlv = (MrvlIEtypes_channel_band_t *)ptlv;
3664 				dfs_check_channel = tlv->channel;
3665 				dfs_check_bandwidth = tlv->bandcfg.chanWidth;
3666 				break;
3667 			default:
3668 				break;
3669 			}
3670 
3671 			pbuffer += (tlv_len + sizeof(ptlv->header));
3672 			evt_len -= (tlv_len + sizeof(ptlv->header));
3673 			evt_len = (evt_len > 0) ? evt_len : 0;
3674 		}
3675 	} else {
3676 		ret = MLAN_STATUS_FAILURE;
3677 	}
3678 	if (dfs_radar_found) {
3679 		PRINTM(MMSG, "RADAR Detected on channel %d bw=%d !\n",
3680 		       dfs_check_channel, dfs_check_bandwidth);
3681 		/* add channel to NOP list */
3682 		wlan_11h_add_all_dfs_timestamp(priv->adapter,
3683 					       DFS_TS_REPR_NOP_START,
3684 					       dfs_check_channel,
3685 					       dfs_check_bandwidth);
3686 	}
3687 	*radar_chan = dfs_check_channel;
3688 	*bandwidth = dfs_check_bandwidth;
3689 	if (dfs_radar_found)
3690 		wlan_11h_set_chan_dfs_state(priv, dfs_check_channel,
3691 					    dfs_check_bandwidth,
3692 					    DFS_UNAVAILABLE);
3693 	else
3694 		wlan_11h_set_chan_dfs_state(priv, dfs_check_channel,
3695 					    dfs_check_bandwidth, DFS_AVAILABLE);
3696 	pstate_dfs->dfs_radar_found = dfs_radar_found;
3697 	/* Update DFS structure. */
3698 	priv->adapter->callbacks.moal_get_system_time(
3699 		priv->adapter->pmoal_handle, &sec, &usec);
3700 	pstate_dfs->dfs_report_time_sec = sec;
3701 	pstate_dfs->dfs_check_pending = MFALSE;
3702 
3703 	LEAVE();
3704 	return ret;
3705 }
3706 
3707 /**
3708  *  @brief Print debug info in RADAR_DETECTED event
3709  *  This event may have the dfs record data appended.
3710  *
3711  *  @param priv   		Pointer to mlan_private
3712  *  @param pevent 		Pointer to mlan_event
3713  *  @param radar_chan 	Pointer to radar channel
3714  *  @param bandwidth    Pointer to band width
3715  *
3716  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3717  */
wlan_11h_print_event_radar_detected(mlan_private * priv,mlan_event * pevent,t_u8 * radar_chan,t_u8 * bandwidth)3718 mlan_status wlan_11h_print_event_radar_detected(mlan_private *priv,
3719 						mlan_event *pevent,
3720 						t_u8 *radar_chan,
3721 						t_u8 *bandwidth)
3722 {
3723 	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
3724 	t_u8 dfs_check_bandwidth = pstate_dfs->dfs_check_bandwidth;
3725 	MrvlIEtypes_channel_band_t *tlv;
3726 	ENTER();
3727 	*radar_chan = pstate_dfs->dfs_check_channel;
3728 	if (pevent->event_len >= sizeof(MrvlIEtypes_channel_band_t)) {
3729 		tlv = (MrvlIEtypes_channel_band_t *)&pevent->event_buf;
3730 		*radar_chan = tlv->channel;
3731 		dfs_check_bandwidth = tlv->bandcfg.chanWidth;
3732 	} else {
3733 		if (priv->bss_type == MLAN_BSS_TYPE_DFS) {
3734 			*radar_chan = priv->chan_rep_req.chanNum;
3735 			dfs_check_bandwidth =
3736 				priv->chan_rep_req.bandcfg.chanWidth;
3737 		}
3738 	}
3739 	*bandwidth = dfs_check_bandwidth;
3740 	wlan_11h_add_all_dfs_timestamp(priv->adapter, DFS_TS_REPR_NOP_START,
3741 				       *radar_chan, dfs_check_bandwidth);
3742 	wlan_11h_set_chan_dfs_state(priv, *radar_chan, dfs_check_bandwidth,
3743 				    DFS_UNAVAILABLE);
3744 	PRINTM(MEVENT, "DFS: Radar detected on %d bw=%d\n", *radar_chan,
3745 	       dfs_check_bandwidth);
3746 	LEAVE();
3747 	return MLAN_STATUS_SUCCESS;
3748 }
3749 
3750 /**
3751  *  @brief Check if RADAR_DETECTED handling is blocking data tx
3752  *
3753  *  @param pmadapter    Pointer to mlan_adapter
3754  *
3755  *  @return MTRUE or MFALSE
3756  */
wlan_11h_radar_detected_tx_blocked(mlan_adapter * pmadapter)3757 t_bool wlan_11h_radar_detected_tx_blocked(mlan_adapter *pmadapter)
3758 {
3759 	if (pmadapter->state_rdh.tx_block)
3760 		return MTRUE;
3761 	switch (pmadapter->state_rdh.stage) {
3762 	case RDH_OFF:
3763 	case RDH_CHK_INTFS:
3764 	case RDH_STOP_TRAFFIC:
3765 		return MFALSE;
3766 	}
3767 	return MTRUE;
3768 }
3769 
3770 /**
3771  *  @brief Callback for RADAR_DETECTED event driver handling
3772  *
3773  *  @param priv    Void pointer to mlan_private
3774  *
3775  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3776  */
wlan_11h_radar_detected_callback(t_void * priv)3777 mlan_status wlan_11h_radar_detected_callback(t_void *priv)
3778 {
3779 	mlan_status ret;
3780 	ENTER();
3781 	ret = wlan_11h_radar_detected_handling(
3782 		((mlan_private *)(priv))->adapter, (mlan_private *)priv);
3783 	LEAVE();
3784 	return ret;
3785 }
3786 
3787 #ifdef UAP_SUPPORT
3788 /**
3789  *  @brief Function for handling sta disconnect event in dfs_repeater mode
3790  *
3791  *  @param pmadapter	pointer to mlan_adapter
3792  *
3793  *  @return NONE
3794  */
wlan_dfs_rep_disconnect(mlan_adapter * pmadapter)3795 void wlan_dfs_rep_disconnect(mlan_adapter *pmadapter)
3796 {
3797 	mlan_private *priv_list[MLAN_MAX_BSS_NUM];
3798 	mlan_private *pmpriv = MNULL;
3799 	t_u8 pcount, i;
3800 
3801 	memset(pmadapter, priv_list, 0x00, sizeof(priv_list));
3802 	pcount = wlan_get_privs_by_cond(pmadapter, wlan_is_intf_active,
3803 					priv_list);
3804 
3805 	/* Stop all the active BSSes */
3806 	for (i = 0; i < pcount; i++) {
3807 		pmpriv = priv_list[i];
3808 
3809 		if (GET_BSS_ROLE(pmpriv) != MLAN_BSS_ROLE_UAP)
3810 			continue;
3811 
3812 		if (wlan_11h_radar_detect_required(pmpriv,
3813 						   pmadapter->dfsr_channel)) {
3814 			wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP,
3815 					 HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
3816 		}
3817 	}
3818 }
3819 
3820 /**
3821  *  @brief Function for handling sta BW change event in dfs_repeater mode
3822  *
3823  *  @param pmadapter	pointer to mlan_adapter
3824  *
3825  *  @return NONE
3826  */
wlan_dfs_rep_bw_change(mlan_adapter * pmadapter)3827 void wlan_dfs_rep_bw_change(mlan_adapter *pmadapter)
3828 {
3829 	mlan_private *priv_list[MLAN_MAX_BSS_NUM];
3830 	mlan_private *pmpriv = MNULL;
3831 	t_u8 pcount, i;
3832 
3833 	memset(pmadapter, priv_list, 0x00, sizeof(priv_list));
3834 	pcount = wlan_get_privs_by_cond(pmadapter, wlan_is_intf_active,
3835 					priv_list);
3836 	if (pcount == 1) {
3837 		pmpriv = priv_list[0];
3838 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
3839 			PRINTM(MMSG,
3840 			       "dfs-repeater: BW change detected\n"
3841 			       "no active priv's, skip event handling.\n");
3842 			return;
3843 		}
3844 	}
3845 
3846 	/* Stop all the active BSSes */
3847 	for (i = 0; i < pcount; i++) {
3848 		pmpriv = priv_list[i];
3849 
3850 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
3851 			/* Check if uAPs running on non-dfs channel. If they do
3852 			 * then there is no need to restart the uAPs
3853 			 */
3854 			if (!wlan_11h_radar_detect_required(
3855 				    pmpriv, pmadapter->dfsr_channel))
3856 				return;
3857 
3858 			wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP,
3859 					 HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
3860 		}
3861 	}
3862 
3863 	/* Start all old active BSSes */
3864 	for (i = 0; i < pcount; i++) {
3865 		pmpriv = priv_list[i];
3866 
3867 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
3868 			wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_START,
3869 					 HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
3870 		}
3871 	}
3872 }
3873 #endif
3874 
3875 /**
3876  *  @brief Update band config for the new channel
3877  *
3878  *  @param uap_band_cfg  uap's old channel's band configuration
3879  *  @param new_channel   new channel that the device is switching to
3880  *
3881  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
3882  */
wlan_11h_update_bandcfg(mlan_private * pmpriv,Band_Config_t * uap_band_cfg,t_u8 new_channel)3883 void wlan_11h_update_bandcfg(mlan_private *pmpriv, Band_Config_t *uap_band_cfg,
3884 			     t_u8 new_channel)
3885 {
3886 	t_u8 chan_offset;
3887 	ENTER();
3888 
3889 	/* Update the channel offset for 20MHz, 40MHz and 80MHz
3890 	 * Clear the channel bandwidth for 20MHz
3891 	 * since channel switch could be happening from 40/80MHz to 20MHz
3892 	 */
3893 	chan_offset = wlan_get_second_channel_offset(pmpriv, new_channel);
3894 	uap_band_cfg->chan2Offset = chan_offset;
3895 
3896 	if (!chan_offset) { /* 40MHz/80MHz */
3897 		PRINTM(MCMD_D, "20MHz channel, clear channel bandwidth\n");
3898 		uap_band_cfg->chanWidth = CHAN_BW_20MHZ;
3899 	}
3900 	LEAVE();
3901 }
3902 
3903 #ifdef UAP_SUPPORT
3904 /**
3905  * @brief Get priv current index -- this is used to enter correct rdh_state
3906  * during radar handling
3907  *
3908  * @param pmpriv           Pointer to mlan_private
3909  * @param pstate_rdh       Pointer to radar detected state handler
3910  *
3911  * @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3912  */
3913 static mlan_status
wlan_11h_get_priv_curr_idx(mlan_private * pmpriv,wlan_radar_det_hndlg_state_t * pstate_rdh)3914 wlan_11h_get_priv_curr_idx(mlan_private *pmpriv,
3915 			   wlan_radar_det_hndlg_state_t *pstate_rdh)
3916 {
3917 	t_bool found = MFALSE;
3918 	ENTER();
3919 
3920 	PRINTM(MINFO, "%s:pmpriv =%p\n", __func__, pmpriv);
3921 	while ((++pstate_rdh->priv_curr_idx) < pstate_rdh->priv_list_count) {
3922 		if (pmpriv ==
3923 		    pstate_rdh->priv_list[pstate_rdh->priv_curr_idx]) {
3924 			PRINTM(MINFO, "found matching priv: priv_idx=%d\n",
3925 			       pstate_rdh->priv_curr_idx);
3926 			found = MTRUE;
3927 			break;
3928 		}
3929 	}
3930 	return (found == MTRUE) ? MLAN_STATUS_SUCCESS : MLAN_STATUS_FAILURE;
3931 }
3932 #endif
3933 
3934 /**
3935  *  @brief Driver handling for remove customeie
3936  *
3937  *  @param pmadapter    Pointer to mlan_adapter
3938  *  @param pmpriv       Pointer to mlan_private
3939  *
3940  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
3941  */
wlan_11h_remove_custom_ie(mlan_adapter * pmadapter,mlan_private * pmpriv)3942 mlan_status wlan_11h_remove_custom_ie(mlan_adapter *pmadapter,
3943 				      mlan_private *pmpriv)
3944 {
3945 	mlan_status ret = MLAN_STATUS_SUCCESS;
3946 	wlan_radar_det_hndlg_state_t *pstate_rdh = &pmadapter->state_rdh;
3947 	mlan_ioctl_req *pioctl_req = MNULL;
3948 
3949 	ENTER();
3950 	if (pstate_rdh->stage == RDH_SET_CUSTOM_IE) {
3951 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
3952 		PRINTM(MMSG, "Removing CHAN_SW IE from interfaces.\n");
3953 		while ((++pstate_rdh->priv_curr_idx) <
3954 		       pstate_rdh->priv_list_count) {
3955 			pmpriv =
3956 				pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
3957 			if (!wlan_11h_is_dfs_master(pmpriv))
3958 				continue;
3959 			ret = wlan_11h_prepare_custom_ie_chansw(
3960 				pmadapter, &pioctl_req, MFALSE);
3961 			if ((ret != MLAN_STATUS_SUCCESS) || !pioctl_req) {
3962 				PRINTM(MERROR,
3963 				       "%s(): Error in preparing CHAN_SW IE.\n",
3964 				       __func__);
3965 				goto done;
3966 			}
3967 
3968 			pioctl_req->bss_index = pmpriv->bss_index;
3969 			ret = wlan_misc_ioctl_custom_ie_list(
3970 				pmadapter, pioctl_req, MFALSE);
3971 			if (ret != MLAN_STATUS_SUCCESS &&
3972 			    ret != MLAN_STATUS_PENDING) {
3973 				PRINTM(MERROR,
3974 				       "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
3975 				       __func__, pmpriv, pmpriv->bss_index);
3976 				/* TODO: hiow to handle this error case??
3977 				 * ignore & continue? */
3978 			}
3979 			/* free ioctl buffer memory before we leave */
3980 			pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle,
3981 							(t_u8 *)pioctl_req);
3982 		}
3983 	}
3984 done:
3985 	LEAVE();
3986 	return ret;
3987 }
3988 
3989 /**
3990  *  @brief Driver handling for RADAR_DETECTED event
3991  *
3992  *  @param pmadapter    Pointer to mlan_adapter
3993  *  @param pmpriv       Pointer to mlan_private
3994  *
3995  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
3996  */
wlan_11h_radar_detected_handling(mlan_adapter * pmadapter,mlan_private * pmpriv)3997 mlan_status wlan_11h_radar_detected_handling(mlan_adapter *pmadapter,
3998 					     mlan_private *pmpriv)
3999 {
4000 #ifdef DEBUG_LEVEL1
4001 	const char *rdh_stage_str[] = {"RDH_OFF",
4002 				       "RDH_CHK_INTFS",
4003 				       "RDH_STOP_TRAFFIC",
4004 				       "RDH_GET_INFO_CHANNEL",
4005 				       "RDH_GET_INFO_BEACON_DTIM",
4006 				       "RDH_SET_CUSTOM_IE",
4007 				       "RDH_REM_CUSTOM_IE",
4008 				       "RDH_STOP_INTFS",
4009 				       "RDH_SET_NEW_CHANNEL",
4010 				       "RDH_RESTART_INTFS",
4011 				       "RDH_RESTART_TRAFFIC"};
4012 #endif
4013 
4014 	mlan_status ret = MLAN_STATUS_SUCCESS;
4015 	t_u32 i;
4016 	wlan_radar_det_hndlg_state_t *pstate_rdh = &pmadapter->state_rdh;
4017 
4018 	ENTER();
4019 
4020 	if (!pmpriv) {
4021 		PRINTM(MERROR, "Invalid radar priv -- Exit radar handling\n");
4022 		LEAVE();
4023 		return MLAN_STATUS_FAILURE;
4024 	}
4025 
4026 	switch (pstate_rdh->stage) {
4027 	case RDH_CHK_INTFS:
4028 		PRINTM(MCMD_D, "%s(): stage(%d)=%s\n", __func__,
4029 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
4030 
4031 		/* get active interfaces */
4032 		memset(pmadapter, pstate_rdh->priv_list, 0x00,
4033 		       sizeof(pstate_rdh->priv_list));
4034 		pstate_rdh->priv_list_count = wlan_get_privs_by_cond(
4035 			pmadapter, wlan_is_intf_active, pstate_rdh->priv_list);
4036 		PRINTM(MCMD_D, "%s():  priv_list_count = %d\n", __func__,
4037 		       pstate_rdh->priv_list_count);
4038 		for (i = 0; i < pstate_rdh->priv_list_count; i++)
4039 			PRINTM(MINFO, "%s():  priv_list[%d] = %p\n", __func__,
4040 			       i, pstate_rdh->priv_list[i]);
4041 
4042 		if (pstate_rdh->priv_list_count == 0) {
4043 			/* no interfaces active... nothing to do */
4044 			PRINTM(MMSG, "11h: Radar Detected - no active priv's,"
4045 				     " skip event handling.\n");
4046 			pstate_rdh->stage = RDH_OFF;
4047 			PRINTM(MCMD_D, "%s(): finished - stage(%d)=%s\n",
4048 			       __func__, pstate_rdh->stage,
4049 			       rdh_stage_str[pstate_rdh->stage]);
4050 			break; /* EXIT CASE */
4051 		}
4052 
4053 		/* else: start handling */
4054 		pstate_rdh->curr_channel = 0;
4055 		pstate_rdh->new_channel = 0;
4056 		memset(pmadapter, &(pstate_rdh->uap_band_cfg), 0,
4057 		       sizeof(pstate_rdh->uap_band_cfg));
4058 		pstate_rdh->max_bcn_dtim_ms = 0;
4059 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4060 		pstate_rdh->stage = RDH_STOP_TRAFFIC;
4061 		/* fall through */
4062 
4063 	case RDH_STOP_TRAFFIC:
4064 		PRINTM(MCMD_D, "%s(): stage(%d)=%s\n", __func__,
4065 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
4066 
4067 		PRINTM(MMSG,
4068 		       "11h: Radar Detected - stopping host tx traffic.\n");
4069 		for (i = 0; i < pstate_rdh->priv_list_count; i++)
4070 			wlan_11h_tx_disable(pstate_rdh->priv_list[i]);
4071 
4072 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4073 		pstate_rdh->stage = RDH_GET_INFO_CHANNEL;
4074 		/* fall through */
4075 
4076 	case RDH_GET_INFO_CHANNEL:
4077 		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
4078 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
4079 		       pstate_rdh->priv_curr_idx);
4080 
4081 		/* here, prefer STA info over UAP info - one less CMD to send */
4082 		if (pstate_rdh->priv_curr_idx ==
4083 		    RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
4084 #ifdef UAP_SUPPORT
4085 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
4086 				ret = wlan_11h_get_priv_curr_idx(pmpriv,
4087 								 pstate_rdh);
4088 				if (ret != MLAN_STATUS_SUCCESS) {
4089 					PRINTM(MERROR,
4090 					       "Unable to locate pmpriv in current active priv_list\n");
4091 					break; /* EXIT CASE */
4092 				}
4093 
4094 				/* send cmd to get first UAP's info */
4095 				pmpriv->uap_state_chan_cb.pioctl_req_curr =
4096 					MNULL;
4097 				pmpriv->uap_state_chan_cb.get_chan_callback =
4098 					wlan_11h_radar_detected_callback;
4099 				ret = wlan_uap_get_channel(pmpriv);
4100 				break; /* EXIT CASE */
4101 			} else
4102 #endif
4103 			{
4104 				/* Assume all STAs on same channel, find first
4105 				 * STA */
4106 				MASSERT(pstate_rdh->priv_list_count > 0);
4107 				for (i = 0; i < pstate_rdh->priv_list_count;
4108 				     i++) {
4109 					pmpriv = pstate_rdh->priv_list[i];
4110 					if (GET_BSS_ROLE(pmpriv) ==
4111 					    MLAN_BSS_ROLE_STA)
4112 						break;
4113 				}
4114 				/* STA info kept in driver, just copy */
4115 				pstate_rdh->curr_channel =
4116 					pmpriv->curr_bss_params.bss_descriptor
4117 						.channel;
4118 			}
4119 		}
4120 #ifdef UAP_SUPPORT
4121 		else if (pstate_rdh->priv_curr_idx <
4122 			 pstate_rdh->priv_list_count) {
4123 			/* repeat entry: UAP return with info */
4124 			pstate_rdh->curr_channel =
4125 				pmpriv->uap_state_chan_cb.channel;
4126 			pstate_rdh->uap_band_cfg =
4127 				pmpriv->uap_state_chan_cb.bandcfg;
4128 			PRINTM(MCMD_D,
4129 			       "%s(): uap_band_cfg=0x%02x curr_chan=%d, curr_idx=%d bss_role=%d\n",
4130 			       __func__, pstate_rdh->uap_band_cfg,
4131 			       pstate_rdh->curr_channel,
4132 			       pstate_rdh->priv_curr_idx, GET_BSS_ROLE(pmpriv));
4133 		}
4134 #endif
4135 
4136 		/* add channel to NOP list */
4137 		wlan_11h_add_dfs_timestamp(pmadapter, DFS_TS_REPR_NOP_START,
4138 					   pstate_rdh->curr_channel);
4139 
4140 		/* choose new channel (!= curr channel) and move on */
4141 #ifdef UAP_SUPPORT
4142 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
4143 			pstate_rdh->new_channel =
4144 				wlan_11h_get_uap_start_channel(
4145 					pmpriv,
4146 					pmpriv->uap_state_chan_cb.bandcfg);
4147 		else
4148 #endif
4149 			pstate_rdh->new_channel =
4150 				wlan_11h_get_adhoc_start_channel(pmpriv);
4151 
4152 		if (!pstate_rdh->new_channel ||
4153 		    (pstate_rdh->new_channel ==
4154 		     pstate_rdh->curr_channel)) { /* report error */
4155 			PRINTM(MERROR,
4156 			       "%s():  ERROR - Failed to choose new_chan"
4157 			       " (!= curr_chan) !!\n",
4158 			       __func__);
4159 #ifdef UAP_SUPPORT
4160 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
4161 				ret = wlan_prepare_cmd(pmpriv,
4162 						       HOST_CMD_APCMD_BSS_STOP,
4163 						       HostCmd_ACT_GEN_SET, 0,
4164 						       MNULL, MNULL);
4165 				PRINTM(MERROR,
4166 				       "STOP UAP and exit radar handling...\n");
4167 				pstate_rdh->stage = RDH_OFF;
4168 				break; /* leads to exit case */
4169 			}
4170 #endif
4171 		}
4172 		if (!pmadapter->dfs_test_params.no_channel_change_on_radar &&
4173 		    pmadapter->dfs_test_params.fixed_new_channel_on_radar) {
4174 			PRINTM(MCMD_D, "dfs_testing - user fixed new_chan=%d\n",
4175 			       pmadapter->dfs_test_params
4176 				       .fixed_new_channel_on_radar);
4177 			pstate_rdh->new_channel =
4178 				pmadapter->dfs_test_params
4179 					.fixed_new_channel_on_radar;
4180 		}
4181 		/* applies to DFS with ECSA support */
4182 		if (pmadapter->dfs_test_params.no_channel_change_on_radar) {
4183 			pstate_rdh->new_channel = pstate_rdh->curr_channel;
4184 		}
4185 		PRINTM(MCMD_D, "%s():  curr_chan=%d, new_chan=%d\n", __func__,
4186 		       pstate_rdh->curr_channel, pstate_rdh->new_channel);
4187 
4188 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4189 		pstate_rdh->stage = RDH_GET_INFO_BEACON_DTIM;
4190 		/* fall through */
4191 
4192 	case RDH_GET_INFO_BEACON_DTIM:
4193 		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
4194 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
4195 		       pstate_rdh->priv_curr_idx);
4196 
4197 #ifdef UAP_SUPPORT
4198 		/* check all intfs in this stage to find longest period */
4199 		/* UAP intf callback returning with info */
4200 		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count) {
4201 			t_u16 bcn_dtim_msec;
4202 			pmpriv =
4203 				pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
4204 			PRINTM(MCMD_D, "%s():  uap.bcn_pd=%d, uap.dtim_pd=%d\n",
4205 			       __func__,
4206 			       pmpriv->uap_state_chan_cb.beacon_period,
4207 			       pmpriv->uap_state_chan_cb.dtim_period);
4208 			bcn_dtim_msec =
4209 				(pmpriv->uap_state_chan_cb.beacon_period *
4210 				 pmpriv->uap_state_chan_cb.dtim_period);
4211 			if (bcn_dtim_msec > pstate_rdh->max_bcn_dtim_ms)
4212 				pstate_rdh->max_bcn_dtim_ms = bcn_dtim_msec;
4213 		}
4214 #endif
4215 
4216 		/* check next intf */
4217 		while ((++pstate_rdh->priv_curr_idx) <
4218 		       pstate_rdh->priv_list_count) {
4219 			pmpriv =
4220 				pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
4221 
4222 #ifdef UAP_SUPPORT
4223 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
4224 				pmpriv->uap_state_chan_cb.pioctl_req_curr =
4225 					MNULL;
4226 				pmpriv->uap_state_chan_cb.get_chan_callback =
4227 					wlan_11h_radar_detected_callback;
4228 				ret = wlan_uap_get_beacon_dtim(pmpriv);
4229 				break; /* leads to exit case */
4230 			} else
4231 #endif
4232 			{ /* get STA info from driver and compare here */
4233 				t_u16 bcn_pd_msec = 100;
4234 				t_u16 dtim_pd_msec = 1;
4235 				t_u16 bcn_dtim_msec;
4236 
4237 				/* adhoc creator */
4238 				if (wlan_11h_is_dfs_master(pmpriv)) {
4239 					bcn_pd_msec = pmpriv->beacon_period;
4240 				} else {
4241 					bcn_pd_msec = pmpriv->curr_bss_params
4242 							      .bss_descriptor
4243 							      .beacon_period;
4244 					/* if (priv->bss_mode !=
4245 					 * MLAN_BSS_MODE_IBSS) */
4246 					/* TODO: mlan_scan.c needs to parse TLV
4247 					 * 0x05 (TIM) for dtim_period */
4248 				}
4249 				PRINTM(MCMD_D,
4250 				       "%s():  sta.bcn_pd=%d, sta.dtim_pd=%d\n",
4251 				       __func__, bcn_pd_msec, dtim_pd_msec);
4252 				bcn_dtim_msec = (bcn_pd_msec * dtim_pd_msec);
4253 				if (bcn_dtim_msec > pstate_rdh->max_bcn_dtim_ms)
4254 					pstate_rdh->max_bcn_dtim_ms =
4255 						bcn_dtim_msec;
4256 			}
4257 		}
4258 
4259 		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count)
4260 			break; /* EXIT CASE (for UAP) */
4261 		/* else */
4262 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4263 		pstate_rdh->stage = RDH_SET_CUSTOM_IE;
4264 		/* fall through */
4265 
4266 	case RDH_SET_CUSTOM_IE:
4267 		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
4268 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
4269 		       pstate_rdh->priv_curr_idx);
4270 
4271 		/* add CHAN_SW IE - Need apply on each interface */
4272 		if (pstate_rdh->priv_curr_idx ==
4273 		    RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
4274 			mlan_ioctl_req *pioctl_req = MNULL;
4275 			PRINTM(MMSG,
4276 			       "11h: Radar Detected - adding CHAN_SW IE to interfaces.\n");
4277 			while ((++pstate_rdh->priv_curr_idx) <
4278 			       pstate_rdh->priv_list_count) {
4279 				pmpriv = pstate_rdh->priv_list
4280 						 [pstate_rdh->priv_curr_idx];
4281 				if (!wlan_11h_is_dfs_master(pmpriv))
4282 					continue;
4283 				ret = wlan_11h_prepare_custom_ie_chansw(
4284 					pmadapter, &pioctl_req, MTRUE);
4285 				if ((ret != MLAN_STATUS_SUCCESS) ||
4286 				    !pioctl_req) {
4287 					PRINTM(MERROR,
4288 					       "%s(): Error in preparing CHAN_SW IE.\n",
4289 					       __func__);
4290 					break; /* EXIT CASE */
4291 				}
4292 
4293 				pioctl_req->bss_index = pmpriv->bss_index;
4294 				ret = wlan_misc_ioctl_custom_ie_list(
4295 					pmadapter, pioctl_req, MFALSE);
4296 				if (ret != MLAN_STATUS_SUCCESS &&
4297 				    ret != MLAN_STATUS_PENDING) {
4298 					PRINTM(MERROR,
4299 					       "%s(): Could not set IE for priv=%p [priv_bss_idx=%d]!\n",
4300 					       __func__, pmpriv,
4301 					       pmpriv->bss_index);
4302 					/* TODO: how to handle this error case??
4303 					 * ignore & continue? */
4304 				}
4305 				/* free ioctl buffer memory before we leave */
4306 				pmadapter->callbacks.moal_mfree(
4307 					pmadapter->pmoal_handle,
4308 					(t_u8 *)pioctl_req);
4309 			}
4310 			break; /* EXIT CASE */
4311 		}
4312 		/* else */
4313 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4314 		pstate_rdh->stage = RDH_REM_CUSTOM_IE;
4315 		/* fall through */
4316 
4317 	case RDH_REM_CUSTOM_IE:
4318 		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
4319 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
4320 		       pstate_rdh->priv_curr_idx);
4321 
4322 		/* remove CHAN_SW IE - Need apply on each interface */
4323 		if (pstate_rdh->priv_curr_idx ==
4324 		    RDH_STAGE_FIRST_ENTRY_PRIV_IDX) {
4325 			mlan_ioctl_req *pioctl_req = MNULL;
4326 			/*
4327 			 * first entry to this stage, do delay
4328 			 * DFS requires a minimum of 5 chances for clients to
4329 			 * hear this IE. Use delay:  5 beacons <=
4330 			 * (BCN_DTIM_MSEC*5) <= 3 seconds).
4331 			 */
4332 			t_u16 delay_ms =
4333 				MAX(MIN_RDH_CHAN_SW_IE_PERIOD_MSEC,
4334 				    MIN((4 * pstate_rdh->max_bcn_dtim_ms),
4335 					MAX_RDH_CHAN_SW_IE_PERIOD_MSEC));
4336 			PRINTM(MMSG,
4337 			       "11h: Radar Detected - delay %d ms for FW to"
4338 			       " broadcast CHAN_SW IE.\n",
4339 			       delay_ms);
4340 			wlan_mdelay(pmadapter, delay_ms);
4341 			PRINTM(MMSG,
4342 			       "11h: Radar Detected - delay over, removing"
4343 			       " CHAN_SW IE from interfaces.\n");
4344 			while ((++pstate_rdh->priv_curr_idx) <
4345 			       pstate_rdh->priv_list_count) {
4346 				pmpriv = pstate_rdh->priv_list
4347 						 [pstate_rdh->priv_curr_idx];
4348 				if (!wlan_11h_is_dfs_master(pmpriv))
4349 					continue;
4350 				ret = wlan_11h_prepare_custom_ie_chansw(
4351 					pmadapter, &pioctl_req, MFALSE);
4352 				if ((ret != MLAN_STATUS_SUCCESS) ||
4353 				    !pioctl_req) {
4354 					PRINTM(MERROR,
4355 					       "%s(): Error in preparing CHAN_SW IE.\n",
4356 					       __func__);
4357 					break; /* EXIT CASE */
4358 				}
4359 
4360 				pioctl_req->bss_index = pmpriv->bss_index;
4361 				ret = wlan_misc_ioctl_custom_ie_list(
4362 					pmadapter, pioctl_req, MFALSE);
4363 				if (ret != MLAN_STATUS_SUCCESS &&
4364 				    ret != MLAN_STATUS_PENDING) {
4365 					PRINTM(MERROR,
4366 					       "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
4367 					       __func__, pmpriv,
4368 					       pmpriv->bss_index);
4369 					/* TODO: hiow to handle this error
4370 					 * case??  ignore & continue? */
4371 				}
4372 				/* free ioctl buffer memory before we leave */
4373 				pmadapter->callbacks.moal_mfree(
4374 					pmadapter->pmoal_handle,
4375 					(t_u8 *)pioctl_req);
4376 			}
4377 			break; /* EXIT CASE */
4378 		}
4379 		/* else */
4380 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4381 		pstate_rdh->stage = RDH_STOP_INTFS;
4382 		/* fall through */
4383 
4384 	case RDH_STOP_INTFS:
4385 		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
4386 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
4387 		       pstate_rdh->priv_curr_idx);
4388 
4389 		/* issues one cmd (DEAUTH/ADHOC_STOP/BSS_STOP) to each intf */
4390 		while ((++pstate_rdh->priv_curr_idx) <
4391 		       pstate_rdh->priv_list_count) {
4392 			pmpriv =
4393 				pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
4394 #ifdef UAP_SUPPORT
4395 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
4396 				ret = wlan_prepare_cmd(pmpriv,
4397 						       HOST_CMD_APCMD_BSS_STOP,
4398 						       HostCmd_ACT_GEN_SET, 0,
4399 						       MNULL, MNULL);
4400 				break; /* leads to exit case */
4401 			}
4402 #endif
4403 #ifdef STA_SUPPORT
4404 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
4405 				if (wlan_11h_is_dfs_master(pmpriv)) {
4406 					/* Save ad-hoc creator state before stop
4407 					 * clears it */
4408 					pmpriv->adhoc_state_prev =
4409 						pmpriv->adhoc_state;
4410 				}
4411 				if (pmpriv->media_connected == MTRUE) {
4412 					wlan_disconnect(pmpriv, MNULL, MNULL);
4413 					break; /* leads to exit case */
4414 				}
4415 			}
4416 #endif
4417 		}
4418 
4419 		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
4420 		    ret == MLAN_STATUS_FAILURE)
4421 			break; /* EXIT CASE */
4422 		/* else */
4423 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4424 		pstate_rdh->stage = RDH_SET_NEW_CHANNEL;
4425 
4426 		if (pmadapter->dfs_test_params.no_channel_change_on_radar) {
4427 			PRINTM(MCMD_D,
4428 			       "dfs_testing - no channel change on radar."
4429 			       "  Overwrite new_chan = curr_chan.\n");
4430 			pstate_rdh->new_channel = pstate_rdh->curr_channel;
4431 			pstate_rdh->priv_curr_idx =
4432 				RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4433 			pstate_rdh->stage = RDH_RESTART_INTFS;
4434 			goto rdh_restart_intfs; /* skip next stage */
4435 		}
4436 		/* fall through */
4437 
4438 	case RDH_SET_NEW_CHANNEL:
4439 		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
4440 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
4441 		       pstate_rdh->priv_curr_idx);
4442 
4443 		/* only set new channel for UAP intfs */
4444 		while ((++pstate_rdh->priv_curr_idx) <
4445 		       pstate_rdh->priv_list_count) {
4446 			pmpriv =
4447 				pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
4448 #ifdef UAP_SUPPORT
4449 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
4450 				pmpriv->uap_state_chan_cb.pioctl_req_curr =
4451 					MNULL;
4452 				pmpriv->uap_state_chan_cb.get_chan_callback =
4453 					wlan_11h_radar_detected_callback;
4454 
4455 				/* DFS only in 5GHz */
4456 				wlan_11h_update_bandcfg(
4457 					pmpriv, &pstate_rdh->uap_band_cfg,
4458 					pstate_rdh->new_channel);
4459 				PRINTM(MCMD_D,
4460 				       "RDH_SET_NEW_CHANNEL: uAP band config = 0x%x channel=%d\n",
4461 				       pstate_rdh->uap_band_cfg,
4462 				       pstate_rdh->new_channel);
4463 
4464 				ret = wlan_uap_set_channel(
4465 					pmpriv, pstate_rdh->uap_band_cfg,
4466 					pstate_rdh->new_channel);
4467 				break; /* leads to exit case */
4468 			}
4469 #endif
4470 		}
4471 
4472 		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
4473 		    ret == MLAN_STATUS_FAILURE)
4474 			break; /* EXIT CASE (for UAP) */
4475 		/* else */
4476 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4477 		pstate_rdh->stage = RDH_RESTART_INTFS;
4478 		/* fall through */
4479 
4480 	case RDH_RESTART_INTFS:
4481 	rdh_restart_intfs:
4482 		PRINTM(MCMD_D, "%s(): stage(%d)=%s, priv_idx=%d\n", __func__,
4483 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage],
4484 		       pstate_rdh->priv_curr_idx);
4485 
4486 		/* can only restart master intfs */
4487 		while ((++pstate_rdh->priv_curr_idx) <
4488 		       pstate_rdh->priv_list_count) {
4489 			pmpriv =
4490 				pstate_rdh->priv_list[pstate_rdh->priv_curr_idx];
4491 #ifdef UAP_SUPPORT
4492 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
4493 				if (wlan_11h_radar_detect_required(
4494 					    pmpriv, pstate_rdh->new_channel)) {
4495 					/* Radar detection is required for this
4496 					   channel, make sure 11h is activated
4497 					   in the firmware */
4498 					ret = wlan_11h_activate(pmpriv, MNULL,
4499 								MTRUE);
4500 					ret = wlan_11h_config_master_radar_det(
4501 						pmpriv, MTRUE);
4502 					ret = wlan_11h_check_update_radar_det_state(
4503 						pmpriv);
4504 				}
4505 				ret = wlan_prepare_cmd(pmpriv,
4506 						       HOST_CMD_APCMD_BSS_START,
4507 						       HostCmd_ACT_GEN_SET, 0,
4508 						       MNULL, MNULL);
4509 				break; /* leads to exit case */
4510 			}
4511 #endif
4512 #ifdef STA_SUPPORT
4513 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
4514 				/* Check previous state to find former
4515 				 * Ad-hoc creator interface. Set new
4516 				 * state to Starting, so it'll be seen
4517 				 * as a DFS master. */
4518 				if (pmpriv->adhoc_state_prev == ADHOC_STARTED) {
4519 					pmpriv->adhoc_state = ADHOC_STARTING;
4520 					pmpriv->adhoc_state_prev = ADHOC_IDLE;
4521 				}
4522 				if (wlan_11h_is_dfs_master(pmpriv)) {
4523 					/* set new adhoc channel here */
4524 					pmpriv->adhoc_channel =
4525 						pstate_rdh->new_channel;
4526 					if (wlan_11h_radar_detect_required(
4527 						    pmpriv,
4528 						    pstate_rdh->new_channel)) {
4529 						/* Radar detection is required
4530 						   for this channel, make sure
4531 						   11h is activated in the
4532 						   firmware */
4533 						ret = wlan_11h_activate(
4534 							pmpriv, MNULL, MTRUE);
4535 						if (ret)
4536 							break;
4537 						ret = wlan_11h_config_master_radar_det(
4538 							pmpriv, MTRUE);
4539 						if (ret)
4540 							break;
4541 						ret = wlan_11h_check_update_radar_det_state(
4542 							pmpriv);
4543 						if (ret)
4544 							break;
4545 					}
4546 					ret = wlan_prepare_cmd(
4547 						pmpriv,
4548 						HostCmd_CMD_802_11_AD_HOC_START,
4549 						HostCmd_ACT_GEN_SET, 0, MNULL,
4550 						&pmpriv->adhoc_last_start_ssid);
4551 					break; /* leads to exit case */
4552 				}
4553 
4554 				/* NOTE:  DON'T reconnect slave STA intfs -
4555 				 * infra/adhoc_joiner Do we want to return to
4556 				 * same AP/network (on radar channel)? If want
4557 				 * to connect back, depend on either:
4558 				 *     1. driver's reassoc thread
4559 				 *     2. wpa_supplicant, or other user-space
4560 				 * app
4561 				 */
4562 			}
4563 #endif
4564 		}
4565 
4566 		if (pstate_rdh->priv_curr_idx < pstate_rdh->priv_list_count ||
4567 		    ret == MLAN_STATUS_FAILURE)
4568 			break; /* EXIT CASE (for UAP) */
4569 		/* else */
4570 		pstate_rdh->priv_curr_idx = RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4571 		pstate_rdh->stage = RDH_RESTART_TRAFFIC;
4572 		/* fall through */
4573 
4574 	case RDH_RESTART_TRAFFIC:
4575 		PRINTM(MCMD_D, "%s(): stage(%d)=%s\n", __func__,
4576 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
4577 		/* remove custome ie */
4578 		if (pmadapter->ecsa_enable) {
4579 			mlan_ioctl_req *pioctl_req = MNULL;
4580 			pstate_rdh->priv_curr_idx =
4581 				RDH_STAGE_FIRST_ENTRY_PRIV_IDX;
4582 			while ((++pstate_rdh->priv_curr_idx) <
4583 			       pstate_rdh->priv_list_count) {
4584 				pmpriv = pstate_rdh->priv_list
4585 						 [pstate_rdh->priv_curr_idx];
4586 				if (!wlan_11h_is_dfs_master(pmpriv))
4587 					continue;
4588 				ret = wlan_11h_prepare_custom_ie_chansw(
4589 					pmadapter, &pioctl_req, MFALSE);
4590 				if ((ret != MLAN_STATUS_SUCCESS) ||
4591 				    !pioctl_req) {
4592 					PRINTM(MERROR,
4593 					       "%s(): Error in preparing CHAN_SW IE.\n",
4594 					       __func__);
4595 					break; /* EXIT CASE */
4596 				}
4597 
4598 				pioctl_req->bss_index = pmpriv->bss_index;
4599 
4600 				ret = wlan_misc_ioctl_custom_ie_list(
4601 					pmadapter, pioctl_req, MFALSE);
4602 				if (ret != MLAN_STATUS_SUCCESS &&
4603 				    ret != MLAN_STATUS_PENDING) {
4604 					PRINTM(MERROR,
4605 					       "%s(): Could not remove IE for priv=%p [priv_bss_idx=%d]!\n",
4606 					       __func__, pmpriv,
4607 					       pmpriv->bss_index);
4608 					/* TODO: hiow to handle this error
4609 					 * case??  ignore & continue? */
4610 				}
4611 				/* free ioctl buffer memory before we leave */
4612 				pmadapter->callbacks.moal_mfree(
4613 					pmadapter->pmoal_handle,
4614 					(t_u8 *)pioctl_req);
4615 			}
4616 		}
4617 		/* continue traffic for reactivated interfaces */
4618 		PRINTM(MMSG,
4619 		       "11h: Radar Detected - restarting host tx traffic.\n");
4620 		for (i = 0; i < pstate_rdh->priv_list_count; i++)
4621 			wlan_11h_tx_enable(pstate_rdh->priv_list[i]);
4622 
4623 		pstate_rdh->stage = RDH_OFF; /* DONE! */
4624 		PRINTM(MCMD_D, "%s(): finished - stage(%d)=%s\n", __func__,
4625 		       pstate_rdh->stage, rdh_stage_str[pstate_rdh->stage]);
4626 
4627 		break;
4628 
4629 	default:
4630 		pstate_rdh->stage = RDH_OFF; /* cancel RDH to unblock Tx packets
4631 					      */
4632 		break;
4633 	}
4634 
4635 	LEAVE();
4636 	return ret;
4637 }
4638 
4639 /**
4640  *  @brief DFS Event Preprocessing.
4641  *  Operates directly on pmadapter variables.
4642  *
4643  *  1. EVENT_RADAR_DETECTED comes from firmware without specific
4644  *     bss_num/bss_type.  Find it an appropriate interface and
4645  *     update event_cause field in event_buf.
4646  *
4647  *  @param pmadapter    Pointer to mlan_adapter
4648  *
4649  *  @return    MLAN_STATUS_SUCCESS (update successful)
4650  *          or MLAN_STATUS_FAILURE (no change)
4651  */
wlan_11h_dfs_event_preprocessing(mlan_adapter * pmadapter)4652 mlan_status wlan_11h_dfs_event_preprocessing(mlan_adapter *pmadapter)
4653 {
4654 	mlan_status ret = MLAN_STATUS_FAILURE;
4655 	mlan_private *pmpriv = MNULL;
4656 	mlan_private *priv_list[MLAN_MAX_BSS_NUM] = {MNULL};
4657 
4658 	ENTER();
4659 	switch (pmadapter->event_cause & EVENT_ID_MASK) {
4660 	case EVENT_RADAR_DETECTED:
4661 		/* find active intf:  prefer dfs_master over dfs_slave */
4662 		if (wlan_get_privs_by_two_cond(
4663 			    pmadapter, wlan_11h_is_master_active_on_dfs_chan,
4664 			    wlan_11h_is_dfs_master, MTRUE, priv_list)) {
4665 			pmpriv = priv_list[0];
4666 			PRINTM(MINFO, "%s: found dfs_master priv=%p\n",
4667 			       __func__, pmpriv);
4668 		} else if (wlan_get_privs_by_two_cond(
4669 				   pmadapter,
4670 				   wlan_11h_is_slave_active_on_dfs_chan,
4671 				   wlan_11h_is_dfs_slave, MTRUE, priv_list)) {
4672 			pmpriv = priv_list[0];
4673 			PRINTM(MINFO, "%s: found dfs_slave priv=%p\n", __func__,
4674 			       pmpriv);
4675 		} else if (pmadapter->state_dfs.dfs_check_pending ||
4676 			   pmadapter->state_dfs.dfs_check_channel) {
4677 			pmpriv = (mlan_private *)(pmadapter->state_dfs
4678 							  .dfs_check_priv);
4679 			PRINTM(MINFO, "%s: found dfs priv=%p\n", __func__,
4680 			       pmpriv);
4681 		}
4682 
4683 		/* update event_cause if we found an appropriate priv */
4684 		if (pmpriv) {
4685 			pmlan_buffer pmevbuf = pmadapter->pmlan_buffer_event;
4686 			t_u32 new_event_cause =
4687 				pmadapter->event_cause & EVENT_ID_MASK;
4688 			new_event_cause |=
4689 				((GET_BSS_NUM(pmpriv) & 0xff) << 16) |
4690 				((pmpriv->bss_type & 0xff) << 24);
4691 			PRINTM(MINFO, "%s: priv - bss_num=%d, bss_type=%d\n",
4692 			       __func__, GET_BSS_NUM(pmpriv), pmpriv->bss_type);
4693 			memcpy_ext(pmadapter,
4694 				   pmevbuf->pbuf + pmevbuf->data_offset,
4695 				   &new_event_cause, sizeof(new_event_cause),
4696 				   sizeof(new_event_cause));
4697 			ret = MLAN_STATUS_SUCCESS;
4698 		} else {
4699 			PRINTM(MERROR,
4700 			       "Failed to find dfs master/slave priv\n");
4701 			ret = MLAN_STATUS_FAILURE;
4702 		}
4703 		break;
4704 	}
4705 
4706 	LEAVE();
4707 	return ret;
4708 }
4709 
4710 /**
4711  *  @brief try to switch to a non-dfs channel
4712  *
4713  *  @param priv    Void pointer to mlan_private
4714  *
4715  *  @param chan    pointer to channel
4716  *
4717  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or MLAN_STATUS_PENDING
4718  */
wlan_11h_switch_non_dfs_chan(mlan_private * priv,t_u8 * chan)4719 mlan_status wlan_11h_switch_non_dfs_chan(mlan_private *priv, t_u8 *chan)
4720 {
4721 	mlan_status ret = MLAN_STATUS_FAILURE;
4722 	t_u32 i;
4723 	t_u32 rand_entry;
4724 	t_u8 def_chan;
4725 	t_u8 rand_tries = 0;
4726 	region_chan_t *chn_tbl = MNULL;
4727 	pmlan_adapter pmadapter = priv->adapter;
4728 
4729 	ENTER();
4730 
4731 	if (!pmadapter->dfs_test_params.no_channel_change_on_radar &&
4732 	    pmadapter->dfs_test_params.fixed_new_channel_on_radar) {
4733 		PRINTM(MCMD_D, "dfs_testing - user fixed new_chan=%d\n",
4734 		       pmadapter->dfs_test_params.fixed_new_channel_on_radar);
4735 		*chan = pmadapter->dfs_test_params.fixed_new_channel_on_radar;
4736 
4737 		LEAVE();
4738 		return MLAN_STATUS_SUCCESS;
4739 	}
4740 
4741 	/*get the channel table first*/
4742 	for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
4743 		if (pmadapter->region_channel[i].band == BAND_A &&
4744 		    pmadapter->region_channel[i].valid) {
4745 			chn_tbl = &pmadapter->region_channel[i];
4746 			break;
4747 		}
4748 	}
4749 
4750 	if (!chn_tbl || !chn_tbl->pcfp)
4751 		goto done;
4752 
4753 	do {
4754 		rand_entry =
4755 			wlan_11h_get_random_num(pmadapter) % chn_tbl->num_cfp;
4756 		def_chan = (t_u8)chn_tbl->pcfp[rand_entry].channel;
4757 		rand_tries++;
4758 	} while ((wlan_11h_is_channel_under_nop(pmadapter, def_chan) ||
4759 		  chn_tbl->pcfp[rand_entry].passive_scan_or_radar_detect ==
4760 			  MTRUE) &&
4761 		 (rand_tries < MAX_SWITCH_CHANNEL_RETRIES));
4762 
4763 	/* meet max retries, use the lowest non-dfs channel */
4764 	if (rand_tries == MAX_SWITCH_CHANNEL_RETRIES) {
4765 		for (i = 0; i < chn_tbl->num_cfp; i++) {
4766 			if (chn_tbl->pcfp[i].passive_scan_or_radar_detect ==
4767 				    MFALSE &&
4768 			    !wlan_11h_is_channel_under_nop(
4769 				    pmadapter,
4770 				    (t_u8)chn_tbl->pcfp[i].channel)) {
4771 				def_chan = (t_u8)chn_tbl->pcfp[i].channel;
4772 				break;
4773 			}
4774 		}
4775 		if (i == chn_tbl->num_cfp)
4776 			goto done;
4777 	}
4778 
4779 	*chan = def_chan;
4780 	ret = MLAN_STATUS_SUCCESS;
4781 done:
4782 	LEAVE();
4783 	return ret;
4784 }
4785 
4786 /**
4787  *  @brief set dfs check channel
4788  *
4789  *  @param priv    Void pointer to mlan_private
4790  *
4791  *  @param chan    pointer to channel
4792  *  @param bandwidth    band width
4793  *
4794  *  @return  N/A
4795  */
wlan_11h_set_dfs_check_chan(mlan_private * priv,t_u8 chan,t_u8 bandwidth)4796 void wlan_11h_set_dfs_check_chan(mlan_private *priv, t_u8 chan, t_u8 bandwidth)
4797 {
4798 	wlan_dfs_device_state_t *pstate_dfs = &priv->adapter->state_dfs;
4799 	ENTER();
4800 	pstate_dfs->dfs_check_channel = chan;
4801 	pstate_dfs->dfs_check_bandwidth = bandwidth;
4802 	PRINTM(MCMND, "Set dfs_check_channel=%d\n", chan);
4803 	LEAVE();
4804 }
4805 
4806 /**
4807  *  @brief 802.11h DFS W53 configuration
4808  *
4809  *  @param pmadapter    Pointer to mlan_adapter
4810  *  @param pioctl_req   Pointer to mlan_ioctl_req
4811  *
4812  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4813  */
wlan_11h_ioctl_dfs_w53_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4814 mlan_status wlan_11h_ioctl_dfs_w53_cfg(pmlan_adapter pmadapter,
4815 				       pmlan_ioctl_req pioctl_req)
4816 {
4817 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
4818 	mlan_ds_11h_dfs_w53_cfg *dfs_w53_cfg = MNULL;
4819 
4820 	ENTER();
4821 
4822 	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
4823 	dfs_w53_cfg = &ds_11hcfg->param.dfs_w53_cfg;
4824 
4825 	if (pioctl_req->action == MLAN_ACT_GET) {
4826 		dfs_w53_cfg->dfs53cfg = pmadapter->dfs53cfg;
4827 	} else {
4828 		pmadapter->dfs53cfg = dfs_w53_cfg->dfs53cfg;
4829 	}
4830 
4831 	LEAVE();
4832 
4833 	return MLAN_STATUS_SUCCESS;
4834 }
4835 
4836 /**
4837  *  @brief 802.11h DFS mode configuration
4838  *
4839  *  @param pmadapter    Pointer to mlan_adapter
4840  *  @param pioctl_req   Pointer to mlan_ioctl_req
4841  *
4842  *  @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4843  */
wlan_11h_ioctl_dfs_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4844 mlan_status wlan_11h_ioctl_dfs_mode(pmlan_adapter pmadapter,
4845 				    pmlan_ioctl_req pioctl_req)
4846 {
4847 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
4848 
4849 	ENTER();
4850 
4851 	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
4852 
4853 	if (pioctl_req->action == MLAN_ACT_GET) {
4854 		ds_11hcfg->param.dfs_mode = pmadapter->dfs_mode;
4855 	} else {
4856 		pmadapter->dfs_mode = ds_11hcfg->param.dfs_mode;
4857 	}
4858 	LEAVE();
4859 	return MLAN_STATUS_SUCCESS;
4860 }
4861