xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c (revision f28396d060cff5c6519f883cb28ae0116ce479f1)
1 /*
2  * Copyright (c) 2017-2020 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 /**
153  * dfs_radar_add_channel_list_to_nol_for_freq()- Add given channels to nol
154  * @dfs: Pointer to wlan_dfs structure.
155  * @freq_list: Pointer to list of frequency.
156  * @num_channels: Number of channels in the list.
157  *
158  * Add list of channels to nol, only if the channel is dfs.
159  *
160  * Return: QDF_STATUS
161  */
162 #ifdef CONFIG_CHAN_FREQ_API
163 static QDF_STATUS
164 dfs_radar_add_channel_list_to_nol_for_freq(struct wlan_dfs *dfs,
165 					   uint16_t *freq_list,
166 					   uint8_t num_channels)
167 {
168 	int i;
169 	uint16_t last_chan_freq = 0;
170 	uint16_t nol_freq_list[NUM_CHANNELS_160MHZ];
171 	uint8_t num_ch = 0;
172 
173 	if (num_channels > NUM_CHANNELS_160MHZ) {
174 		dfs_err(dfs, WLAN_DEBUG_DFS,
175 			"Invalid num channels: %d", num_channels);
176 		return QDF_STATUS_E_FAILURE;
177 	}
178 
179 	for (i = 0; i < num_channels; i++) {
180 		if (freq_list[i] == 0 ||
181 		    freq_list[i] == last_chan_freq)
182 			continue;
183 		if (!utils_is_dfs_chan_for_freq(dfs->dfs_pdev_obj,
184 						freq_list[i])) {
185 			dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip",
186 				 freq_list[i]);
187 			continue;
188 		}
189 		last_chan_freq = freq_list[i];
190 		DFS_NOL_ADD_CHAN_LOCKED(dfs,
191 					freq_list[i],
192 					dfs->wlan_dfs_nol_timeout);
193 		nol_freq_list[num_ch++] = last_chan_freq;
194 		utils_dfs_deliver_event(dfs->dfs_pdev_obj,
195 					freq_list[i],
196 					WLAN_EV_NOL_STARTED);
197 		dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL",
198 			 last_chan_freq);
199 	}
200 
201 	if (!num_ch) {
202 		dfs_err(dfs, WLAN_DEBUG_DFS,
203 			"dfs channels not found in channel list");
204 		return QDF_STATUS_E_FAILURE;
205 	}
206 
207 	utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj,
208 					     nol_freq_list, num_ch,
209 					     DFS_NOL_SET);
210 
211 	if (dfs->dfs_is_stadfs_enabled)
212 		if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj))
213 			utils_dfs_reg_update_nol_history_chan_for_freq(
214 					dfs->dfs_pdev_obj, nol_freq_list,
215 					num_ch, DFS_NOL_HISTORY_SET);
216 
217 	dfs_nol_update(dfs);
218 	utils_dfs_save_nol(dfs->dfs_pdev_obj);
219 
220 	return QDF_STATUS_SUCCESS;
221 }
222 #endif
223 /**
224  * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz
225  * @freq_offset: freq offset
226  * @center_freq: center frequency
227  *
228  * Find frequency offsets for 80MHz
229  *
230  * Return: None
231  */
232 static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset,
233 				  uint32_t center_freq)
234 {
235 	int i;
236 
237 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
238 		if (freq_offset->offset[i] < DFS_OFFSET_SECOND_LOWER)
239 			freq_offset->freq[i] =
240 				DFS_THIRD_LOWER_CHANNEL(center_freq);
241 		else if ((freq_offset->offset[i] > DFS_OFFSET_SECOND_LOWER) &&
242 			 (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER))
243 			freq_offset->freq[i] =
244 				DFS_SECOND_LOWER_CHANNEL(center_freq);
245 		else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) &&
246 			 (freq_offset->offset[i] < 0))
247 			freq_offset->freq[i] =
248 				DFS_FIRST_LOWER_CHANNEL(center_freq);
249 		else if ((freq_offset->offset[i] > 0) &&
250 			  (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER))
251 			freq_offset->freq[i] =
252 				DFS_FIRST_UPPER_CHANNEL(center_freq);
253 		else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) &&
254 			 (freq_offset->offset[i] < DFS_OFFSET_SECOND_UPPER))
255 			freq_offset->freq[i] =
256 				DFS_SECOND_UPPER_CHANNEL(center_freq);
257 		else if (freq_offset->offset[i] > DFS_OFFSET_SECOND_UPPER)
258 			freq_offset->freq[i] =
259 				DFS_THIRD_UPPER_CHANNEL(center_freq);
260 	}
261 }
262 
263 /**
264  * dfs_radar_chan_for_40()- Find frequency offsets for 40MHz
265  * @freq_offset: freq offset
266  * @center_freq: center frequency
267  *
268  * Find frequency offsets for 40MHz
269  *
270  * Return: None
271  */
272 static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset,
273 				  uint32_t center_freq)
274 {
275 	int i;
276 
277 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
278 		if (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER)
279 			freq_offset->freq[i] =
280 				DFS_SECOND_LOWER_CHANNEL(center_freq);
281 		else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) &&
282 			 (freq_offset->offset[i] < 0))
283 			freq_offset->freq[i] =
284 				DFS_FIRST_LOWER_CHANNEL(center_freq);
285 		else if ((freq_offset->offset[i] > 0) &&
286 			 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER))
287 			freq_offset->freq[i] =
288 				DFS_FIRST_UPPER_CHANNEL(center_freq);
289 		else if (freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER)
290 			freq_offset->freq[i] =
291 				DFS_SECOND_UPPER_CHANNEL(center_freq);
292 	}
293 }
294 
295 /**
296  * dfs_radar_chan_for_20()- Find frequency offsets for 20MHz
297  * @freq_offset: freq offset
298  * @center_freq: center frequency
299  *
300  * Find frequency offsets for 20MHz
301  *
302  * Return: None
303  */
304 static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset,
305 				  uint32_t center_freq)
306 {
307 	int i;
308 
309 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
310 		if (freq_offset->offset[i] <= DFS_20MZ_OFFSET_LOWER)
311 			freq_offset->freq[i] =
312 				DFS_20MHZ_LOWER_CHANNEL(center_freq);
313 		else if ((freq_offset->offset[i] > DFS_20MZ_OFFSET_LOWER) &&
314 			  (freq_offset->offset[i] < DFS_20MZ_OFFSET_UPPER))
315 			freq_offset->freq[i] = center_freq;
316 		else if (freq_offset->offset[i] >= DFS_20MZ_OFFSET_UPPER)
317 			freq_offset->freq[i] =
318 				DFS_20MHZ_UPPER_CHANNEL(center_freq);
319 	}
320 }
321 
322 /* dfs_compute_radar_found_cfreq(): Computes the centre frequency of the
323  * radar hit channel.
324  * @dfs: Pointer to wlan_dfs structure.
325  * @radar_found: Pointer to radar_found_info.
326  * @freq_center: Pointer to retrieve the value of radar found cfreq.
327  */
328 #ifdef CONFIG_CHAN_FREQ_API
329 static void
330 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs,
331 			      struct radar_found_info *radar_found,
332 			      uint32_t *freq_center)
333 {
334 	struct dfs_channel *curchan = dfs->dfs_curchan;
335 
336 	/* Radar found on agile detector ID.
337 	 * Applicable to chips that have a separate agile radar detector
338 	 * engine.
339 	 */
340 	if (radar_found->detector_id == AGILE_DETECTOR_ID) {
341 		*freq_center = dfs->dfs_agile_precac_freq_mhz;
342 	} else if (!radar_found->segment_id) {
343 		*freq_center = curchan->dfs_ch_mhz_freq_seg1;
344 	} else {
345 	    /* Radar found on secondary segment by the HW when
346 	     * preCAC was running. It (dfs_precac_enable) is specific to
347 	     * legacy chips.
348 	     */
349 		if (dfs_is_precac_timer_running(dfs) &&
350 			dfs_is_legacy_precac_enabled(dfs)) {
351 			*freq_center = dfs->dfs_precac_secondary_freq_mhz;
352 		} else {
353 		    /* Radar found on secondary segment by the HW, when preCAC
354 		     * was not running in legacy chips or preCAC was running
355 		     * in Lithium chips.
356 		     */
357 			*freq_center = curchan->dfs_ch_mhz_freq_seg2;
358 			if (WLAN_IS_CHAN_MODE_160(curchan)) {
359 				/* If center frequency of entire 160 band
360 				 * is less than center frequency of primary
361 				 * segment, then the center frequency of
362 				 * secondary segment is -40 of center
363 				 * frequency of entire 160 segment.
364 				 */
365 				if (curchan->dfs_ch_mhz_freq_seg2 <
366 				    curchan->dfs_ch_mhz_freq_seg1)
367 					*freq_center -=
368 						DFS_160MHZ_SECOND_SEG_OFFSET;
369 				else
370 					*freq_center +=
371 						DFS_160MHZ_SECOND_SEG_OFFSET;
372 			}
373 		}
374 	}
375 }
376 #else
377 #ifdef CONFIG_CHAN_NUM_API
378 static void
379 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs,
380 			      struct radar_found_info
381 			      *radar_found,
382 			      uint32_t *freq_center)
383 {
384 	struct dfs_channel *curchan = dfs->dfs_curchan;
385 	/* Radar found on agile detector ID.
386 	 * Applicable to chips that have a separate agile radar detector
387 	 * engine.
388 	 */
389 	if (radar_found->detector_id == AGILE_DETECTOR_ID) {
390 		*freq_center = utils_dfs_chan_to_freq(
391 				dfs->dfs_agile_precac_freq);
392        /* Radar found on primary segment by the HW. */
393 	} else if (radar_found->segment_id == PRIMARY_SEG) {
394 		*freq_center = utils_dfs_chan_to_freq(
395 				curchan->dfs_ch_vhtop_ch_freq_seg1);
396 	} else {
397 	    /* Radar found on secondary segment by the HW when
398 	     * preCAC was running. It (dfs_precac_enable) is specific to
399 	     * legacy chips.
400 	     */
401 		if (dfs_is_precac_timer_running(dfs) &&
402 		    dfs_is_legacy_precac_enabled(dfs)) {
403 			*freq_center = utils_dfs_chan_to_freq(
404 					dfs->dfs_precac_secondary_freq);
405 		} else {
406 		    /* Radar found on secondary segment by the HW, when preCAC
407 		     * was not running in legacy chips or preCAC was running
408 		     * in Lithium chips.
409 		     */
410 		    *freq_center = utils_dfs_chan_to_freq(
411 				  curchan->dfs_ch_vhtop_ch_freq_seg2);
412 			if (WLAN_IS_CHAN_MODE_160(curchan)) {
413 				/* If center frequency of entire 160 band
414 				 * is less than center frequency of primary
415 				 * segment, then the center frequency of
416 				 * secondary segment is -40 of center
417 				 * frequency of entire 160 segment.
418 				 */
419 				if (curchan->dfs_ch_vhtop_ch_freq_seg2 <
420 					curchan->dfs_ch_vhtop_ch_freq_seg1)
421 					*freq_center -=
422 						DFS_160MHZ_SECOND_SEG_OFFSET;
423 				else
424 					*freq_center +=
425 						DFS_160MHZ_SECOND_SEG_OFFSET;
426 			}
427 		}
428 	}
429 }
430 #endif
431 #endif
432 
433 /**
434  * dfs_find_radar_affected_subchans_for_freq() - Find radar affected sub chans.
435  * @dfs: Pointer to wlan_dfs structure.
436  * @radar_found: Pointer to radar_found structure.
437  * @freq_list: Pointer to save radar affected channels.
438  * @freq_center: Freq_center of the radar affected chan.
439  *
440  * Return: Number of channels.
441  */
442 #ifdef CONFIG_CHAN_FREQ_API
443 static uint8_t
444 dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs *dfs,
445 					  struct radar_found_info *radar_found,
446 					  uint16_t *freq_list,
447 					  uint32_t freq_center)
448 {
449 	int i, j;
450 	uint8_t num_radar_subchans;
451 	uint32_t flag;
452 	int32_t sidx;
453 	uint16_t candidate_subchan_freq;
454 	uint16_t cur_subchans[NUM_CHANNELS_160MHZ];
455 	uint8_t n_cur_subchans;
456 	struct dfs_channel *curchan = dfs->dfs_curchan;
457 	struct freqs_offsets freq_offset;
458 
459 	qdf_mem_zero(&freq_offset, sizeof(freq_offset));
460 	flag = curchan->dfs_ch_flags;
461 
462 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++)
463 		freq_offset.offset[i] = radar_found->freq_offset;
464 
465 	sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset);
466 
467 	dfs_info(dfs, WLAN_DEBUG_DFS,
468 		 "seg=%d, det=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d",
469 		 radar_found->segment_id, radar_found->detector_id, sidx,
470 		 radar_found->freq_offset, radar_found->is_chirp,
471 		 flag, freq_center);
472 
473 	if ((WLAN_IS_CHAN_A(curchan)) ||
474 	    WLAN_IS_CHAN_MODE_20(curchan)) {
475 		if (radar_found->is_chirp ||
476 		    (sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) {
477 			freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
478 			freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
479 		}
480 		dfs_radar_chan_for_20(&freq_offset, freq_center);
481 	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
482 		if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
483 			freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
484 			freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
485 		}
486 		dfs_radar_chan_for_40(&freq_offset, freq_center);
487 	} else if (WLAN_IS_CHAN_MODE_80(curchan) ||
488 			WLAN_IS_CHAN_MODE_160(curchan) ||
489 			WLAN_IS_CHAN_MODE_80_80(curchan)) {
490 		if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
491 			freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
492 			freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
493 		}
494 		dfs_radar_chan_for_80(&freq_offset, freq_center);
495 	} else {
496 		dfs_err(dfs, WLAN_DEBUG_DFS,
497 			"channel flag=%d is invalid", flag);
498 		return 0;
499 	}
500 
501 	n_cur_subchans =
502 	    dfs_get_bonding_channels_for_freq(dfs, curchan,
503 					      radar_found->segment_id,
504 					      radar_found->detector_id,
505 					      cur_subchans);
506 
507 	for (i = 0, num_radar_subchans = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
508 		candidate_subchan_freq = freq_offset.freq[i];
509 		for (j = 0; j < n_cur_subchans; j++) {
510 			if (cur_subchans[j] == candidate_subchan_freq) {
511 				freq_list[num_radar_subchans++] =
512 						candidate_subchan_freq;
513 				dfs_info(dfs, WLAN_DEBUG_DFS,
514 					 "offset=%d, channel=%d",
515 					 num_radar_subchans,
516 					 freq_list[num_radar_subchans - 1]);
517 				break;
518 			}
519 		}
520 	}
521 	return num_radar_subchans;
522 }
523 #endif
524 
525 #ifdef CONFIG_CHAN_NUM_API
526 uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan,
527 						  uint8_t *channels)
528 {
529 	uint8_t center_chan;
530 	uint8_t nchannels = 0;
531 
532 	center_chan = chan->dfs_ch_vhtop_ch_freq_seg1;
533 
534 	if (WLAN_IS_CHAN_MODE_20(chan)) {
535 		nchannels = 1;
536 		channels[0] = center_chan;
537 	} else if (WLAN_IS_CHAN_MODE_40(chan)) {
538 		nchannels = 2;
539 		channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
540 		channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
541 	} else if (WLAN_IS_CHAN_MODE_80(chan)) {
542 		nchannels = 4;
543 		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
544 		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
545 		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
546 		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
547 	} else if (WLAN_IS_CHAN_MODE_80_80(chan)) {
548 		nchannels = 8;
549 		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
550 		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
551 		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
552 		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
553 		center_chan = chan->dfs_ch_vhtop_ch_freq_seg2;
554 		channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
555 		channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
556 		channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
557 		channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
558 	} else if (WLAN_IS_CHAN_MODE_160(chan)) {
559 		nchannels = 8;
560 		center_chan = chan->dfs_ch_vhtop_ch_freq_seg2;
561 		channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET;
562 		channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET;
563 		channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
564 		channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
565 		channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
566 		channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
567 		channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET;
568 		channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET;
569 	}
570 
571 	return nchannels;
572 }
573 #endif
574 
575 /*
576  * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding frequency
577  * list.
578  * @chan: Pointer to dfs_channel.
579  * @freq_list: Pointer to frequency list.
580  */
581 #ifdef CONFIG_CHAN_FREQ_API
582 uint8_t
583 dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan,
584 						  uint16_t *freq_list)
585 {
586 	uint16_t center_freq;
587 	uint8_t nchannels = 0;
588 
589 	center_freq = chan->dfs_ch_mhz_freq_seg1;
590 
591 	if (WLAN_IS_CHAN_MODE_20(chan)) {
592 		nchannels = 1;
593 		freq_list[0] = center_freq;
594 	} else if (WLAN_IS_CHAN_MODE_40(chan)) {
595 		nchannels = 2;
596 		freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
597 		freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
598 	} else if (WLAN_IS_CHAN_MODE_80(chan)) {
599 		nchannels = 4;
600 		freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
601 		freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
602 		freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
603 		freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
604 	} else if (WLAN_IS_CHAN_MODE_80_80(chan)) {
605 		nchannels = 8;
606 		freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
607 		freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
608 		freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
609 		freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
610 		center_freq = chan->dfs_ch_mhz_freq_seg2;
611 		freq_list[4] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
612 		freq_list[5] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
613 		freq_list[6] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
614 		freq_list[7] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
615 	} else if (WLAN_IS_CHAN_MODE_160(chan)) {
616 		nchannels = 8;
617 		center_freq = chan->dfs_ch_mhz_freq_seg2;
618 		freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET;
619 		freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET;
620 		freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
621 		freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
622 		freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
623 		freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
624 		freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET;
625 		freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET;
626 	}
627 
628 	return nchannels;
629 }
630 #endif
631 
632 /*
633  * dfs_get_bonding_channels_for_freq() - Get bonding channel frequency.
634  * @dfs: Pointer to wlan_dfs.
635  * @curchan: Pointer to dfs_channel.
636  * @segment_id: Segment ID.
637  * @detector_id: Detector ID.
638  * @freq_list: Pointer to frequency list.
639  */
640 #ifdef CONFIG_CHAN_FREQ_API
641 uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs,
642 					  struct dfs_channel *curchan,
643 					  uint32_t segment_id,
644 					  uint8_t detector_id,
645 					  uint16_t *freq_list)
646 {
647 	uint16_t center_freq;
648 	uint8_t nchannels = 0;
649 
650 	if (detector_id == AGILE_DETECTOR_ID)
651 		center_freq = dfs->dfs_agile_precac_freq_mhz;
652 	else if (!segment_id)
653 		center_freq = curchan->dfs_ch_mhz_freq_seg1;
654 	else {
655 		/* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is
656 		 * zero and "dfs_precac_secondary_freq" holds the secondary
657 		 * frequency.
658 		 */
659 		if (dfs_is_precac_timer_running(dfs))
660 			center_freq = dfs->dfs_precac_secondary_freq_mhz;
661 		else
662 			center_freq = curchan->dfs_ch_mhz_freq_seg2;
663 	}
664 
665 	if (WLAN_IS_CHAN_MODE_20(curchan)) {
666 		nchannels = 1;
667 		freq_list[0] = center_freq;
668 	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
669 		nchannels = 2;
670 		freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
671 		freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
672 	} else if (WLAN_IS_CHAN_MODE_80(curchan) ||
673 			 WLAN_IS_CHAN_MODE_80_80(curchan) ||
674 			 detector_id == AGILE_DETECTOR_ID) {
675 		/* If the current channel's bandwidth is 80/80+80/160Mhz,
676 		 * the corresponding agile Detector's bandwidth will be 80Mhz.
677 		 * Therefore, if radar is found on the agile detector find
678 		 * subchannels for 80Mhz bandwidth.
679 		 */
680 		nchannels = 4;
681 		freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
682 		freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
683 		freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
684 		freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
685 	} else if (WLAN_IS_CHAN_MODE_160(curchan)) {
686 		nchannels = 8;
687 		center_freq = curchan->dfs_ch_mhz_freq_seg2;
688 		freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET;
689 		freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET;
690 		freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
691 		freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
692 		freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET;
693 		freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET;
694 		freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET;
695 		freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET;
696 	}
697 
698 	return nchannels;
699 }
700 #endif
701 
702 #ifdef CONFIG_CHAN_NUM_API
703 uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs,
704 				 struct dfs_channel *curchan,
705 				 uint32_t segment_id,
706 				 uint8_t detector_id,
707 				 uint8_t *channels)
708 {
709 	uint8_t center_chan;
710 	uint8_t nchannels = 0;
711 
712 	if (detector_id == AGILE_DETECTOR_ID)
713 		center_chan = dfs->dfs_agile_precac_freq;
714 	else if (!segment_id)
715 		center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1;
716 	else {
717 		/* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is
718 		 * zero and "dfs_precac_secondary_freq" holds the secondary
719 		 * frequency in case of legacy chips.
720 		 * For chips that support a separate agile detector engine,
721 		 * "dfs_agile_precac_freq" holds the frequency that agile
722 		 * engine operates on.
723 		 *
724 		 * In case of radar detected by the HW in the secondary 80
725 		 * channel,"dfs_ch_vhtop_ch_freq_seg2" holds the secondary
726 		 * segment center frequency in the below cases:
727 		 * 1. preCAC timer is running in chips that support separate
728 		 * agile engines.
729 		 * 2. preCAC timer is not running.
730 		 */
731 		if (dfs_is_precac_timer_running(dfs) &&
732 		    dfs_is_legacy_precac_enabled(dfs))
733 			center_chan = dfs->dfs_precac_secondary_freq;
734 		else
735 			center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2;
736 	}
737 
738 	if (WLAN_IS_CHAN_MODE_20(curchan)) {
739 		nchannels = 1;
740 		channels[0] = center_chan;
741 	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
742 		nchannels = 2;
743 		channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
744 		channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
745 	} else if (WLAN_IS_CHAN_MODE_80(curchan) ||
746 		   WLAN_IS_CHAN_MODE_80_80(curchan) ||
747 		   detector_id == AGILE_DETECTOR_ID) {
748 		/* If the current channel's bandwidth is 80/80+80/160Mhz,
749 		 * the corresponding agile Detector's bandwidth will be 80Mhz.
750 		 * Therefore, if radar is found on the agile detector find
751 		 * subchannels for 80Mhz bandwidth.
752 		 */
753 		nchannels = 4;
754 		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
755 		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
756 		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
757 		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
758 	} else if (WLAN_IS_CHAN_MODE_160(curchan)) {
759 		nchannels = 8;
760 		center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2;
761 		channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET;
762 		channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET;
763 		channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
764 		channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
765 		channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
766 		channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
767 		channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET;
768 		channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET;
769 	}
770 
771 	return nchannels;
772 }
773 #endif
774 
775 static inline void dfs_reset_bangradar(struct wlan_dfs *dfs)
776 {
777 	dfs->dfs_bangradar_type = DFS_NO_BANGRADAR;
778 }
779 
780 int dfs_radarevent_basic_sanity(struct wlan_dfs *dfs,
781 		struct dfs_channel *chan)
782 {
783 	if (!(dfs->dfs_seg_id == SEG_ID_SECONDARY &&
784 	      dfs_is_precac_timer_running(dfs)))
785 		if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) {
786 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
787 					"radar event on non-DFS chan");
788 			if (!(dfs->dfs_is_offload_enabled)) {
789 				dfs_reset_radarq(dfs);
790 				dfs_reset_alldelaylines(dfs);
791 				dfs_reset_bangradar(dfs);
792 			}
793 			return 0;
794 		}
795 
796 	return 1;
797 }
798 
799 /**
800  * dfs_send_csa_to_current_chan() - Send CSA to current channel
801  * @dfs: Pointer to wlan_dfs structure.
802  *
803  * For the test mode(usenol = 0), don't do a CSA; but setup the test timer so
804  * we get a CSA _back_ to the current operating channel.
805  */
806 static inline void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs)
807 {
808 	qdf_timer_stop(&dfs->wlan_dfstesttimer);
809 	dfs->wlan_dfstest = 1;
810 	dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee;
811 	dfs->wlan_dfstesttime = 1;   /* 1ms */
812 	qdf_timer_mod(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime);
813 }
814 
815 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs)
816 {
817 	dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
818 
819 	return 0;
820 }
821 
822 /* dfs_prepare_nol_ie_bitmap: Create a Bitmap from the radar found subchannels
823  * to be sent along with RCSA.
824  * @dfs: Pointer to wlan_dfs.
825  * @radar_found: Pointer to radar_found_info.
826  * @in_sub_channels: Pointer to Sub-channels.
827  * @n_in_sub_channels: Number of sub-channels.
828  */
829 #ifdef CONFIG_CHAN_FREQ_API
830 static void
831 dfs_prepare_nol_ie_bitmap_for_freq(struct wlan_dfs *dfs,
832 				   struct radar_found_info *radar_found,
833 				   uint16_t *in_sub_channels,
834 				   uint8_t n_in_sub_channels)
835 {
836 	uint16_t cur_subchans[NUM_CHANNELS_160MHZ];
837 	uint8_t n_cur_subchans;
838 	uint8_t i;
839 	uint8_t j;
840 	uint8_t bits = 0x01;
841 
842 	n_cur_subchans =
843 	    dfs_get_bonding_channels_for_freq(dfs, dfs->dfs_curchan,
844 					      radar_found->segment_id,
845 					      radar_found->detector_id,
846 					      cur_subchans);
847 	dfs->dfs_nol_ie_bandwidth = MIN_DFS_SUBCHAN_BW;
848 	dfs->dfs_nol_ie_startfreq = cur_subchans[0];
849 
850 	/* Search through the array list of radar affected subchannels
851 	 * to find if the subchannel in our current channel has radar hit.
852 	 * Break if found to reduce loop count.
853 	 */
854 	for (i = 0; i < n_cur_subchans; i++) {
855 		for (j = 0; j < n_in_sub_channels; j++) {
856 			if (cur_subchans[i] == in_sub_channels[j]) {
857 				dfs->dfs_nol_ie_bitmap |= bits;
858 				break;
859 			}
860 		}
861 		bits <<= 1;
862 	}
863 }
864 #endif
865 
866 void dfs_fetch_nol_ie_info(struct wlan_dfs *dfs,
867 			   uint8_t *nol_ie_bandwidth,
868 			   uint16_t *nol_ie_startfreq,
869 			   uint8_t *nol_ie_bitmap)
870 {
871 	if (nol_ie_bandwidth)
872 		*nol_ie_bandwidth = dfs->dfs_nol_ie_bandwidth;
873 	if (nol_ie_startfreq)
874 		*nol_ie_startfreq = dfs->dfs_nol_ie_startfreq;
875 	if (nol_ie_bitmap)
876 		*nol_ie_bitmap = dfs->dfs_nol_ie_bitmap;
877 }
878 
879 void dfs_get_rcsa_flags(struct wlan_dfs *dfs, bool *is_rcsa_ie_sent,
880 			bool *is_nol_ie_sent)
881 {
882 	if (is_rcsa_ie_sent)
883 		*is_rcsa_ie_sent = dfs->dfs_is_rcsa_ie_sent;
884 	if (is_nol_ie_sent)
885 		*is_nol_ie_sent = dfs->dfs_is_nol_ie_sent;
886 }
887 
888 void dfs_set_rcsa_flags(struct wlan_dfs *dfs, bool is_rcsa_ie_sent,
889 			bool is_nol_ie_sent)
890 {
891 	dfs->dfs_is_rcsa_ie_sent = is_rcsa_ie_sent;
892 	dfs->dfs_is_nol_ie_sent = is_nol_ie_sent;
893 }
894 
895 static void dfs_reset_nol_ie_bitmap(struct wlan_dfs *dfs)
896 {
897 	dfs->dfs_nol_ie_bitmap = 0;
898 }
899 
900 #ifdef CONFIG_CHAN_FREQ_API
901 bool dfs_process_nol_ie_bitmap(struct wlan_dfs *dfs, uint8_t nol_ie_bandwidth,
902 			       uint16_t nol_ie_startfreq, uint8_t nol_ie_bitmap)
903 {
904 	uint8_t num_subchans;
905 	uint8_t bits = 0x01;
906 	uint16_t radar_subchans[NUM_CHANNELS_160MHZ];
907 	bool should_nol_ie_be_sent = true;
908 
909 	qdf_mem_zero(radar_subchans, sizeof(radar_subchans));
910 	if (!dfs->dfs_use_nol_subchannel_marking) {
911 		/* Since subchannel marking is disabled, disregard
912 		 * NOL IE and set NOL IE flag as false, so it
913 		 * can't be sent to uplink.
914 		 */
915 		num_subchans =
916 		    dfs_get_bonding_channels_for_freq(dfs,
917 						      dfs->dfs_curchan,
918 						      SEG_ID_PRIMARY,
919 						      DETECTOR_ID_0,
920 						      radar_subchans);
921 		should_nol_ie_be_sent = false;
922 	} else {
923 		/* Add the NOL IE information in DFS structure so that RCSA
924 		 * and NOL IE can be sent to uplink if uplink exists.
925 		 */
926 		uint32_t frequency = (uint32_t)nol_ie_startfreq;
927 
928 		dfs->dfs_nol_ie_bandwidth = nol_ie_bandwidth;
929 		dfs->dfs_nol_ie_startfreq = nol_ie_startfreq;
930 		dfs->dfs_nol_ie_bitmap = nol_ie_bitmap;
931 		for (num_subchans = 0; num_subchans < NUM_CHANNELS_160MHZ;
932 			num_subchans++) {
933 			if (nol_ie_bitmap & bits) {
934 				radar_subchans[num_subchans] = frequency;
935 			}
936 			bits <<= 1;
937 			frequency += nol_ie_bandwidth;
938 		}
939 	}
940 
941 	dfs_radar_add_channel_list_to_nol_for_freq(dfs, radar_subchans,
942 						   num_subchans);
943 	return should_nol_ie_be_sent;
944 }
945 #endif
946 
947 #ifdef CONFIG_CHAN_FREQ_API
948 QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
949 				 struct radar_found_info *radar_found)
950 {
951 	bool wait_for_csa = false;
952 	uint16_t freq_list[NUM_CHANNELS_160MHZ];
953 	uint8_t num_channels;
954 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
955 	uint32_t freq_center;
956 	uint32_t radarfound_freq;
957 	struct dfs_channel *dfs_curchan;
958 
959 	/* Acquire a lock to avoid initiating mode switch till radar
960 	 * processing is completed.
961 	 */
962 	DFS_RADAR_MODE_SWITCH_LOCK(dfs);
963 
964 	/* Before processing radar, check if HW mode switch is in progress.
965 	 * If in progress, defer the processing of radar event received till
966 	 * the mode switch is completed.
967 	 */
968 	if (dfs_is_hw_mode_switch_in_progress(dfs)) {
969 		struct radar_found_info *radar_params = NULL;
970 
971 		radar_params = qdf_mem_malloc(sizeof(*radar_params));
972 		if (!radar_params)
973 			goto exit;
974 
975 		/* If CAC timer is running, cancel it here rather than
976 		 * after processing to avoid handling unnecessary CAC timeouts.
977 		 */
978 		if (dfs->dfs_cac_timer_running)
979 			dfs_cac_stop(dfs);
980 
981 		/* If CAC timer is to be handled after mode switch and then
982 		 * we receive radar, no point in handling CAC completion.
983 		 */
984 		if (dfs->dfs_defer_params.is_cac_completed)
985 			dfs->dfs_defer_params.is_cac_completed = false;
986 		qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params));
987 		dfs->dfs_defer_params.radar_params = radar_params;
988 		dfs->dfs_defer_params.is_radar_detected = true;
989 		status = QDF_STATUS_SUCCESS;
990 		goto exit;
991 	}
992 
993 	dfs_curchan = dfs->dfs_curchan;
994 
995 	if (!dfs_curchan) {
996 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs->dfs_curchan is NULL");
997 		goto exit;
998 	}
999 
1000 	/* Check if the current channel is a non DFS channel
1001 	 * If the current channel is non-DFS and the radar is from Agile
1002 	 * Detector we need to process it since Agile Detector has a
1003 	 * different channel.
1004 	 */
1005 	if (!dfs_radarevent_basic_sanity(dfs, dfs_curchan) &&
1006 	    !(radar_found->detector_id == AGILE_DETECTOR_ID)) {
1007 		dfs_err(dfs, WLAN_DEBUG_DFS,
1008 			"radar event on a non-DFS channel");
1009 		goto exit;
1010 	}
1011 
1012 	/* Sanity checks for radar on Agile detector */
1013 	if (radar_found->detector_id == AGILE_DETECTOR_ID &&
1014 	    (!dfs_is_agile_precac_enabled(dfs) || !dfs->dfs_agile_precac_freq_mhz))
1015 	{
1016 		dfs_err(dfs, WLAN_DEBUG_DFS,
1017 			"radar on Agile detector when ADFS is not running");
1018 		goto exit;
1019 	}
1020 
1021 	/* For Full Offload, FW sends segment id,freq_offset and chirp
1022 	 * information and gets assigned when there is radar detect. In
1023 	 * case of radartool bangradar enhanced command and real radar
1024 	 * for DA and PO, we assign these information here.
1025 	 */
1026 	if (!(dfs->dfs_is_offload_enabled && dfs->dfs_radar_found_for_fo)) {
1027 		radar_found->segment_id = dfs->dfs_seg_id;
1028 		radar_found->freq_offset = dfs->dfs_freq_offset;
1029 		radar_found->is_chirp = dfs->dfs_is_chirp;
1030 	}
1031 
1032 	dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center);
1033 	radarfound_freq = freq_center + radar_found->freq_offset;
1034 
1035 	if (radar_found->detector_id == AGILE_DETECTOR_ID)
1036 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
1037 			 "Radar found on Agile detector freq=%d radar freq=%d",
1038 			 freq_center, radarfound_freq);
1039 	else if (radar_found->segment_id == SEG_ID_SECONDARY)
1040 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
1041 			 "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.",
1042 			 radarfound_freq, freq_center);
1043 	else
1044 		dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS,
1045 			 "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.",
1046 			 utils_dfs_freq_to_chan(radarfound_freq),
1047 			 radarfound_freq, dfs_curchan->dfs_ch_ieee,
1048 			 dfs_curchan->dfs_ch_freq);
1049 
1050 	utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq,
1051 				WLAN_EV_RADAR_DETECTED);
1052 
1053 	if (!dfs->dfs_use_nol) {
1054 		dfs_reset_bangradar(dfs);
1055 		dfs_send_csa_to_current_chan(dfs);
1056 		status = QDF_STATUS_SUCCESS;
1057 		goto exit;
1058 	}
1059 
1060 	if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS)
1061 		num_channels =
1062 			dfs_get_bonding_channel_without_seg_info_for_freq
1063 			(dfs_curchan, freq_list);
1064 	/* BW reduction is dependent on subchannel marking */
1065 	else if ((dfs->dfs_use_nol_subchannel_marking) &&
1066 		 (!(dfs->dfs_bangradar_type) ||
1067 		  (dfs->dfs_bangradar_type ==
1068 		   DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS)))
1069 		num_channels =
1070 			dfs_find_radar_affected_subchans_for_freq(dfs,
1071 								  radar_found,
1072 								  freq_list,
1073 								  freq_center);
1074 	else
1075 		num_channels = dfs_get_bonding_channels_for_freq
1076 			(dfs, dfs_curchan, radar_found->segment_id,
1077 			 radar_found->detector_id, freq_list);
1078 
1079 	dfs_reset_bangradar(dfs);
1080 
1081 	status = dfs_radar_add_channel_list_to_nol_for_freq(dfs,
1082 							    freq_list,
1083 							    num_channels);
1084 	if (QDF_IS_STATUS_ERROR(status)) {
1085 		dfs_err(dfs, WLAN_DEBUG_DFS,
1086 			"radar event received on invalid channel");
1087 		goto exit;
1088 	}
1089 
1090 	dfs->dfs_is_nol_ie_sent = false;
1091 	(dfs->is_radar_during_precac ||
1092 	 radar_found->detector_id == AGILE_DETECTOR_ID) ?
1093 		(dfs->dfs_is_rcsa_ie_sent = false) :
1094 		(dfs->dfs_is_rcsa_ie_sent = true);
1095 	if (dfs->dfs_use_nol_subchannel_marking) {
1096 		dfs_reset_nol_ie_bitmap(dfs);
1097 		dfs_prepare_nol_ie_bitmap_for_freq(dfs, radar_found, freq_list,
1098 						   num_channels);
1099 		dfs->dfs_is_nol_ie_sent = true;
1100 	}
1101 
1102 	/*
1103 	 * If precac is running and the radar found in secondary
1104 	 * VHT80 mark the channel as radar and add to NOL list.
1105 	 * Otherwise random channel selection can choose this
1106 	 * channel.
1107 	 */
1108 	dfs_debug(dfs, WLAN_DEBUG_DFS,
1109 		  "found_on_second=%d is_pre=%d",
1110 		  dfs->is_radar_found_on_secondary_seg,
1111 		  dfs_is_precac_timer_running(dfs));
1112 	/*
1113 	 * Even if radar found on primary, we need to mark the channel as NOL
1114 	 * in preCAC list. The preCAC list also maintains the current CAC
1115 	 * channels as part of pre-cleared DFS. Hence call the API
1116 	 * to mark channels as NOL irrespective of preCAC being enabled or not.
1117 	 */
1118 
1119 	dfs_debug(dfs, WLAN_DEBUG_DFS,
1120 		  "%s: %d Radar found on dfs detector:%d",
1121 		  __func__, __LINE__, radar_found->detector_id);
1122 	dfs_mark_precac_nol_for_freq(dfs,
1123 				     dfs->is_radar_found_on_secondary_seg,
1124 				     radar_found->detector_id,
1125 				     freq_list,
1126 				     num_channels);
1127 	/*
1128 	 * This calls into the umac DFS code, which sets the umac
1129 	 * related radar flags and begins the channel change
1130 	 * machinery.
1131 
1132 	 * Even during precac, this API is called, but with a flag
1133 	 * saying not to send RCSA, but only the radar affected subchannel
1134 	 * information.
1135 	 */
1136 
1137 	dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa);
1138 
1139 	/* If radar is found on preCAC or Agile CAC, return here since
1140 	 * channel change is not required.
1141 	 */
1142 	if (radar_found->detector_id == AGILE_DETECTOR_ID)
1143 		goto exit;
1144 	if (!dfs->dfs_is_offload_enabled &&
1145 	    dfs->is_radar_found_on_secondary_seg) {
1146 		dfs_second_segment_radar_disable(dfs);
1147 		dfs->is_radar_found_on_secondary_seg = 0;
1148 
1149 		if (dfs->is_radar_during_precac) {
1150 			dfs->is_radar_during_precac = 0;
1151 			goto exit;
1152 		}
1153 	}
1154 
1155 	/*
1156 	 * XXX TODO: the umac NOL code isn't used, but
1157 	 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac
1158 	 * NOL code isn't used, that flag is never cleared. This
1159 	 * needs to be fixed. See EV 105776.
1160 	 */
1161 	if (wait_for_csa)
1162 		goto exit;
1163 
1164 	/*
1165 	 * EV 129487 : We have detected radar in the channel,
1166 	 * stop processing PHY error data as this can cause
1167 	 * false detect in the new channel while channel
1168 	 * change is in progress.
1169 	 */
1170 
1171 	if (!dfs->dfs_is_offload_enabled) {
1172 		dfs_radar_disable(dfs);
1173 		dfs_second_segment_radar_disable(dfs);
1174 	}
1175 
1176 	dfs_mlme_mark_dfs_for_freq(dfs->dfs_pdev_obj,
1177 				   dfs->dfs_curchan->dfs_ch_ieee,
1178 				   dfs->dfs_curchan->dfs_ch_freq,
1179 				   dfs->dfs_curchan->dfs_ch_mhz_freq_seg2,
1180 				   dfs->dfs_curchan->dfs_ch_flags);
1181 
1182 exit:
1183 	DFS_RADAR_MODE_SWITCH_UNLOCK(dfs);
1184 	return status;
1185 }
1186 #endif
1187