xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c (revision 6f3a375902d676398fbb5b8710604e6236bff43f)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 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 /**
220  * dfs_find_20mhz_subchans_from_offsets()- Find frequency offsets
221  * that aligns with 20MHz sub-channel centers.
222  *
223  * @freq_offset: freq offset
224  * @center_freq: center frequency
225  * @ch_width: Channel Width value: 20/40/80/160/320MHz.
226  * Find frequency offsets for 80MHz
227  *
228  * Return: None
229  */
230 static void
231 dfs_find_20mhz_subchans_from_offsets(struct freqs_offsets *freq_offset,
232 				     uint32_t center_freq,
233 				     uint16_t ch_width)
234 {
235 	uint16_t first_chan20_cen = center_freq - (ch_width / 2) + BW_10;
236 	uint16_t i, j;
237 	uint8_t num_20mhz_subchans = ch_width / BW_20;
238 
239 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
240 		uint16_t radar_found_freq =
241 					center_freq + freq_offset->offset[i];
242 		uint16_t chan20_cen = first_chan20_cen;
243 
244 		for (j = 0; j < num_20mhz_subchans; j++) {
245 			if ((radar_found_freq > chan20_cen - BW_10) &&
246 			    (radar_found_freq < chan20_cen + BW_10)) {
247 				freq_offset->freq[i] = chan20_cen;
248 				break;
249 			}
250 			chan20_cen += BW_20;
251 		}
252 	}
253 }
254 
255 #ifdef CONFIG_CHAN_FREQ_API
256 void
257 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs,
258 			      struct radar_found_info *radar_found,
259 			      uint32_t *freq_center)
260 {
261 	struct dfs_channel *curchan = dfs->dfs_curchan;
262 
263 	/* In case of 11BE Chipsets, radar found center frequency is
264 	 * directly obtained from WMI.
265 	 */
266 	if (dfs->dfs_is_radar_found_chan_freq_eq_center_freq) {
267 		*freq_center = radar_found->chan_freq;
268 		return;
269 	}
270 
271 	/* Radar found on agile detector ID.
272 	 * Applicable to chips that have a separate agile radar detector
273 	 * engine.
274 	 */
275 	if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) {
276 		*freq_center = dfs->dfs_agile_precac_freq_mhz;
277 		if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) {
278 			if (radar_found->segment_id == PRIMARY_SEG)
279 				*freq_center -= DFS_160MHZ_SECOND_SEG_OFFSET;
280 			else
281 				*freq_center += DFS_160MHZ_SECOND_SEG_OFFSET;
282 		} else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ &&
283 			   dfs->dfs_agile_precac_freq_mhz ==
284 				RESTRICTED_80P80_CHAN_CENTER_FREQ) {
285 			/*
286 			 * The reason why left and right offsets
287 			 * are different.
288 			 * Center of 165 is 5730MHz.
289 			 * Center of left 80 is 5690MHz.
290 			 * Center of right 80 is 5775MHz.
291 			 */
292 			if (radar_found->segment_id == PRIMARY_SEG)
293 				*freq_center -=
294 				    DFS_165MHZ_SECOND_SEG_OFFSET_LEFT;
295 			else
296 				*freq_center +=
297 				    DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT;
298 		}
299 	} else if (!radar_found->segment_id) {
300 		*freq_center = curchan->dfs_ch_mhz_freq_seg1;
301 	} else {
302 		/* Radar found on secondary segment by the HW, when preCAC
303 		 * was not running in legacy chips or preCAC was running
304 		 * in Lithium chips.
305 		 */
306 		*freq_center = curchan->dfs_ch_mhz_freq_seg2;
307 		if (WLAN_IS_CHAN_MODE_160(curchan)) {
308 			/* If center frequency of entire 160 band
309 			 * is less than center frequency of primary
310 			 * segment, then the center frequency of
311 			 * secondary segment is -40 of center
312 			 * frequency of entire 160 segment.
313 			 */
314 			if (curchan->dfs_ch_mhz_freq_seg2 <
315 			    curchan->dfs_ch_mhz_freq_seg1)
316 				*freq_center -=
317 					DFS_160MHZ_SECOND_SEG_OFFSET;
318 			else
319 				*freq_center +=
320 					DFS_160MHZ_SECOND_SEG_OFFSET;
321 		}
322 	}
323 }
324 #endif
325 
326 /**
327  * dfs_find_radar_affected_subchans_for_freq() - Find radar affected sub chans.
328  * @dfs: Pointer to wlan_dfs structure.
329  * @radar_found: Pointer to radar_found structure.
330  * @freq_list: Pointer to save radar affected channels.
331  * @freq_center: Freq_center of the radar affected chan.
332  *
333  * Return: Number of channels.
334  */
335 #ifdef CONFIG_CHAN_FREQ_API
336 static uint8_t
337 dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs *dfs,
338 					  struct radar_found_info *radar_found,
339 					  uint16_t *freq_list,
340 					  uint32_t freq_center)
341 {
342 	int i, j;
343 	uint8_t num_radar_subchans;
344 	uint32_t flag;
345 	int32_t sidx;
346 	uint16_t candidate_subchan_freq;
347 	uint16_t cur_subchans[MAX_20MHZ_SUBCHANS];
348 	uint8_t n_cur_subchans;
349 	struct dfs_channel *curchan = dfs->dfs_curchan;
350 	struct freqs_offsets freq_offset;
351 	uint16_t ch_width;
352 
353 	qdf_mem_zero(&freq_offset, sizeof(freq_offset));
354 	flag = curchan->dfs_ch_flags;
355 
356 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++)
357 		freq_offset.offset[i] = radar_found->freq_offset;
358 
359 	sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset);
360 
361 	dfs_info(dfs, WLAN_DEBUG_DFS,
362 		 "seg=%d, det=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d",
363 		 radar_found->segment_id, radar_found->detector_id, sidx,
364 		 radar_found->freq_offset, radar_found->is_chirp,
365 		 flag, freq_center);
366 
367 	ch_width = dfs_chan_to_ch_width(curchan);
368 	if (ch_width == BW_INVALID) {
369 		dfs_err(dfs, WLAN_DEBUG_DFS,
370 			"channel flag=%d is invalid", flag);
371 		return 0;
372 	}
373 
374 	if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
375 		freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
376 		freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
377 	}
378 
379 	dfs_find_20mhz_subchans_from_offsets(&freq_offset, freq_center,
380 					     ch_width);
381 
382 	n_cur_subchans =
383 	    dfs_get_bonding_channels_for_freq(dfs, curchan,
384 					      radar_found->segment_id,
385 					      radar_found->detector_id,
386 					      cur_subchans);
387 
388 	for (i = 0, num_radar_subchans = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
389 		candidate_subchan_freq = freq_offset.freq[i];
390 		for (j = 0; j < n_cur_subchans; j++) {
391 			if (cur_subchans[j] == candidate_subchan_freq) {
392 				freq_list[num_radar_subchans++] =
393 						candidate_subchan_freq;
394 				dfs_info(dfs, WLAN_DEBUG_DFS,
395 					 "offset=%d, channel=%d",
396 					 num_radar_subchans,
397 					 freq_list[num_radar_subchans - 1]);
398 				break;
399 			}
400 		}
401 	}
402 	return num_radar_subchans;
403 }
404 #endif
405 
406 /**
407  * dfs_calc_bonding_freqs() - Calculate bonding channel frequencies
408  * @center_freq: Center frequency of the channel width.
409  * @ch_width: Channel width.
410  * @freq_list: output array of sub-channel frequencies.
411  *
412  * Calculate bonding channel frequencies from the channel width's
413  * center frequency and channel width.  It is assumed that the caller
414  * has allocated sufficient memory for @freq_list so that it can hold
415  * all the output subchannels.
416  *
417  * Return: void
418  */
419 static void
420 dfs_calc_bonding_freqs(qdf_freq_t center_freq,
421 		       uint16_t ch_width,
422 		       uint16_t *freq_list)
423 {
424 #define CHAN_SPACING_MHZ_5G 20
425 #define SUB20CHAN_BW_MHZ_5G 20
426 	uint8_t nchans = ch_width / CHAN_SPACING_MHZ_5G;
427 	qdf_freq_t first_subchan_cfreq = center_freq - (ch_width / 2) +
428 					 (SUB20CHAN_BW_MHZ_5G / 2);
429 	uint8_t i;
430 
431 	for (i = 0; i < nchans; ++i)
432 		freq_list[i] = first_subchan_cfreq + (i * CHAN_SPACING_MHZ_5G);
433 }
434 
435 /**
436  * dfs_get_20mhz_bonding_channels() - Get bonding frequency list of 20MHz
437  * channel.
438  * @center_freq: Center frequency of the 20MHz channel.
439  * @freq_list: Pointer to frequency list.
440  *
441  * Return: void
442  */
443 static
444 void dfs_get_20mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
445 {
446 	uint16_t chwidth = BW_20;
447 
448 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
449 }
450 
451 /**
452  * dfs_get_40mhz_bonding_channels() - Get bonding frequency list of 40MHz
453  * channel.
454  * @center_freq: Center frequency of the 40MHz channel.
455  * @freq_list: Pointer to frequency list.
456  *
457  * Return: void
458  */
459 static
460 void dfs_get_40mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
461 {
462 	uint16_t chwidth = BW_40;
463 
464 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
465 }
466 
467 /**
468  * dfs_get_80mhz_bonding_channels() - Get bonding frequency list of 80MHz
469  * channel.
470  * @center_freq: Center frequency of the 80MHz channel.
471  * @freq_list: Pointer to frequency list.
472  *
473  * Return: void
474  */
475 static
476 void dfs_get_80mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
477 {
478 	uint16_t chwidth = BW_80;
479 
480 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
481 }
482 
483 /**
484  * dfs_get_160mhz_bonding_channels() - Get bonding frequency list of 160MHz
485  * channel.
486  * @center_freq: Center frequency of the 160MHz channel.
487  * @freq_list: Pointer to frequency list.
488  *
489  * Return: void
490  */
491 static
492 void dfs_get_160mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list)
493 {
494 	uint16_t chwidth = BW_160;
495 
496 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
497 }
498 
499 /**
500  * dfs_get_320mhz_bonding_channels() - Get bonding frequency list of 320 MHz
501  * channel.
502  * @center_freq: Center frequency of the 320 MHz channel.
503  * @freq_list: Pointer to frequency list.
504  * @nchannels: Number of channels in @freq_list
505  *
506  * Return: void
507  */
508 #ifdef WLAN_FEATURE_11BE
509 static
510 void dfs_get_320mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list,
511 				     uint8_t *nchannels)
512 {
513 	uint16_t chwidth = 320;
514 
515 	/*
516 	 * In 5 GHz band, the 320 MHz channel is always 80 MHz punctured
517 	 * to the right. Therefore, it is actually a 240 MHz channel and
518 	 * has twelve 20 MHz subchannels.
519 	 */
520 	*nchannels = NUM_CHANNELS_240MHZ;
521 	dfs_calc_bonding_freqs(center_freq, chwidth, freq_list);
522 }
523 #else
524 static
525 void dfs_get_320mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list,
526 				     uint8_t *nchannels)
527 {
528 	*nchannels = 0;
529 	dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
530 		  "320MHz chan width for non 11be");
531 }
532 #endif
533 
534 /**
535  * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding frequency
536  * list.
537  * @chan: Pointer to dfs_channel.
538  * @freq_list: Pointer to frequency list.
539  */
540 #ifdef CONFIG_CHAN_FREQ_API
541 uint8_t
542 dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan,
543 						  uint16_t *freq_list)
544 {
545 	uint16_t center_freq;
546 	uint8_t nchannels = 0;
547 
548 	center_freq = chan->dfs_ch_mhz_freq_seg1;
549 
550 	if (WLAN_IS_CHAN_MODE_20(chan)) {
551 		nchannels = 1;
552 		dfs_get_20mhz_bonding_channels(center_freq,
553 					       freq_list);
554 	} else if (WLAN_IS_CHAN_MODE_40(chan)) {
555 		nchannels = 2;
556 		dfs_get_40mhz_bonding_channels(center_freq,
557 					       freq_list);
558 	} else if (WLAN_IS_CHAN_MODE_80(chan)) {
559 		nchannels = 4;
560 		dfs_get_80mhz_bonding_channels(center_freq,
561 					       freq_list);
562 	} else if (WLAN_IS_CHAN_MODE_80_80(chan)) {
563 		nchannels = 8;
564 		dfs_get_80mhz_bonding_channels(center_freq,
565 					       freq_list);
566 		center_freq = chan->dfs_ch_mhz_freq_seg2;
567 		dfs_get_80mhz_bonding_channels(center_freq,
568 					       freq_list + 4);
569 	} else if (WLAN_IS_CHAN_MODE_160(chan)) {
570 		nchannels = 8;
571 		center_freq = chan->dfs_ch_mhz_freq_seg2;
572 		dfs_get_160mhz_bonding_channels(center_freq, freq_list);
573 	} else if (WLAN_IS_CHAN_MODE_320(chan)) {
574 		center_freq = chan->dfs_ch_mhz_freq_seg2;
575 		dfs_get_320mhz_bonding_channels(center_freq, freq_list,
576 						&nchannels);
577 	}
578 
579 	return nchannels;
580 }
581 #endif
582 
583 #ifdef CONFIG_CHAN_FREQ_API
584 /**
585  * dfs_get_agile_subchans_for_curchan_160() - Get bonding frequency list of
586  * agile channels when current operating channel is 160MHz.
587  *
588  * @dfs: Pointer to DFS structure.
589  * @center_freq: Center frequency of the channel.
590  * @segment_id: Segment ID of interest. 0 for primary segment and 1 for
591  * secondary segment.
592  * @freq_list: Pointer to frequency list.
593  * @nchannels: Number of subchannel.
594  */
595 static void
596 dfs_get_agile_subchans_for_curchan_160(struct wlan_dfs *dfs,
597 				       uint16_t center_freq,
598 				       uint32_t segment_id,
599 				       uint16_t *freq_list,
600 				       uint8_t *nchannels)
601 {
602 	if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) {
603 		/*
604 		 * The current operating channel is 160MHz and
605 		 * the agile channel is 80MHz. This can happen
606 		 * in HK only.
607 		 */
608 		*nchannels = 4;
609 		dfs_get_80mhz_bonding_channels(center_freq,
610 					       freq_list);
611 	} else if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ)
612 		/*
613 		 * The current operating channel is 160MHz and
614 		 * the agile channel is 160MHz.
615 		 * Pine ADFS specific.
616 		 */
617 		dfs_get_160mhz_bonding_channels(center_freq,
618 						freq_list);
619 	else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ) {
620 		/*
621 		 * The current operating channel is 160MHz and the agile channel
622 		 * is 165MHz(restricted 80P80MHZ). Pine ADFS specific.
623 		 * If the segment id is primary segment 0, shift the center
624 		 * frequency 5730MHz to the center of left 80MHz segment 5690MHz
625 		 * and add the subchannels of the left 80MHz segment.
626 		 * If the segment id is secondary segment 1, shift the center
627 		 * frequency 5730MHz to the center of right 80MHz segment
628 		 * 5775MHz and add the subchannels of the right 80MHz segment.
629 		 */
630 		*nchannels = 4;
631 		center_freq = (segment_id) ?
632 			(center_freq + DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT) :
633 			(center_freq - DFS_165MHZ_SECOND_SEG_OFFSET_LEFT);
634 		dfs_get_80mhz_bonding_channels(center_freq,
635 					       freq_list);
636 	}
637 }
638 
639 /**
640  * dfs_get_bonding_channels_for_freq() - Get bonding channel frequency.
641  * @dfs: Pointer to wlan_dfs.
642  * @curchan: Pointer to dfs_channel.
643  * @segment_id: Segment ID.
644  * @detector_id: Detector ID.
645  * @freq_list: Pointer to frequency list.
646  */
647 uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs,
648 					  struct dfs_channel *curchan,
649 					  uint32_t segment_id,
650 					  uint8_t detector_id,
651 					  uint16_t *freq_list)
652 {
653 	uint16_t center_freq;
654 	uint8_t nchannels = 0;
655 
656 	/*
657 	 * For radar in agile detector, use the center of the channel
658 	 * configured to the agile detector.
659 	 * For radar on a 160MHz home channel, use the center of 160MHz.
660 	 * For radar on all other bandwidths, use the center of the segment
661 	 * affected.
662 	 */
663 	if (detector_id == dfs_get_agile_detector_id(dfs))
664 		center_freq = dfs->dfs_agile_precac_freq_mhz;
665 	else if (WLAN_IS_CHAN_MODE_160(curchan) ||
666 		 WLAN_IS_CHAN_MODE_320(curchan))
667 		center_freq = curchan->dfs_ch_mhz_freq_seg2;
668 	else if (!segment_id)
669 		center_freq = curchan->dfs_ch_mhz_freq_seg1;
670 	else
671 		center_freq = curchan->dfs_ch_mhz_freq_seg2;
672 
673 	if (WLAN_IS_CHAN_MODE_20(curchan)) {
674 		nchannels = 1;
675 		dfs_get_20mhz_bonding_channels(center_freq, freq_list);
676 	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
677 		nchannels = 2;
678 		dfs_get_40mhz_bonding_channels(center_freq, freq_list);
679 	} else if (WLAN_IS_CHAN_MODE_80(curchan)) {
680 		nchannels = 4;
681 		dfs_get_80mhz_bonding_channels(center_freq, freq_list);
682 	} else if (WLAN_IS_CHAN_MODE_160(curchan)) {
683 		nchannels = 8;
684 		if (detector_id == dfs_get_agile_detector_id(dfs))
685 			dfs_get_agile_subchans_for_curchan_160(dfs,
686 							       center_freq,
687 							       segment_id,
688 							       freq_list,
689 							       &nchannels);
690 		else
691 			dfs_get_160mhz_bonding_channels(center_freq, freq_list);
692 	} else if (WLAN_IS_CHAN_MODE_320(curchan)) {
693 		dfs_get_320mhz_bonding_channels(center_freq, freq_list,
694 						&nchannels);
695 	}  else if (WLAN_IS_CHAN_MODE_80_80(curchan)) {
696 		/*
697 		 * If the current channel's bandwidth is 80P80MHz,
698 		 * the corresponding agile Detector's bandwidth will be 160MHz
699 		 * in case of Pine ADFS.
700 		 */
701 		if (detector_id == dfs_get_agile_detector_id(dfs)) {
702 			if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) {
703 				nchannels = 8;
704 				dfs_get_160mhz_bonding_channels(center_freq,
705 								freq_list);
706 			} else if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) {
707 				nchannels = 4;
708 				dfs_get_80mhz_bonding_channels(center_freq,
709 							       freq_list);
710 			} else {
711 				dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
712 					"Incorrect precac width %u",
713 					dfs->dfs_precac_chwidth);
714 			}
715 		} else {
716 			/*
717 			 * If the radar is getting detected in 80P80MHz home
718 			 * channel, only the 80MHz segment that is infected with
719 			 * radar is of interest. The other 80MHz segment is
720 			 * ignored. The center frequency of the radar infected
721 			 * segment is dfs_ch_mhz_freq_seg1 if primary and
722 			 * dfs_ch_mhz_freq_seg2 in case of secondary.
723 			 */
724 			nchannels = 4;
725 			dfs_get_80mhz_bonding_channels(center_freq, freq_list);
726 		}
727 	}
728 
729 	return nchannels;
730 }
731 #endif
732 
733 void dfs_reset_bangradar(struct wlan_dfs *dfs)
734 {
735 	dfs->dfs_bangradar_type = DFS_NO_BANGRADAR;
736 }
737 
738 /**
739  * dfs_radar_found_event_basic_sanity() - Check if radar event is received on a
740  * DFS channel.
741  * @dfs: Pointer to wlan_dfs structure.
742  * @chan: Current channel.
743  *
744  * Return: If a radar event found on NON-DFS channel return false. Otherwise,
745  * return true.
746  */
747 static
748 bool dfs_radar_found_event_basic_sanity(struct wlan_dfs *dfs,
749 					struct dfs_channel *chan)
750 {
751 	if (!chan) {
752 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
753 			"dfs->dfs_curchan is NULL");
754 		return false;
755 	}
756 
757 	if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) {
758 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
759 			  "radar event on non-DFS chan");
760 		return false;
761 	}
762 
763 	return true;
764 }
765 
766 void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs)
767 {
768 	dfs->wlan_dfstest = 1;
769 	dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee;
770 	dfs->wlan_dfstesttime = 1;   /* 1ms */
771 	qdf_timer_sync_cancel(&dfs->wlan_dfstesttimer);
772 	qdf_timer_start(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime);
773 }
774 
775 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs)
776 {
777 	dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
778 
779 	return 0;
780 }
781 
782 #ifdef WLAN_DFS_FULL_OFFLOAD
783 void dfs_inc_num_radar(struct wlan_dfs *dfs)
784 {
785 	dfs->wlan_dfs_stats.num_radar_detects++;
786 }
787 #endif /* WLAN_DFS_FULL_OFFLOAD */
788 
789 #if defined(WLAN_DFS_TRUE_160MHZ_SUPPORT) && defined(WLAN_DFS_FULL_OFFLOAD)
790 void dfs_translate_radar_params(struct wlan_dfs *dfs,
791 				struct radar_found_info *radar_found)
792 {
793 	struct dfs_channel *curchan = dfs->dfs_curchan;
794 	bool is_primary_ch_right_of_center = false;
795 
796 	if (!dfs_is_true_160mhz_supported(dfs))
797 		return;
798 
799 	if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) {
800 		dfs_translate_radar_params_for_agile_chan(dfs, radar_found);
801 		return;
802 	}
803 
804 	/* Is the primary channel ( or primary 80 segment) to the right
805 	 * of the center of 160/165Mhz channel.
806 	 */
807 	if (curchan->dfs_ch_freq > curchan->dfs_ch_mhz_freq_seg2)
808 		is_primary_ch_right_of_center = true;
809 
810 	if (WLAN_IS_CHAN_MODE_160(curchan)) {
811 		if (radar_found->freq_offset > 0) {
812 			/* Offset positive: Equivalent to Upper IEEE
813 			 * 80Mhz chans Synthesizer.
814 			 */
815 			if (!is_primary_ch_right_of_center)
816 				radar_found->segment_id = SEG_ID_SECONDARY;
817 			radar_found->freq_offset -=
818 				DFS_160MHZ_SECOND_SEG_OFFSET;
819 		} else {
820 			/* Offset negative: Equivalent to Lower IEEE
821 			 * 80Mhz chans Synthesizer.
822 			 */
823 			if (is_primary_ch_right_of_center)
824 				radar_found->segment_id = SEG_ID_SECONDARY;
825 			radar_found->freq_offset +=
826 				DFS_160MHZ_SECOND_SEG_OFFSET;
827 		}
828 	} else if (WLAN_IS_CHAN_MODE_165(dfs, curchan)) {
829 		/* If offset is greater than 40MHz, radar is found on the
830 		 * secondary segment.
831 		 */
832 		if (abs(radar_found->freq_offset) > 40) {
833 			radar_found->segment_id = SEG_ID_SECONDARY;
834 			/* Update the freq. offset with respect to the
835 			 * secondary segment center freq.
836 			 */
837 			if (is_primary_ch_right_of_center)
838 				radar_found->freq_offset +=
839 					DFS_80P80MHZ_SECOND_SEG_OFFSET;
840 			else
841 				radar_found->freq_offset -=
842 					DFS_80P80MHZ_SECOND_SEG_OFFSET;
843 		}
844 	}
845 }
846 #endif /* WLAN_DFS_TRUE_160MHZ_SUPPORT */
847 
848 /**
849  * dfs_radar_action_for_hw_mode_switch()- Radar cannot be processed when HW
850  * switch is in progress. So save the radar found parameters for
851  * future processing.
852  * @dfs: Pointer to wlan_dfs structure.
853  * @radar_found: Pointer to radar found structure.
854  *
855  * Return: QDF_STATUS
856  */
857 static QDF_STATUS
858 dfs_radar_action_for_hw_mode_switch(struct wlan_dfs *dfs,
859 				    struct radar_found_info *radar_found)
860 {
861 	struct radar_found_info *radar_params = NULL;
862 
863 	radar_params = qdf_mem_malloc(sizeof(*radar_params));
864 	if (!radar_params)
865 		return QDF_STATUS_E_NOMEM;
866 
867 	/* If CAC timer is running, cancel it here rather than
868 	 * after processing to avoid handling unnecessary CAC timeouts.
869 	 */
870 	if (dfs->dfs_cac_timer_running)
871 		dfs_cac_stop(dfs);
872 
873 	/* If CAC timer is to be handled after mode switch and then
874 	 * we receive radar, no point in handling CAC completion.
875 	 */
876 	if (dfs->dfs_defer_params.is_cac_completed)
877 		dfs->dfs_defer_params.is_cac_completed = false;
878 	qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params));
879 	dfs->dfs_defer_params.radar_params = radar_params;
880 	dfs->dfs_defer_params.is_radar_detected = true;
881 
882 	return QDF_STATUS_SUCCESS;
883 }
884 
885 #ifdef CONFIG_CHAN_FREQ_API
886 uint8_t
887 dfs_find_radar_affected_channels(struct wlan_dfs *dfs,
888 				 struct radar_found_info *radar_found,
889 				 uint16_t *freq_list,
890 				 uint32_t freq_center)
891 {
892 	uint8_t num_channels;
893 
894 	if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS)
895 		num_channels =
896 			dfs_get_bonding_channel_without_seg_info_for_freq
897 			(dfs->dfs_curchan, freq_list);
898 	/* BW reduction is dependent on subchannel marking */
899 	else if ((dfs->dfs_use_nol_subchannel_marking) &&
900 		 (!(dfs->dfs_bangradar_type) ||
901 		 (dfs->dfs_bangradar_type ==
902 		  DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS)))
903 		num_channels =
904 		dfs_find_radar_affected_subchans_for_freq(dfs,
905 							  radar_found,
906 							  freq_list,
907 							  freq_center);
908 	else
909 		num_channels = dfs_get_bonding_channels_for_freq
910 			(dfs,
911 			 dfs->dfs_curchan,
912 			 radar_found->segment_id,
913 			 radar_found->detector_id,
914 			 freq_list);
915 
916 	return num_channels;
917 }
918 
919 #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) || \
920 	defined(QCA_SUPPORT_ADFS_RCAC)
921 /**
922  * dfs_is_radarsource_agile() - Indicates whether the radar event is received
923  * on the agile channel.
924  * @dfs: Pointer to wlan_dfs structure.
925  * @radar_found: Pointer to radar_found_info structure.
926  *
927  * Return: QDF_STATUS
928  */
929 static
930 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs,
931 			      struct radar_found_info *radar_found)
932 {
933 	bool is_radar_from_agile_dfs =
934 	    ((dfs_is_agile_precac_enabled(dfs) &&
935 	      dfs_is_precac_timer_running(dfs)) ||
936 	     dfs_is_agile_rcac_enabled(dfs)) &&
937 	    (radar_found->detector_id == dfs_get_agile_detector_id(dfs));
938 
939 	dfs_debug(dfs, WLAN_DEBUG_DFS_AGILE,
940 		  "radar on PreCAC segment: ADFS:%d",
941 		  is_radar_from_agile_dfs);
942 
943 	return is_radar_from_agile_dfs;
944 }
945 #else
946 static
947 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs,
948 			      struct radar_found_info *radar_found)
949 {
950 	return false;
951 }
952 #endif
953 
954 #ifdef QCA_DFS_BW_PUNCTURE
955 uint16_t dfs_generate_radar_bitmap(struct wlan_dfs *dfs,
956 				   uint16_t *radar_freq_list,
957 				   uint8_t num_radar_channels)
958 {
959 	uint8_t n_cur_channels;
960 	uint16_t dfs_radar_bitmap = 0x0;
961 	uint16_t bits = 0x1;
962 	uint8_t i, j;
963 	uint16_t cur_freq_list[MAX_20MHZ_SUBCHANS] = {0};
964 
965 	n_cur_channels =
966 		dfs_get_bonding_channel_without_seg_info_for_freq(dfs->dfs_curchan,
967 								  cur_freq_list);
968 
969 	for (i = 0; i < n_cur_channels; i++) {
970 		for (j = 0; j < num_radar_channels; j++) {
971 			if (cur_freq_list[i] == radar_freq_list[j]) {
972 				dfs_radar_bitmap |= bits;
973 				break;
974 			}
975 		}
976 		bits <<= 1;
977 	}
978 
979 	return dfs_radar_bitmap;
980 }
981 #endif
982 
983 QDF_STATUS
984 dfs_process_radar_ind(struct wlan_dfs *dfs,
985 		      struct radar_found_info *radar_found)
986 {
987 	QDF_STATUS status;
988 
989 	/* Acquire a lock to avoid initiating mode switch till radar
990 	 * processing is completed.
991 	 */
992 	DFS_RADAR_MODE_SWITCH_LOCK(dfs);
993 
994 	if (utils_dfs_can_ignore_radar_event(dfs->dfs_pdev_obj)) {
995 		DFS_RADAR_MODE_SWITCH_UNLOCK(dfs);
996 		return QDF_STATUS_SUCCESS;
997 	}
998 
999 	/* Before processing radar, check if HW mode switch is in progress.
1000 	 * If in progress, defer the processing of radar event received till
1001 	 * the mode switch is completed.
1002 	 */
1003 	if (dfs_is_hw_mode_switch_in_progress(dfs))
1004 		status = dfs_radar_action_for_hw_mode_switch(dfs, radar_found);
1005 	else if (dfs_is_radarsource_agile(dfs, radar_found))
1006 		status = dfs_process_radar_ind_on_agile_chan(dfs, radar_found);
1007 	else
1008 		status = dfs_process_radar_ind_on_home_chan(dfs, radar_found);
1009 
1010 	DFS_RADAR_MODE_SWITCH_UNLOCK(dfs);
1011 
1012 	return status;
1013 }
1014 
1015 #if defined(QCA_DFS_BW_PUNCTURE) && defined(WLAN_FEATURE_11BE)
1016 /**
1017  * dfs_is_ignore_radar_for_punctured_chans() - Store the radar bitmap and check
1018  *                                             if radar is found in already
1019  *                                             punctured channel and ignore the
1020  *                                             radar.
1021  * @dfs: Wlan_dfs structure
1022  * @dfs_radar_bitmap: Variable to store radar bitmap.
1023  * @freq_list: output array of sub-channel frequencies.
1024  * @num_channels: Number of sub-channels in target DFS channel.
1025  *
1026  * Return: If radar is found on punctured channel then return true.
1027  * Else return false.
1028  */
1029 static
1030 bool dfs_is_ignore_radar_for_punctured_chans(struct wlan_dfs *dfs,
1031 					     uint16_t *dfs_radar_bitmap,
1032 					     uint16_t *freq_list,
1033 					     uint8_t num_channels)
1034 {
1035 	uint16_t dfs_punc_pattern = dfs->dfs_curchan->dfs_ch_punc_pattern;
1036 
1037 	*dfs_radar_bitmap = dfs_generate_radar_bitmap(dfs,
1038 						      freq_list,
1039 						      num_channels);
1040 	*dfs_radar_bitmap |= dfs_punc_pattern;
1041 
1042 	if (*dfs_radar_bitmap == dfs_punc_pattern) {
1043 		dfs_err(dfs, WLAN_DEBUG_DFS,
1044 			"radar event received on invalid channel");
1045 		return true;
1046 	}
1047 
1048 	return false;
1049 }
1050 #else
1051 static
1052 bool dfs_is_ignore_radar_for_punctured_chans(struct wlan_dfs *dfs,
1053 					     uint16_t *dfs_radar_bitmap,
1054 					     uint16_t *freq_list,
1055 					     uint8_t num_channels)
1056 {
1057 	return false;
1058 }
1059 #endif /* QCA_DFS_BW_PUNCTURE */
1060 
1061 QDF_STATUS
1062 dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs,
1063 				   struct radar_found_info *radar_found)
1064 {
1065 	bool wait_for_csa = false;
1066 	uint16_t freq_list[MAX_20MHZ_SUBCHANS];
1067 	uint16_t nol_freq_list[MAX_20MHZ_SUBCHANS];
1068 	uint8_t num_channels;
1069 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1070 	uint32_t freq_center;
1071 	uint32_t radarfound_freq;
1072 	struct dfs_channel *dfs_curchan;
1073 	uint16_t dfs_radar_bitmap = 0;
1074 
1075 	dfs_curchan = dfs->dfs_curchan;
1076 
1077 	/* Check if the current channel is a non DFS channel
1078 	 * If the current channel is non-DFS and the radar is from Agile
1079 	 * Detector we need to process it since Agile Detector has a
1080 	 * different channel.
1081 	 */
1082 	if (!dfs_radar_found_event_basic_sanity(dfs, dfs_curchan))
1083 		goto exit;
1084 
1085 	dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center);
1086 	radarfound_freq = freq_center + radar_found->freq_offset;
1087 
1088 	if (radar_found->segment_id == SEG_ID_SECONDARY)
1089 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
1090 			  "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.",
1091 			  radarfound_freq, freq_center);
1092 	else
1093 		dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
1094 			  "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.",
1095 			  utils_dfs_freq_to_chan(radarfound_freq),
1096 			  radarfound_freq, dfs_curchan->dfs_ch_ieee,
1097 			  dfs_curchan->dfs_ch_freq);
1098 
1099 	num_channels = dfs_find_radar_affected_channels(dfs,
1100 							radar_found,
1101 							freq_list,
1102 							freq_center);
1103 
1104 	if (dfs->dfs_use_puncture &&
1105 	    dfs_is_ignore_radar_for_punctured_chans(dfs,
1106 						    &dfs_radar_bitmap,
1107 						    freq_list,
1108 						    num_channels))
1109 		goto exit;
1110 
1111 	if (!dfs->dfs_use_nol) {
1112 		if (!dfs->dfs_is_offload_enabled)
1113 			dfs_disable_radar_and_flush_pulses(dfs);
1114 		dfs_reset_bangradar(dfs);
1115 		dfs_send_csa_to_current_chan(dfs);
1116 		status = QDF_STATUS_SUCCESS;
1117 		goto exit;
1118 	}
1119 
1120 	dfs_reset_bangradar(dfs);
1121 
1122 	status = dfs_radar_add_channel_list_to_nol_for_freq(dfs,
1123 							    freq_list,
1124 							    nol_freq_list,
1125 							    &num_channels);
1126 	if (QDF_IS_STATUS_ERROR(status)) {
1127 		dfs_err(dfs, WLAN_DEBUG_DFS,
1128 			"radar event received on invalid channel");
1129 		goto exit;
1130 	}
1131 
1132 	/*
1133 	 * If precac is running and the radar found in secondary
1134 	 * VHT80 mark the channel as radar and add to NOL list.
1135 	 * Otherwise random channel selection can choose this
1136 	 * channel.
1137 	 */
1138 	dfs_debug(dfs, WLAN_DEBUG_DFS,
1139 		  "found_on_second=%d is_pre=%d",
1140 		  dfs->is_radar_found_on_secondary_seg,
1141 		  dfs_is_precac_timer_running(dfs));
1142 	/*
1143 	 * Even if radar found on primary, we need to mark the channel as NOL
1144 	 * in preCAC list. The preCAC list also maintains the current CAC
1145 	 * channels as part of pre-cleared DFS. Hence call the API
1146 	 * to mark channels as NOL irrespective of preCAC being enabled or not.
1147 	 */
1148 
1149 	dfs_debug(dfs, WLAN_DEBUG_DFS,
1150 		  "Radar found on dfs detector: %d", radar_found->detector_id);
1151 	dfs_mark_precac_nol_for_freq(dfs,
1152 				     dfs->is_radar_found_on_secondary_seg,
1153 				     radar_found->detector_id,
1154 				     nol_freq_list,
1155 				     num_channels);
1156 
1157 	dfs_send_nol_ie_and_rcsa(dfs,
1158 				 radar_found,
1159 				 nol_freq_list,
1160 				 num_channels,
1161 				 &wait_for_csa);
1162 
1163 	if (!dfs->dfs_is_offload_enabled &&
1164 	    dfs->is_radar_found_on_secondary_seg) {
1165 		dfs_second_segment_radar_disable(dfs);
1166 		dfs->is_radar_found_on_secondary_seg = 0;
1167 
1168 		if (dfs->is_radar_during_precac) {
1169 			dfs->is_radar_during_precac = 0;
1170 			goto exit;
1171 		}
1172 	}
1173 
1174 	/*
1175 	 * XXX TODO: the umac NOL code isn't used, but
1176 	 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac
1177 	 * NOL code isn't used, that flag is never cleared. This
1178 	 * needs to be fixed. See EV 105776.
1179 	 */
1180 	if (wait_for_csa)
1181 		goto exit;
1182 
1183 	/*
1184 	 * EV 129487 : We have detected radar in the channel,
1185 	 * stop processing PHY error data as this can cause
1186 	 * false detect in the new channel while channel
1187 	 * change is in progress.
1188 	 */
1189 
1190 	if (!dfs->dfs_is_offload_enabled) {
1191 		/*
1192 		 * The radar queues were reset just after the filter match, but
1193 		 * the phyerror reception was not disabled. This might
1194 		 * cause the unwanted additional/accumulated pulses to be
1195 		 * detected as radar in the new channel. So, clear the radar
1196 		 * queues and the associated variables.
1197 		 */
1198 		dfs_disable_radar_and_flush_pulses(dfs);
1199 	}
1200 
1201 	dfs_mlme_mark_dfs(dfs->dfs_pdev_obj,
1202 			  dfs->dfs_curchan->dfs_ch_ieee,
1203 			  dfs->dfs_curchan->dfs_ch_freq,
1204 			  dfs->dfs_curchan->dfs_ch_mhz_freq_seg2,
1205 			  dfs->dfs_curchan->dfs_ch_flags,
1206 			  dfs_radar_bitmap);
1207 
1208 exit:
1209 	if (QDF_IS_STATUS_SUCCESS(status))
1210 		utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq,
1211 					WLAN_EV_RADAR_DETECTED);
1212 
1213 	return status;
1214 }
1215 #endif
1216