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