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