xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c (revision b6ef4fe306b6abd9485ff7d6ca12da80552e7caf)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: API for processing radar found indication.
22  *
23  */
24 
25 #include "../dfs.h"
26 #include "../dfs_zero_cac.h"
27 #include "../dfs_process_radar_found_ind.h"
28 #include <wlan_reg_services_api.h>
29 #include <wlan_objmgr_vdev_obj.h>
30 #include <wlan_dfs_utils_api.h>
31 #include <wlan_dfs_tgt_api.h>
32 #include "wlan_dfs_mlme_api.h"
33 #include "../dfs_internal.h"
34 /**
35  * TODO: The code is not according to the following description needs
36  * modification and correction. Code always adds left and right channels to
37  * NOL even if it is not a chirp radar.
38  *
39  * A) If chirp radar starts at boundary and ends at boundary then three channels
40  *    will be affected.
41  *    freq_offset.freq[0] = fn   (Center frequency)
42  *    freq_offset.freq[1] = fn-1 (Left of center)
43  *    freq_offset.freq[2] = fn+1 (Right of center)
44  *
45  *    Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL.
46  *
47  *                     Chirp start freq         Chirp end freq
48  *                             |                       |
49  *                             |                       |
50  *                             V                       V
51  *      _______________________________________________________________________
52  *     |       center freq     |       center freq     |       center freq     |
53  *     |          ch(n-1)      |          ch(n)        |          ch(n+1)      |
54  *     |           |           |           |           |           |           |
55  *     |           |           |           |           |           |           |
56  *     |           |           |           |           |           |           |
57  *                fn-1                    fn         boundary     fn+1
58  *     <-------- 20 Mhz ------>
59  *
60  * B) If chirp radar starts at one channel and continues up to another channel
61  *    then two channels will be affected.
62  *    freq_offset.freq[0] = fn
63  *    freq_offset.freq[1] = 0
64  *    freq_offset.freq[2] = fn+1
65  *
66  *    Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL.
67  *
68  *                                   Chirp start freq         Chirp end freq
69  *                                           |                       |
70  *                                           |                       |
71  *                                           V                       V
72  *      _______________________________________________________________________
73  *     |       center freq     |       center freq     |       center freq     |
74  *     |          ch(n-1)      |          ch(n)        |          ch(n+1)      |
75  *     |           |           |           |           |           |           |
76  *     |           |           |           |           |           |           |
77  *     |           |           |           |           |           |           |
78  *                fn-1                    fn         boundary     fn+1
79  *     <-------- 20 Mhz ------>
80  *
81  * C) Radar found at boundary, two channels will be affected.
82  *    freq_offset.freq[0] = fn
83  *    freq_offset.freq[1] = 0
84  *    freq_offset.freq[2] = fn+1
85  *
86  *    Two channels, ch(n) and ch(n+1) will be added to NOL.
87  *
88  *                                            dfs_freq_offset (radar found freq)
89  *                                                     |
90  *                                                     |
91  *                                                     V
92  *      _______________________________________________________________________
93  *     |       center freq     |       center freq     |       center freq     |
94  *     |          ch(n-1)      |          ch(n)        |          ch(n+1)      |
95  *     |           |           |           |           |           |           |
96  *     |           |           |           |           |           |           |
97  *     |           |           |           |           |           |           |
98  *                fn-1                    fn         boundary     fn+1
99  *     <-------- 20 Mhz ------>
100  *
101  *
102  * D) Else only one channel will be affected.
103  *    freq_offset.freq[0] = fn
104  *    freq_offset.freq[1] = 0
105  *    freq_offset.freq[2] = 0
106  *
107  *   One channel ch(n) will be added to NOL.
108  *
109  *
110  *                                            dfs_freq_offset (radar found freq)
111  *                                                |
112  *                                                |
113  *                                                V
114  *      _______________________________________________________________________
115  *     |       center freq     |       center freq     |       center freq     |
116  *     |          ch(n-1)      |          ch(n)        |          ch(n+1)      |
117  *     |           |           |           |           |           |           |
118  *     |           |           |           |           |           |           |
119  *     |           |           |           |           |           |           |
120  *                fn-1                    fn         boundary     fn+1
121  *     <-------- 20 Mhz ------>
122  */
123 
124 int dfs_set_nol_subchannel_marking(struct wlan_dfs *dfs,
125 				   bool nol_subchannel_marking)
126 {
127 	QDF_STATUS status = QDF_STATUS_SUCCESS;
128 
129 	if (!dfs)
130 		return -EIO;
131 
132 	dfs->dfs_use_nol_subchannel_marking = nol_subchannel_marking;
133 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "NOL subchannel marking is %s ",
134 		 (nol_subchannel_marking) ? "set" : "disabled");
135 	if (dfs->dfs_is_offload_enabled)
136 		status = tgt_dfs_send_subchan_marking(dfs->dfs_pdev_obj,
137 						      nol_subchannel_marking);
138 
139 	return qdf_status_to_os_return(status);
140 }
141 
142 int dfs_get_nol_subchannel_marking(struct wlan_dfs *dfs,
143 				   bool *nol_subchannel_marking)
144 {
145 	if (!dfs)
146 		return -EIO;
147 
148 	(*nol_subchannel_marking) = dfs->dfs_use_nol_subchannel_marking;
149 
150 	return 0;
151 }
152 
153 #ifdef CONFIG_CHAN_FREQ_API
154 QDF_STATUS
155 dfs_radar_add_channel_list_to_nol_for_freq(struct wlan_dfs *dfs,
156 					   uint16_t *freq_list,
157 					   uint16_t *nol_freq_list,
158 					   uint8_t *num_channels)
159 {
160 	int i;
161 	uint16_t last_chan_freq = 0;
162 	uint8_t num_ch = 0;
163 
164 	if (*num_channels > MAX_20MHZ_SUBCHANS) {
165 		dfs_err(dfs, WLAN_DEBUG_DFS,
166 			"Invalid num channels: %d", *num_channels);
167 		return QDF_STATUS_E_FAILURE;
168 	}
169 
170 	for (i = 0; i < *num_channels; i++) {
171 		if (freq_list[i] == 0 ||
172 		    freq_list[i] == last_chan_freq)
173 			continue;
174 		if (!utils_is_dfs_chan_for_freq(dfs->dfs_pdev_obj,
175 						freq_list[i])) {
176 			dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip",
177 				 freq_list[i]);
178 			continue;
179 		}
180 
181 		last_chan_freq = freq_list[i];
182 		DFS_NOL_ADD_CHAN_LOCKED(dfs,
183 					freq_list[i],
184 					dfs->wlan_dfs_nol_timeout);
185 		nol_freq_list[num_ch++] = last_chan_freq;
186 		utils_dfs_deliver_event(dfs->dfs_pdev_obj,
187 					freq_list[i],
188 					WLAN_EV_NOL_STARTED);
189 		dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL",
190 			 last_chan_freq);
191 	}
192 
193 	if (!num_ch) {
194 		dfs_err(dfs, WLAN_DEBUG_DFS,
195 			"dfs channels not found in channel list");
196 		return QDF_STATUS_E_FAILURE;
197 	}
198 	*num_channels = num_ch;
199 
200 	if (!dfs_get_disable_radar_marking(dfs)) {
201 		utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj,
202 						       nol_freq_list, num_ch,
203 						       DFS_NOL_SET);
204 
205 		if (dfs->dfs_is_stadfs_enabled)
206 			if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj))
207 				utils_dfs_reg_update_nol_history_chan_for_freq(
208 					dfs->dfs_pdev_obj, nol_freq_list,
209 					num_ch, DFS_NOL_HISTORY_SET);
210 	}
211 
212 	dfs_nol_update(dfs);
213 	utils_dfs_save_nol(dfs->dfs_pdev_obj);
214 
215 	return QDF_STATUS_SUCCESS;
216 }
217 #endif
218 /**
219  * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz
220  * @freq_offset: freq offset
221  * @center_freq: center frequency
222  *
223  * Find frequency offsets for 80MHz
224  *
225  * Return: None
226  */
227 static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset,
228 				  uint32_t center_freq)
229 {
230 	int i;
231 
232 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
233 		if (freq_offset->offset[i] < DFS_OFFSET_SECOND_LOWER)
234 			freq_offset->freq[i] =
235 				DFS_THIRD_LOWER_CHANNEL(center_freq);
236 		else if ((freq_offset->offset[i] > DFS_OFFSET_SECOND_LOWER) &&
237 			 (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER))
238 			freq_offset->freq[i] =
239 				DFS_SECOND_LOWER_CHANNEL(center_freq);
240 		else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) &&
241 			 (freq_offset->offset[i] < 0))
242 			freq_offset->freq[i] =
243 				DFS_FIRST_LOWER_CHANNEL(center_freq);
244 		else if ((freq_offset->offset[i] > 0) &&
245 			  (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER))
246 			freq_offset->freq[i] =
247 				DFS_FIRST_UPPER_CHANNEL(center_freq);
248 		else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) &&
249 			 (freq_offset->offset[i] < DFS_OFFSET_SECOND_UPPER))
250 			freq_offset->freq[i] =
251 				DFS_SECOND_UPPER_CHANNEL(center_freq);
252 		else if (freq_offset->offset[i] > DFS_OFFSET_SECOND_UPPER)
253 			freq_offset->freq[i] =
254 				DFS_THIRD_UPPER_CHANNEL(center_freq);
255 	}
256 }
257 
258 /**
259  * dfs_radar_chan_for_40()- Find frequency offsets for 40MHz
260  * @freq_offset: freq offset
261  * @center_freq: center frequency
262  *
263  * Find frequency offsets for 40MHz
264  *
265  * Return: None
266  */
267 static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset,
268 				  uint32_t center_freq)
269 {
270 	int i;
271 
272 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
273 		if (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER)
274 			freq_offset->freq[i] =
275 				DFS_SECOND_LOWER_CHANNEL(center_freq);
276 		else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) &&
277 			 (freq_offset->offset[i] < 0))
278 			freq_offset->freq[i] =
279 				DFS_FIRST_LOWER_CHANNEL(center_freq);
280 		else if ((freq_offset->offset[i] > 0) &&
281 			 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER))
282 			freq_offset->freq[i] =
283 				DFS_FIRST_UPPER_CHANNEL(center_freq);
284 		else if (freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER)
285 			freq_offset->freq[i] =
286 				DFS_SECOND_UPPER_CHANNEL(center_freq);
287 	}
288 }
289 
290 /**
291  * dfs_radar_chan_for_20()- Find frequency offsets for 20MHz
292  * @freq_offset: freq offset
293  * @center_freq: center frequency
294  *
295  * Find frequency offsets for 20MHz
296  *
297  * Return: None
298  */
299 static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset,
300 				  uint32_t center_freq)
301 {
302 	int i;
303 
304 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
305 		if (freq_offset->offset[i] <= DFS_20MZ_OFFSET_LOWER)
306 			freq_offset->freq[i] =
307 				DFS_20MHZ_LOWER_CHANNEL(center_freq);
308 		else if ((freq_offset->offset[i] > DFS_20MZ_OFFSET_LOWER) &&
309 			  (freq_offset->offset[i] < DFS_20MZ_OFFSET_UPPER))
310 			freq_offset->freq[i] = center_freq;
311 		else if (freq_offset->offset[i] >= DFS_20MZ_OFFSET_UPPER)
312 			freq_offset->freq[i] =
313 				DFS_20MHZ_UPPER_CHANNEL(center_freq);
314 	}
315 }
316 
317 #ifdef CONFIG_CHAN_FREQ_API
318 void
319 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs,
320 			      struct radar_found_info *radar_found,
321 			      uint32_t *freq_center)
322 {
323 	struct dfs_channel *curchan = dfs->dfs_curchan;
324 
325 	/* In case of 11BE Chipsets, radar found center frequency is
326 	 * directly obtained from WMI.
327 	 */
328 	if (dfs->dfs_is_radar_found_chan_freq_eq_center_freq) {
329 		*freq_center = radar_found->chan_freq;
330 		return;
331 	}
332 
333 	/* Radar found on agile detector ID.
334 	 * Applicable to chips that have a separate agile radar detector
335 	 * engine.
336 	 */
337 	if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) {
338 		*freq_center = dfs->dfs_agile_precac_freq_mhz;
339 		if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) {
340 			if (radar_found->segment_id == PRIMARY_SEG)
341 				*freq_center -= DFS_160MHZ_SECOND_SEG_OFFSET;
342 			else
343 				*freq_center += DFS_160MHZ_SECOND_SEG_OFFSET;
344 		} else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ &&
345 			   dfs->dfs_agile_precac_freq_mhz ==
346 				RESTRICTED_80P80_CHAN_CENTER_FREQ) {
347 			/*
348 			 * The reason why left and right offsets
349 			 * are different.
350 			 * Center of 165 is 5730MHz.
351 			 * Center of left 80 is 5690MHz.
352 			 * Center of right 80 is 5775MHz.
353 			 */
354 			if (radar_found->segment_id == PRIMARY_SEG)
355 				*freq_center -=
356 				    DFS_165MHZ_SECOND_SEG_OFFSET_LEFT;
357 			else
358 				*freq_center +=
359 				    DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT;
360 		}
361 	} else if (!radar_found->segment_id) {
362 		*freq_center = curchan->dfs_ch_mhz_freq_seg1;
363 	} else {
364 		/* Radar found on secondary segment by the HW, when preCAC
365 		 * was not running in legacy chips or preCAC was running
366 		 * in Lithium chips.
367 		 */
368 		*freq_center = curchan->dfs_ch_mhz_freq_seg2;
369 		if (WLAN_IS_CHAN_MODE_160(curchan)) {
370 			/* If center frequency of entire 160 band
371 			 * is less than center frequency of primary
372 			 * segment, then the center frequency of
373 			 * secondary segment is -40 of center
374 			 * frequency of entire 160 segment.
375 			 */
376 			if (curchan->dfs_ch_mhz_freq_seg2 <
377 			    curchan->dfs_ch_mhz_freq_seg1)
378 				*freq_center -=
379 					DFS_160MHZ_SECOND_SEG_OFFSET;
380 			else
381 				*freq_center +=
382 					DFS_160MHZ_SECOND_SEG_OFFSET;
383 		}
384 	}
385 }
386 #endif
387 
388 /**
389  * dfs_find_radar_affected_subchans_for_freq() - Find radar affected sub chans.
390  * @dfs: Pointer to wlan_dfs structure.
391  * @radar_found: Pointer to radar_found structure.
392  * @freq_list: Pointer to save radar affected channels.
393  * @freq_center: Freq_center of the radar affected chan.
394  *
395  * Return: Number of channels.
396  */
397 #ifdef CONFIG_CHAN_FREQ_API
398 static uint8_t
399 dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs *dfs,
400 					  struct radar_found_info *radar_found,
401 					  uint16_t *freq_list,
402 					  uint32_t freq_center)
403 {
404 	int i, j;
405 	uint8_t num_radar_subchans;
406 	uint32_t flag;
407 	int32_t sidx;
408 	uint16_t candidate_subchan_freq;
409 	uint16_t cur_subchans[MAX_20MHZ_SUBCHANS];
410 	uint8_t n_cur_subchans;
411 	struct dfs_channel *curchan = dfs->dfs_curchan;
412 	struct freqs_offsets freq_offset;
413 
414 	qdf_mem_zero(&freq_offset, sizeof(freq_offset));
415 	flag = curchan->dfs_ch_flags;
416 
417 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++)
418 		freq_offset.offset[i] = radar_found->freq_offset;
419 
420 	sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset);
421 
422 	dfs_info(dfs, WLAN_DEBUG_DFS,
423 		 "seg=%d, det=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d",
424 		 radar_found->segment_id, radar_found->detector_id, sidx,
425 		 radar_found->freq_offset, radar_found->is_chirp,
426 		 flag, freq_center);
427 
428 	if ((WLAN_IS_CHAN_A(curchan)) ||
429 	    WLAN_IS_CHAN_MODE_20(curchan)) {
430 		if (radar_found->is_chirp ||
431 		    (sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) {
432 			freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
433 			freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
434 		}
435 		dfs_radar_chan_for_20(&freq_offset, freq_center);
436 	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
437 		if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
438 			freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
439 			freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
440 		}
441 		dfs_radar_chan_for_40(&freq_offset, freq_center);
442 	} else if (WLAN_IS_CHAN_MODE_80(curchan) ||
443 			WLAN_IS_CHAN_MODE_160(curchan) ||
444 			WLAN_IS_CHAN_MODE_80_80(curchan) ||
445 			WLAN_IS_CHAN_MODE_320(curchan)) {
446 		if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
447 			freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
448 			freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
449 		}
450 		dfs_radar_chan_for_80(&freq_offset, freq_center);
451 	} else {
452 		dfs_err(dfs, WLAN_DEBUG_DFS,
453 			"channel flag=%d is invalid", flag);
454 		return 0;
455 	}
456 
457 	n_cur_subchans =
458 	    dfs_get_bonding_channels_for_freq(dfs, curchan,
459 					      radar_found->segment_id,
460 					      radar_found->detector_id,
461 					      cur_subchans);
462 
463 	for (i = 0, num_radar_subchans = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
464 		candidate_subchan_freq = freq_offset.freq[i];
465 		for (j = 0; j < n_cur_subchans; j++) {
466 			if (cur_subchans[j] == candidate_subchan_freq) {
467 				freq_list[num_radar_subchans++] =
468 						candidate_subchan_freq;
469 				dfs_info(dfs, WLAN_DEBUG_DFS,
470 					 "offset=%d, channel=%d",
471 					 num_radar_subchans,
472 					 freq_list[num_radar_subchans - 1]);
473 				break;
474 			}
475 		}
476 	}
477 	return num_radar_subchans;
478 }
479 #endif
480 
481 /**
482  * dfs_calc_bonding_freqs: Calculate bonding channel frequencies from the
483  * channel width's center frequency and channel width.
484  * It is assumed that the caller has allocated sufficient memory for 'freq_list'
485  * so that it can hold all the output subchannels.
486  *
487  * center_freq: Center frequency of the channel width.
488  * ch_width: Channel width.
489  * freq_list: output array of sub-channel frequencies.
490  *
491  * Return: void
492  */
493 static void
494 dfs_calc_bonding_freqs(qdf_freq_t center_freq,
495 		       uint16_t ch_width,
496 		       uint16_t *freq_list)
497 {
498 #define CHAN_SPACING_MHZ_5G 20
499 #define SUB20CHAN_BW_MHZ_5G 20
500 	uint8_t nchans = ch_width / CHAN_SPACING_MHZ_5G;
501 	qdf_freq_t first_subchan_cfreq = center_freq - (ch_width / 2) +
502 					 (SUB20CHAN_BW_MHZ_5G / 2);
503 	uint8_t i;
504 
505 	for (i = 0; i < nchans; ++i)
506 		freq_list[i] = first_subchan_cfreq + (i * CHAN_SPACING_MHZ_5G);
507 }
508 
509 /**
510  * dfs_get_20mhz_bonding_channels() - Get bonding frequency list of 20MHz
511  * channel.
512  * @center_freq: Center frequency of the 20MHz channel.
513  * @freq_list: Pointer to frequency list.
514  *
515  * Return: void
516  */
517 static
518 void dfs_get_20mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
519 {
520 	uint16_t chwidth = BW_20;
521 
522 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
523 }
524 
525 /**
526  * dfs_get_40mhz_bonding_channels() - Get bonding frequency list of 40MHz
527  * channel.
528  * @center_freq: Center frequency of the 40MHz channel.
529  * @freq_list: Pointer to frequency list.
530  *
531  * Return: void
532  */
533 static
534 void dfs_get_40mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
535 {
536 	uint16_t chwidth = BW_40;
537 
538 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
539 }
540 
541 /**
542  * dfs_get_80mhz_bonding_channels() - Get bonding frequency list of 80MHz
543  * channel.
544  * @center_freq: Center frequency of the 80MHz channel.
545  * @freq_list: Pointer to frequency list.
546  *
547  * Return: void
548  */
549 static
550 void dfs_get_80mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
551 {
552 	uint16_t chwidth = BW_80;
553 
554 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
555 }
556 
557 /**
558  * dfs_get_160mhz_bonding_channels() - Get bonding frequency list of 160MHz
559  * channel.
560  * @center_freq: Center frequency of the 160MHz channel.
561  * @freq_list: Pointer to frequency list.
562  *
563  * Return: void
564  */
565 static
566 void dfs_get_160mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
567 {
568 	uint16_t chwidth = BW_160;
569 
570 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
571 }
572 
573 /**
574  * dfs_get_320mhz_bonding_channels() - Get bonding frequency list of 320MHz
575  * channel.
576  * @center_freq: Center frequency of the 320MHz channel.
577  * @freq_list: Pointer to frequency list.
578  *
579  * Return: void
580  */
581 #ifdef WLAN_FEATURE_11BE
582 static
583 void dfs_get_320mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list,
584 				     uint8_t *nchannels)
585 {
586 	uint16_t chwidth = 320;
587 
588 	*nchannels = 16;
589 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
590 }
591 #else
592 static
593 void dfs_get_320mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list,
594 				     uint8_t *nchannels)
595 {
596 	*nchannels = 0;
597 	dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
598 		  "320MHz chan width for non 11be");
599 }
600 #endif
601 
602 /*
603  * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding frequency
604  * list.
605  * @chan: Pointer to dfs_channel.
606  * @freq_list: Pointer to frequency list.
607  */
608 #ifdef CONFIG_CHAN_FREQ_API
609 uint8_t
610 dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan,
611 						  uint16_t *freq_list)
612 {
613 	uint16_t center_freq;
614 	uint8_t nchannels = 0;
615 
616 	center_freq = chan->dfs_ch_mhz_freq_seg1;
617 
618 	if (WLAN_IS_CHAN_MODE_20(chan)) {
619 		nchannels = 1;
620 		dfs_get_20mhz_bonding_channels(center_freq,
621 					       freq_list);
622 	} else if (WLAN_IS_CHAN_MODE_40(chan)) {
623 		nchannels = 2;
624 		dfs_get_40mhz_bonding_channels(center_freq,
625 					       freq_list);
626 	} else if (WLAN_IS_CHAN_MODE_80(chan)) {
627 		nchannels = 4;
628 		dfs_get_80mhz_bonding_channels(center_freq,
629 					       freq_list);
630 	} else if (WLAN_IS_CHAN_MODE_80_80(chan)) {
631 		nchannels = 8;
632 		dfs_get_80mhz_bonding_channels(center_freq,
633 					       freq_list);
634 		center_freq = chan->dfs_ch_mhz_freq_seg2;
635 		dfs_get_80mhz_bonding_channels(center_freq,
636 					       freq_list + 4);
637 	} else if (WLAN_IS_CHAN_MODE_160(chan)) {
638 		nchannels = 8;
639 		center_freq = chan->dfs_ch_mhz_freq_seg2;
640 		dfs_get_160mhz_bonding_channels(center_freq, freq_list);
641 	} else if (WLAN_IS_CHAN_MODE_320(chan)) {
642 		center_freq = chan->dfs_ch_mhz_freq_seg2;
643 		dfs_get_320mhz_bonding_channels(center_freq, freq_list,
644 						&nchannels);
645 	}
646 
647 	return nchannels;
648 }
649 #endif
650 
651 #ifdef CONFIG_CHAN_FREQ_API
652 /*
653  * dfs_get_agile_subchans_for_curchan_160() - Get bonding frequency list of
654  * agile channels when current operating channel is 160MHz.
655  *
656  * @dfs: Pointer to DFS structure.
657  * @center_freq: Center frequency of the channel.
658  * @segment_id: Segment ID of interest. 0 for primary segment and 1 for
659  * secondary segment.
660  * @freq_list: Pointer to frequency list.
661  * @nchannels: Number of subchannel.
662  */
663 static void
664 dfs_get_agile_subchans_for_curchan_160(struct wlan_dfs *dfs,
665 				       uint16_t center_freq,
666 				       uint32_t segment_id,
667 				       uint16_t *freq_list,
668 				       uint8_t *nchannels)
669 {
670 	if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) {
671 		/*
672 		 * The current operating channel is 160MHz and
673 		 * the agile channel is 80MHz. This can happen
674 		 * in HK only.
675 		 */
676 		*nchannels = 4;
677 		dfs_get_80mhz_bonding_channels(center_freq,
678 					       freq_list);
679 	} else if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ)
680 		/*
681 		 * The current operating channel is 160MHz and
682 		 * the agile channel is 160MHz.
683 		 * Pine ADFS specific.
684 		 */
685 		dfs_get_160mhz_bonding_channels(center_freq,
686 						freq_list);
687 	else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ) {
688 		/*
689 		 * The current operating channel is 160MHz and the agile channel
690 		 * is 165MHz(restricted 80P80MHZ). Pine ADFS specific.
691 		 * If the segment id is primary segment 0, shift the center
692 		 * frequency 5730MHz to the center of left 80MHz segment 5690MHz
693 		 * and add the subchannels of the left 80MHz segment.
694 		 * If the segment id is secondary segment 1, shift the center
695 		 * frequency 5730MHz to the center of right 80MHz segment
696 		 * 5775MHz and add the subchannels of the right 80MHz segment.
697 		 */
698 		*nchannels = 4;
699 		center_freq = (segment_id) ?
700 			(center_freq + DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT) :
701 			(center_freq - DFS_165MHZ_SECOND_SEG_OFFSET_LEFT);
702 		dfs_get_80mhz_bonding_channels(center_freq,
703 					       freq_list);
704 	}
705 }
706 
707 /*
708  * dfs_get_bonding_channels_for_freq() - Get bonding channel frequency.
709  * @dfs: Pointer to wlan_dfs.
710  * @curchan: Pointer to dfs_channel.
711  * @segment_id: Segment ID.
712  * @detector_id: Detector ID.
713  * @freq_list: Pointer to frequency list.
714  */
715 uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs,
716 					  struct dfs_channel *curchan,
717 					  uint32_t segment_id,
718 					  uint8_t detector_id,
719 					  uint16_t *freq_list)
720 {
721 	uint16_t center_freq;
722 	uint8_t nchannels = 0;
723 
724 	/*
725 	 * For radar in agile detector, use the center of the channel
726 	 * configured to the agile detector.
727 	 * For radar on a 160MHz home channel, use the center of 160MHz.
728 	 * For radar on all other bandwidths, use the center of the segment
729 	 * affected.
730 	 */
731 	if (detector_id == dfs_get_agile_detector_id(dfs))
732 		center_freq = dfs->dfs_agile_precac_freq_mhz;
733 	else if (WLAN_IS_CHAN_MODE_160(curchan) ||
734 		 WLAN_IS_CHAN_MODE_320(curchan))
735 		center_freq = curchan->dfs_ch_mhz_freq_seg2;
736 	else if (!segment_id)
737 		center_freq = curchan->dfs_ch_mhz_freq_seg1;
738 	else
739 		center_freq = curchan->dfs_ch_mhz_freq_seg2;
740 
741 	if (WLAN_IS_CHAN_MODE_20(curchan)) {
742 		nchannels = 1;
743 		dfs_get_20mhz_bonding_channels(center_freq, freq_list);
744 	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
745 		nchannels = 2;
746 		dfs_get_40mhz_bonding_channels(center_freq, freq_list);
747 	} else if (WLAN_IS_CHAN_MODE_80(curchan)) {
748 		nchannels = 4;
749 		dfs_get_80mhz_bonding_channels(center_freq, freq_list);
750 	} else if (WLAN_IS_CHAN_MODE_160(curchan)) {
751 		nchannels = 8;
752 		if (detector_id == dfs_get_agile_detector_id(dfs))
753 			dfs_get_agile_subchans_for_curchan_160(dfs,
754 							       center_freq,
755 							       segment_id,
756 							       freq_list,
757 							       &nchannels);
758 		else
759 			dfs_get_160mhz_bonding_channels(center_freq, freq_list);
760 	} else if (WLAN_IS_CHAN_MODE_320(curchan)) {
761 		dfs_get_320mhz_bonding_channels(center_freq, freq_list,
762 						&nchannels);
763 	}  else if (WLAN_IS_CHAN_MODE_80_80(curchan)) {
764 		/*
765 		 * If the current channel's bandwidth is 80P80MHz,
766 		 * the corresponding agile Detector's bandwidth will be 160MHz
767 		 * in case of Pine ADFS.
768 		 */
769 		if (detector_id == dfs_get_agile_detector_id(dfs)) {
770 			if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) {
771 				nchannels = 8;
772 				dfs_get_160mhz_bonding_channels(center_freq,
773 								freq_list);
774 			} else if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) {
775 				nchannels = 4;
776 				dfs_get_80mhz_bonding_channels(center_freq,
777 							       freq_list);
778 			} else {
779 				dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
780 					"Incorrect precac width %u",
781 					dfs->dfs_precac_chwidth);
782 			}
783 		} else {
784 			/*
785 			 * If the radar is getting detected in 80P80MHz home
786 			 * channel, only the 80MHz segment that is infected with
787 			 * radar is of interest. The other 80MHz segment is
788 			 * ignored. The center frequency of the radar infected
789 			 * segment is dfs_ch_mhz_freq_seg1 if primary and
790 			 * dfs_ch_mhz_freq_seg2 in case of secondary.
791 			 */
792 			nchannels = 4;
793 			dfs_get_80mhz_bonding_channels(center_freq, freq_list);
794 		}
795 	}
796 
797 	return nchannels;
798 }
799 #endif
800 
801 void dfs_reset_bangradar(struct wlan_dfs *dfs)
802 {
803 	dfs->dfs_bangradar_type = DFS_NO_BANGRADAR;
804 }
805 
806 /**
807  * dfs_radar_found_event_basic_sanity() - Check if radar event is received on a
808  * DFS channel.
809  * @dfs: Pointer to wlan_dfs structure.
810  * @chan: Current channel.
811  *
812  * Return: If a radar event found on NON-DFS channel return false. Otherwise,
813  * return true.
814  */
815 static
816 bool dfs_radar_found_event_basic_sanity(struct wlan_dfs *dfs,
817 					struct dfs_channel *chan)
818 {
819 	if (!chan) {
820 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
821 			"dfs->dfs_curchan is NULL");
822 		return false;
823 	}
824 
825 	if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) {
826 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
827 			  "radar event on non-DFS chan");
828 		return false;
829 	}
830 
831 	return true;
832 }
833 
834 void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs)
835 {
836 	dfs->wlan_dfstest = 1;
837 	dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee;
838 	dfs->wlan_dfstesttime = 1;   /* 1ms */
839 	qdf_timer_sync_cancel(&dfs->wlan_dfstesttimer);
840 	qdf_timer_start(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime);
841 }
842 
843 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs)
844 {
845 	dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
846 
847 	return 0;
848 }
849 
850 #ifdef WLAN_DFS_FULL_OFFLOAD
851 void dfs_inc_num_radar(struct wlan_dfs *dfs)
852 {
853 	dfs->wlan_dfs_stats.num_radar_detects++;
854 }
855 #endif /* WLAN_DFS_FULL_OFFLOAD */
856 
857 #if defined(WLAN_DFS_TRUE_160MHZ_SUPPORT) && defined(WLAN_DFS_FULL_OFFLOAD)
858 void dfs_translate_radar_params(struct wlan_dfs *dfs,
859 				struct radar_found_info *radar_found)
860 {
861 	struct dfs_channel *curchan = dfs->dfs_curchan;
862 	bool is_primary_ch_right_of_center = false;
863 
864 	if (!dfs_is_true_160mhz_supported(dfs))
865 		return;
866 
867 	if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) {
868 		dfs_translate_radar_params_for_agile_chan(dfs, radar_found);
869 		return;
870 	}
871 
872 	/* Is the primary channel ( or primary 80 segment) to the right
873 	 * of the center of 160/165Mhz channel.
874 	 */
875 	if (curchan->dfs_ch_freq > curchan->dfs_ch_mhz_freq_seg2)
876 		is_primary_ch_right_of_center = true;
877 
878 	if (WLAN_IS_CHAN_MODE_160(curchan)) {
879 		if (radar_found->freq_offset > 0) {
880 			/* Offset positive: Equivalent to Upper IEEE
881 			 * 80Mhz chans Synthesizer.
882 			 */
883 			if (!is_primary_ch_right_of_center)
884 				radar_found->segment_id = SEG_ID_SECONDARY;
885 			radar_found->freq_offset -=
886 				DFS_160MHZ_SECOND_SEG_OFFSET;
887 		} else {
888 			/* Offset negative: Equivalent to Lower IEEE
889 			 * 80Mhz chans Synthesizer.
890 			 */
891 			if (is_primary_ch_right_of_center)
892 				radar_found->segment_id = SEG_ID_SECONDARY;
893 			radar_found->freq_offset +=
894 				DFS_160MHZ_SECOND_SEG_OFFSET;
895 		}
896 	} else if (WLAN_IS_CHAN_MODE_165(dfs, curchan)) {
897 		/* If offset is greater than 40MHz, radar is found on the
898 		 * secondary segment.
899 		 */
900 		if (abs(radar_found->freq_offset) > 40) {
901 			radar_found->segment_id = SEG_ID_SECONDARY;
902 			/* Update the freq. offset with respect to the
903 			 * secondary segment center freq.
904 			 */
905 			if (is_primary_ch_right_of_center)
906 				radar_found->freq_offset +=
907 					DFS_80P80MHZ_SECOND_SEG_OFFSET;
908 			else
909 				radar_found->freq_offset -=
910 					DFS_80P80MHZ_SECOND_SEG_OFFSET;
911 		}
912 	}
913 }
914 #endif /* WLAN_DFS_TRUE_160MHZ_SUPPORT */
915 
916 /**
917  * dfs_radar_action_for_hw_mode_switch()- Radar cannot be processed when HW
918  * switch is in progress. So save the radar found parameters for
919  * future processing.
920  * @dfs: Pointer to wlan_dfs structure.
921  * @radar_found: Pointer to radar found structure.
922  *
923  * Return: QDF_STATUS
924  */
925 static QDF_STATUS
926 dfs_radar_action_for_hw_mode_switch(struct wlan_dfs *dfs,
927 				    struct radar_found_info *radar_found)
928 {
929 	struct radar_found_info *radar_params = NULL;
930 
931 	radar_params = qdf_mem_malloc(sizeof(*radar_params));
932 	if (!radar_params)
933 		return QDF_STATUS_E_NOMEM;
934 
935 	/* If CAC timer is running, cancel it here rather than
936 	 * after processing to avoid handling unnecessary CAC timeouts.
937 	 */
938 	if (dfs->dfs_cac_timer_running)
939 		dfs_cac_stop(dfs);
940 
941 	/* If CAC timer is to be handled after mode switch and then
942 	 * we receive radar, no point in handling CAC completion.
943 	 */
944 	if (dfs->dfs_defer_params.is_cac_completed)
945 		dfs->dfs_defer_params.is_cac_completed = false;
946 	qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params));
947 	dfs->dfs_defer_params.radar_params = radar_params;
948 	dfs->dfs_defer_params.is_radar_detected = true;
949 
950 	return QDF_STATUS_SUCCESS;
951 }
952 
953 #ifdef CONFIG_CHAN_FREQ_API
954 uint8_t
955 dfs_find_radar_affected_channels(struct wlan_dfs *dfs,
956 				 struct radar_found_info *radar_found,
957 				 uint16_t *freq_list,
958 				 uint32_t freq_center)
959 {
960 	uint8_t num_channels;
961 
962 	if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS)
963 		num_channels =
964 			dfs_get_bonding_channel_without_seg_info_for_freq
965 			(dfs->dfs_curchan, freq_list);
966 	/* BW reduction is dependent on subchannel marking */
967 	else if ((dfs->dfs_use_nol_subchannel_marking) &&
968 		 (!(dfs->dfs_bangradar_type) ||
969 		 (dfs->dfs_bangradar_type ==
970 		  DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS)))
971 		num_channels =
972 		dfs_find_radar_affected_subchans_for_freq(dfs,
973 							  radar_found,
974 							  freq_list,
975 							  freq_center);
976 	else
977 		num_channels = dfs_get_bonding_channels_for_freq
978 			(dfs,
979 			 dfs->dfs_curchan,
980 			 radar_found->segment_id,
981 			 radar_found->detector_id,
982 			 freq_list);
983 
984 	return num_channels;
985 }
986 
987 #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) || \
988 	defined(QCA_SUPPORT_ADFS_RCAC)
989 /**
990  * dfs_is_radarsource_agile() - Indicates whether the radar event is received
991  * on the agile channel.
992  * @dfs: Pointer to wlan_dfs structure.
993  * @radar_found: Pointer to radar_found_info structure.
994  *
995  * Return: QDF_STATUS
996  */
997 static
998 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs,
999 			      struct radar_found_info *radar_found)
1000 {
1001 	bool is_radar_from_agile_dfs =
1002 	    ((dfs_is_agile_precac_enabled(dfs) &&
1003 	      dfs_is_precac_timer_running(dfs)) ||
1004 	     dfs_is_agile_rcac_enabled(dfs)) &&
1005 	    (radar_found->detector_id == dfs_get_agile_detector_id(dfs));
1006 
1007 	dfs_debug(dfs, WLAN_DEBUG_DFS_AGILE,
1008 		  "radar on PreCAC segment: ADFS:%d",
1009 		  is_radar_from_agile_dfs);
1010 
1011 	return is_radar_from_agile_dfs;
1012 }
1013 #else
1014 static
1015 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs,
1016 			      struct radar_found_info *radar_found)
1017 {
1018 	return false;
1019 }
1020 #endif
1021 
1022 QDF_STATUS
1023 dfs_process_radar_ind(struct wlan_dfs *dfs,
1024 		      struct radar_found_info *radar_found)
1025 {
1026 	QDF_STATUS status;
1027 
1028 	/* Acquire a lock to avoid initiating mode switch till radar
1029 	 * processing is completed.
1030 	 */
1031 	DFS_RADAR_MODE_SWITCH_LOCK(dfs);
1032 
1033 	if (utils_dfs_can_ignore_radar_event(dfs->dfs_pdev_obj)) {
1034 		DFS_RADAR_MODE_SWITCH_UNLOCK(dfs);
1035 		return QDF_STATUS_SUCCESS;
1036 	}
1037 
1038 	/* Before processing radar, check if HW mode switch is in progress.
1039 	 * If in progress, defer the processing of radar event received till
1040 	 * the mode switch is completed.
1041 	 */
1042 	if (dfs_is_hw_mode_switch_in_progress(dfs))
1043 		status = dfs_radar_action_for_hw_mode_switch(dfs, radar_found);
1044 	else if (dfs_is_radarsource_agile(dfs, radar_found))
1045 		status = dfs_process_radar_ind_on_agile_chan(dfs, radar_found);
1046 	else
1047 		status = dfs_process_radar_ind_on_home_chan(dfs, radar_found);
1048 
1049 	DFS_RADAR_MODE_SWITCH_UNLOCK(dfs);
1050 
1051 	return status;
1052 }
1053 
1054 QDF_STATUS
1055 dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
1056 				   struct radar_found_info *radar_found)
1057 {
1058 	bool wait_for_csa = false;
1059 	uint16_t freq_list[MAX_20MHZ_SUBCHANS];
1060 	uint16_t nol_freq_list[MAX_20MHZ_SUBCHANS];
1061 	uint8_t num_channels;
1062 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1063 	uint32_t freq_center;
1064 	uint32_t radarfound_freq;
1065 	struct dfs_channel *dfs_curchan;
1066 
1067 	dfs_curchan = dfs->dfs_curchan;
1068 
1069 	/* Check if the current channel is a non DFS channel
1070 	 * If the current channel is non-DFS and the radar is from Agile
1071 	 * Detector we need to process it since Agile Detector has a
1072 	 * different channel.
1073 	 */
1074 	if (!dfs_radar_found_event_basic_sanity(dfs, dfs_curchan))
1075 		goto exit;
1076 
1077 	dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center);
1078 	radarfound_freq = freq_center + radar_found->freq_offset;
1079 
1080 	if (radar_found->segment_id == SEG_ID_SECONDARY)
1081 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
1082 			  "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.",
1083 			  radarfound_freq, freq_center);
1084 	else
1085 		dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
1086 			  "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.",
1087 			  utils_dfs_freq_to_chan(radarfound_freq),
1088 			  radarfound_freq, dfs_curchan->dfs_ch_ieee,
1089 			  dfs_curchan->dfs_ch_freq);
1090 
1091 	utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq,
1092 				WLAN_EV_RADAR_DETECTED);
1093 
1094 	if (!dfs->dfs_use_nol) {
1095 		if (!dfs->dfs_is_offload_enabled) {
1096 			dfs_radar_disable(dfs);
1097 			dfs_second_segment_radar_disable(dfs);
1098 			dfs_flush_additional_pulses(dfs);
1099 		}
1100 		dfs_reset_bangradar(dfs);
1101 		dfs_send_csa_to_current_chan(dfs);
1102 		status = QDF_STATUS_SUCCESS;
1103 		goto exit;
1104 	}
1105 	num_channels = dfs_find_radar_affected_channels(dfs,
1106 							radar_found,
1107 							freq_list,
1108 							freq_center);
1109 
1110 	dfs_reset_bangradar(dfs);
1111 
1112 	status = dfs_radar_add_channel_list_to_nol_for_freq(dfs,
1113 							    freq_list,
1114 							    nol_freq_list,
1115 							    &num_channels);
1116 	if (QDF_IS_STATUS_ERROR(status)) {
1117 		dfs_err(dfs, WLAN_DEBUG_DFS,
1118 			"radar event received on invalid channel");
1119 		goto exit;
1120 	}
1121 
1122 	/*
1123 	 * If precac is running and the radar found in secondary
1124 	 * VHT80 mark the channel as radar and add to NOL list.
1125 	 * Otherwise random channel selection can choose this
1126 	 * channel.
1127 	 */
1128 	dfs_debug(dfs, WLAN_DEBUG_DFS,
1129 		  "found_on_second=%d is_pre=%d",
1130 		  dfs->is_radar_found_on_secondary_seg,
1131 		  dfs_is_precac_timer_running(dfs));
1132 	/*
1133 	 * Even if radar found on primary, we need to mark the channel as NOL
1134 	 * in preCAC list. The preCAC list also maintains the current CAC
1135 	 * channels as part of pre-cleared DFS. Hence call the API
1136 	 * to mark channels as NOL irrespective of preCAC being enabled or not.
1137 	 */
1138 
1139 	dfs_debug(dfs, WLAN_DEBUG_DFS,
1140 		  "Radar found on dfs detector: %d", radar_found->detector_id);
1141 	dfs_mark_precac_nol_for_freq(dfs,
1142 				     dfs->is_radar_found_on_secondary_seg,
1143 				     radar_found->detector_id,
1144 				     nol_freq_list,
1145 				     num_channels);
1146 
1147 	dfs_send_nol_ie_and_rcsa(dfs,
1148 				 radar_found,
1149 				 nol_freq_list,
1150 				 num_channels,
1151 				 &wait_for_csa);
1152 
1153 	if (!dfs->dfs_is_offload_enabled &&
1154 	    dfs->is_radar_found_on_secondary_seg) {
1155 		dfs_second_segment_radar_disable(dfs);
1156 		dfs->is_radar_found_on_secondary_seg = 0;
1157 
1158 		if (dfs->is_radar_during_precac) {
1159 			dfs->is_radar_during_precac = 0;
1160 			goto exit;
1161 		}
1162 	}
1163 
1164 	/*
1165 	 * XXX TODO: the umac NOL code isn't used, but
1166 	 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac
1167 	 * NOL code isn't used, that flag is never cleared. This
1168 	 * needs to be fixed. See EV 105776.
1169 	 */
1170 	if (wait_for_csa)
1171 		goto exit;
1172 
1173 	/*
1174 	 * EV 129487 : We have detected radar in the channel,
1175 	 * stop processing PHY error data as this can cause
1176 	 * false detect in the new channel while channel
1177 	 * change is in progress.
1178 	 */
1179 
1180 	if (!dfs->dfs_is_offload_enabled) {
1181 		dfs_radar_disable(dfs);
1182 		dfs_second_segment_radar_disable(dfs);
1183 		/*
1184 		 * The radar queues were reset just after the filter match, but
1185 		 * the phyerror reception was not disabled. This might
1186 		 * cause the unwanted additional/accumulated pulses to be
1187 		 * detected as radar in the new channel. So, clear the radar
1188 		 * queues and the associated variables.
1189 		 */
1190 		dfs_flush_additional_pulses(dfs);
1191 	}
1192 
1193 	dfs_mlme_mark_dfs(dfs->dfs_pdev_obj,
1194 			  dfs->dfs_curchan->dfs_ch_ieee,
1195 			  dfs->dfs_curchan->dfs_ch_freq,
1196 			  dfs->dfs_curchan->dfs_ch_mhz_freq_seg2,
1197 			  dfs->dfs_curchan->dfs_ch_flags);
1198 
1199 exit:
1200 	return status;
1201 }
1202 #endif
1203