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