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