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