xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c (revision 0626a4da6c07f30da06dd6747e8cc290a60371d8)
1 /*
2  * Copyright (c) 2017-2018 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_etsi_precac.h"
27 #include "../dfs_process_radar_found_ind.h"
28 #include <wlan_reg_services_api.h>
29 #include <wlan_dfs_utils_api.h>
30 #include "wlan_dfs_mlme_api.h"
31 #include "../dfs_internal.h"
32 /**
33  * TODO: The code is not according to the following description needs
34  * modification and correction. Code always adds left and right channels to
35  * NOL even if it is not a chirp radar.
36  *
37  * A) If chirp radar starts at boundary and ends at boundary then three channels
38  *    will be affected.
39  *    freq_offset.freq[0] = fn   (Center frequency)
40  *    freq_offset.freq[1] = fn-1 (Left of center)
41  *    freq_offset.freq[2] = fn+1 (Right of center)
42  *
43  *    Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL.
44  *
45  *                     Chirp start freq         Chirp end freq
46  *                             |                       |
47  *                             |                       |
48  *                             V                       V
49  *      _______________________________________________________________________
50  *     |       center freq     |       center freq     |       center freq     |
51  *     |          ch(n-1)      |          ch(n)        |          ch(n+1)      |
52  *     |           |           |           |           |           |           |
53  *     |           |           |           |           |           |           |
54  *     |           |           |           |           |           |           |
55  *                fn-1                    fn         boundary     fn+1
56  *     <-------- 20 Mhz ------>
57  *
58  * B) If chirp radar starts at one channel and continues up to another channel
59  *    then two channels will be affected.
60  *    freq_offset.freq[0] = fn
61  *    freq_offset.freq[1] = 0
62  *    freq_offset.freq[2] = fn+1
63  *
64  *    Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL.
65  *
66  *                                   Chirp start freq         Chirp end freq
67  *                                           |                       |
68  *                                           |                       |
69  *                                           V                       V
70  *      _______________________________________________________________________
71  *     |       center freq     |       center freq     |       center freq     |
72  *     |          ch(n-1)      |          ch(n)        |          ch(n+1)      |
73  *     |           |           |           |           |           |           |
74  *     |           |           |           |           |           |           |
75  *     |           |           |           |           |           |           |
76  *                fn-1                    fn         boundary     fn+1
77  *     <-------- 20 Mhz ------>
78  *
79  * C) Radar found at boundary, two channels will be affected.
80  *    freq_offset.freq[0] = fn
81  *    freq_offset.freq[1] = 0
82  *    freq_offset.freq[2] = fn+1
83  *
84  *    Two channels, ch(n) and ch(n+1) will be added to NOL.
85  *
86  *                                            dfs_freq_offset (radar found freq)
87  *                                                     |
88  *                                                     |
89  *                                                     V
90  *      _______________________________________________________________________
91  *     |       center freq     |       center freq     |       center freq     |
92  *     |          ch(n-1)      |          ch(n)        |          ch(n+1)      |
93  *     |           |           |           |           |           |           |
94  *     |           |           |           |           |           |           |
95  *     |           |           |           |           |           |           |
96  *                fn-1                    fn         boundary     fn+1
97  *     <-------- 20 Mhz ------>
98  *
99  *
100  * D) Else only one channel will be affected.
101  *    freq_offset.freq[0] = fn
102  *    freq_offset.freq[1] = 0
103  *    freq_offset.freq[2] = 0
104  *
105  *   One channel ch(n) will be added to NOL.
106  *
107  *
108  *                                            dfs_freq_offset (radar found freq)
109  *                                                |
110  *                                                |
111  *                                                V
112  *      _______________________________________________________________________
113  *     |       center freq     |       center freq     |       center freq     |
114  *     |          ch(n-1)      |          ch(n)        |          ch(n+1)      |
115  *     |           |           |           |           |           |           |
116  *     |           |           |           |           |           |           |
117  *     |           |           |           |           |           |           |
118  *                fn-1                    fn         boundary     fn+1
119  *     <-------- 20 Mhz ------>
120  */
121 
122 /**
123  * dfs_radar_add_channel_list_to_nol()- Add given channels to nol
124  * @dfs: Pointer to wlan_dfs structure.
125  * @channels: Pointer to the channel list.
126  * @num_channels: Number of channels in the list.
127  *
128  * Add list of channels to nol, only if the channel is dfs.
129  *
130  * Return: QDF_STATUS
131  */
132 static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs,
133 						    uint8_t *channels,
134 						    uint8_t num_channels)
135 {
136 	int i;
137 	uint8_t last_chan = 0;
138 	uint8_t nollist[NUM_CHANNELS_160MHZ];
139 	uint8_t num_ch = 0;
140 
141 	if (num_channels > NUM_CHANNELS_160MHZ) {
142 		dfs_err(dfs, WLAN_DEBUG_DFS,
143 			"Invalid num channels: %d", num_channels);
144 		return QDF_STATUS_E_FAILURE;
145 	}
146 
147 	for (i = 0; i < num_channels; i++) {
148 		if (channels[i] == 0 ||
149 		    channels[i] == last_chan)
150 			continue;
151 		if (!utils_is_dfs_ch(dfs->dfs_pdev_obj, channels[i])) {
152 			dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip",
153 				 channels[i]);
154 			continue;
155 		}
156 		last_chan = channels[i];
157 		DFS_NOL_ADD_CHAN_LOCKED(dfs,
158 				(uint16_t)utils_dfs_chan_to_freq(channels[i]),
159 				dfs->wlan_dfs_nol_timeout);
160 		nollist[num_ch++] = last_chan;
161 		dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL",
162 			 last_chan);
163 	}
164 
165 	if (!num_ch) {
166 		dfs_err(dfs, WLAN_DEBUG_DFS,
167 			"dfs channels not found in channel list");
168 		return QDF_STATUS_E_FAILURE;
169 	}
170 
171 	utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj,
172 				    nollist, num_ch, DFS_NOL_SET);
173 	dfs_nol_update(dfs);
174 	utils_dfs_save_nol(dfs->dfs_pdev_obj);
175 
176 	return QDF_STATUS_SUCCESS;
177 }
178 
179 /**
180  * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz
181  * @freq_offset: freq offset
182  * @center_freq: center frequency
183  *
184  * Find frequency offsets for 80MHz
185  *
186  * Return: None
187  */
188 static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset,
189 				  uint32_t center_freq)
190 {
191 	int i;
192 
193 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
194 		if (freq_offset->offset[i] < DFS_OFFSET_SECOND_LOWER)
195 			freq_offset->freq[i] =
196 				DFS_THIRD_LOWER_CHANNEL(center_freq);
197 		else if ((freq_offset->offset[i] > DFS_OFFSET_SECOND_LOWER) &&
198 			 (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER))
199 			freq_offset->freq[i] =
200 				DFS_SECOND_LOWER_CHANNEL(center_freq);
201 		else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) &&
202 			 (freq_offset->offset[i] < 0))
203 			freq_offset->freq[i] =
204 				DFS_FIRST_LOWER_CHANNEL(center_freq);
205 		else if ((freq_offset->offset[i] > 0) &&
206 			  (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER))
207 			freq_offset->freq[i] =
208 				DFS_FIRST_UPPER_CHANNEL(center_freq);
209 		else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) &&
210 			 (freq_offset->offset[i] < DFS_OFFSET_SECOND_UPPER))
211 			freq_offset->freq[i] =
212 				DFS_SECOND_UPPER_CHANNEL(center_freq);
213 		else if (freq_offset->offset[i] > DFS_OFFSET_SECOND_UPPER)
214 			freq_offset->freq[i] =
215 				DFS_THIRD_UPPER_CHANNEL(center_freq);
216 	}
217 }
218 
219 /**
220  * dfs_radar_chan_for_40()- Find frequency offsets for 40MHz
221  * @freq_offset: freq offset
222  * @center_freq: center frequency
223  *
224  * Find frequency offsets for 40MHz
225  *
226  * Return: None
227  */
228 static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset,
229 				  uint32_t center_freq)
230 {
231 	int i;
232 
233 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
234 		if (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER)
235 			freq_offset->freq[i] =
236 				DFS_SECOND_LOWER_CHANNEL(center_freq);
237 		else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) &&
238 			 (freq_offset->offset[i] < 0))
239 			freq_offset->freq[i] =
240 				DFS_FIRST_LOWER_CHANNEL(center_freq);
241 		else if ((freq_offset->offset[i] > 0) &&
242 			 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER))
243 			freq_offset->freq[i] =
244 				DFS_FIRST_UPPER_CHANNEL(center_freq);
245 		else if (freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER)
246 			freq_offset->freq[i] =
247 				DFS_SECOND_UPPER_CHANNEL(center_freq);
248 	}
249 }
250 
251 /**
252  * dfs_radar_chan_for_20()- Find frequency offsets for 20MHz
253  * @freq_offset: freq offset
254  * @center_freq: center frequency
255  *
256  * Find frequency offsets for 20MHz
257  *
258  * Return: None
259  */
260 static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset,
261 				  uint32_t center_freq)
262 {
263 	int i;
264 
265 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
266 		if (freq_offset->offset[i] <= DFS_20MZ_OFFSET_LOWER)
267 			freq_offset->freq[i] =
268 				DFS_20MHZ_LOWER_CHANNEL(center_freq);
269 		else if ((freq_offset->offset[i] > DFS_20MZ_OFFSET_LOWER) &&
270 			  (freq_offset->offset[i] < DFS_20MZ_OFFSET_UPPER))
271 			freq_offset->freq[i] = center_freq;
272 		else if (freq_offset->offset[i] >= DFS_20MZ_OFFSET_UPPER)
273 			freq_offset->freq[i] =
274 				DFS_20MHZ_UPPER_CHANNEL(center_freq);
275 	}
276 }
277 
278 /**
279  * dfs_find_radar_affected_subchans() - Finds radar affected sub channels.
280  * @dfs: Pointer to wlan_dfs structure.
281  * @radar_found: Pointer to radar_found structure.
282  * @channels: Pointer to save radar affected channels.
283  *
284  * Return: Number of channels.
285  */
286 static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs,
287 						struct radar_found_info
288 						*radar_found,
289 						uint8_t *channels)
290 {
291 	int i;
292 	uint32_t freq_center, flag;
293 	int32_t sidx;
294 	struct dfs_channel *curchan = dfs->dfs_curchan;
295 	struct freqs_offsets freq_offset;
296 
297 	qdf_mem_set(&freq_offset, sizeof(freq_offset), 0);
298 	flag = curchan->dfs_ch_flags;
299 
300 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++)
301 		freq_offset.offset[i] = radar_found->freq_offset;
302 
303 	sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset);
304 
305 	if (!radar_found->segment_id)
306 		freq_center = utils_dfs_chan_to_freq(
307 				curchan->dfs_ch_vhtop_ch_freq_seg1);
308 	else {
309 		if (dfs_is_precac_timer_running(dfs)) {
310 			freq_center = utils_dfs_chan_to_freq(
311 					dfs->dfs_precac_secondary_freq);
312 		} else {
313 			freq_center = utils_dfs_chan_to_freq(
314 					curchan->dfs_ch_vhtop_ch_freq_seg2);
315 			if (flag & WLAN_CHAN_VHT160)
316 				freq_center += DFS_160MHZ_SECOND_SEG_OFFSET;
317 		}
318 	}
319 
320 	dfs_info(dfs, WLAN_DEBUG_DFS,
321 		 "seg=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d",
322 		 radar_found->segment_id, sidx,
323 		 radar_found->freq_offset, radar_found->is_chirp,
324 		 flag, freq_center);
325 
326 	if ((WLAN_IS_CHAN_A(curchan)) ||
327 	    WLAN_IS_CHAN_MODE_20(curchan)) {
328 		if (radar_found->is_chirp ||
329 		    (sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) {
330 			freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
331 			freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
332 		}
333 		dfs_radar_chan_for_20(&freq_offset, freq_center);
334 	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
335 		if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
336 			freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
337 			freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
338 		}
339 		dfs_radar_chan_for_40(&freq_offset, freq_center);
340 	} else if (WLAN_IS_CHAN_MODE_80(curchan) ||
341 			WLAN_IS_CHAN_MODE_160(curchan) ||
342 			WLAN_IS_CHAN_MODE_80_80(curchan)) {
343 		if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) {
344 			freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET;
345 			freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET;
346 		}
347 		dfs_radar_chan_for_80(&freq_offset, freq_center);
348 	} else {
349 		dfs_err(dfs, WLAN_DEBUG_DFS,
350 			"channel flag=%d is invalid", flag);
351 		return 0;
352 	}
353 
354 	for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) {
355 		channels[i] = utils_dfs_freq_to_chan(freq_offset.freq[i]);
356 		dfs_info(dfs, WLAN_DEBUG_DFS, "offset=%d, channel=%d",
357 			 i, channels[i]);
358 	}
359 
360 	return i;
361 }
362 
363 uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan,
364 						  uint8_t *channels)
365 {
366 	uint8_t center_chan;
367 	uint8_t nchannels = 0;
368 
369 	center_chan = chan->dfs_ch_vhtop_ch_freq_seg1;
370 
371 	if (WLAN_IS_CHAN_MODE_20(chan)) {
372 		nchannels = 1;
373 		channels[0] = center_chan;
374 	} else if (WLAN_IS_CHAN_MODE_40(chan)) {
375 		nchannels = 2;
376 		channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
377 		channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
378 	} else if (WLAN_IS_CHAN_MODE_80(chan)) {
379 		nchannels = 4;
380 		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
381 		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
382 		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
383 		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
384 	} else if (WLAN_IS_CHAN_MODE_80_80(chan)) {
385 		nchannels = 8;
386 		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
387 		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
388 		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
389 		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
390 		center_chan = chan->dfs_ch_vhtop_ch_freq_seg2;
391 		channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
392 		channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
393 		channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
394 		channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
395 	} else if (WLAN_IS_CHAN_MODE_160(chan)) {
396 		nchannels = 8;
397 		center_chan = chan->dfs_ch_vhtop_ch_freq_seg2;
398 		channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET;
399 		channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET;
400 		channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
401 		channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
402 		channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
403 		channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
404 		channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET;
405 		channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET;
406 	}
407 
408 	return nchannels;
409 }
410 
411 uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan,
412 				 uint32_t segment_id,
413 				 uint8_t *channels)
414 {
415 	uint8_t center_chan;
416 	uint8_t nchannels = 0;
417 
418 	if (!segment_id)
419 		center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1;
420 	else
421 		center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2;
422 
423 	if (WLAN_IS_CHAN_MODE_20(curchan)) {
424 		nchannels = 1;
425 		channels[0] = center_chan;
426 	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
427 		nchannels = 2;
428 		channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
429 		channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
430 	} else if (WLAN_IS_CHAN_MODE_80(curchan) ||
431 		   WLAN_IS_CHAN_MODE_80_80(curchan)) {
432 		nchannels = 4;
433 		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
434 		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
435 		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
436 		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
437 	} else if (WLAN_IS_CHAN_MODE_160(curchan)) {
438 		nchannels = 8;
439 		center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2;
440 		channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET;
441 		channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET;
442 		channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
443 		channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
444 		channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
445 		channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
446 		channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET;
447 		channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET;
448 	}
449 
450 	return nchannels;
451 }
452 
453 int dfs_radarevent_basic_sanity(struct wlan_dfs *dfs,
454 		struct dfs_channel *chan)
455 {
456 	if (!(dfs->dfs_second_segment_bangradar ||
457 				dfs_is_precac_timer_running(dfs)))
458 		if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) {
459 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
460 					"radar event on non-DFS chan");
461 			if (!(dfs->dfs_is_offload_enabled)) {
462 				dfs_reset_radarq(dfs);
463 				dfs_reset_alldelaylines(dfs);
464 				dfs->dfs_bangradar = 0;
465 			}
466 			return 0;
467 		}
468 
469 	return 1;
470 }
471 
472 /**
473  * dfs_send_csa_to_current_chan() - Send CSA to current channel
474  * @dfs: Pointer to wlan_dfs structure.
475  *
476  * For the test mode(usenol = 0), don't do a CSA; but setup the test timer so
477  * we get a CSA _back_ to the current operating channel.
478  */
479 static inline void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs)
480 {
481 	qdf_timer_stop(&dfs->wlan_dfstesttimer);
482 	dfs->wlan_dfstest = 1;
483 	dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee;
484 	dfs->wlan_dfstesttime = 1;   /* 1ms */
485 	qdf_timer_mod(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime);
486 }
487 
488 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs)
489 {
490 	dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
491 
492 	return 0;
493 }
494 
495 static inline void dfs_reset_bangradar(struct wlan_dfs *dfs)
496 {
497 	dfs->dfs_bangradar  = 0;
498 	dfs->dfs_second_segment_bangradar = 0;
499 }
500 
501 QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
502 				 struct radar_found_info *radar_found)
503 {
504 	bool wait_for_csa = false;
505 	uint8_t channels[NUM_CHANNELS_160MHZ];
506 	uint8_t num_channels;
507 	QDF_STATUS status;
508 
509 	if (!dfs->dfs_curchan) {
510 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs->dfs_curchan is NULL");
511 		return QDF_STATUS_E_FAILURE;
512 	}
513 
514 	/* Check if the current channel is a non DFS channel */
515 	if (!dfs_radarevent_basic_sanity(dfs, dfs->dfs_curchan)) {
516 		dfs_err(dfs, WLAN_DEBUG_DFS,
517 			"radar event on a non-DFS channel");
518 		return QDF_STATUS_E_FAILURE;
519 	}
520 
521 	if (radar_found->segment_id == SEG_ID_SECONDARY)
522 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
523 			 "Radar found on second segment VHT80 freq=%d MHz",
524 			 dfs->dfs_precac_secondary_freq);
525 	else
526 		dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS,
527 			 "Radar found on channel=%d, freq=%d MHz",
528 			 dfs->dfs_curchan->dfs_ch_ieee,
529 			 dfs->dfs_curchan->dfs_ch_freq);
530 
531 	if (!dfs->dfs_use_nol) {
532 		dfs_reset_bangradar(dfs);
533 		dfs_send_csa_to_current_chan(dfs);
534 		return QDF_STATUS_SUCCESS;
535 	}
536 
537 	/* For Full Offload, FW sends segment id,freq_offset and
538 	 * is chirp information and gets assigned when there is radar detect.
539 	 * In case of radartool bangradar enhanced command and real radar
540 	 * for FO and PO, we assign these information here.
541 	 */
542 	if (!dfs->dfs_is_offload_enabled || dfs->dfs_enhanced_bangradar) {
543 		radar_found->segment_id = dfs->dfs_seg_id;
544 		radar_found->freq_offset = dfs->dfs_freq_offset;
545 		radar_found->is_chirp = dfs->dfs_is_chirp;
546 		dfs->dfs_enhanced_bangradar = 0;
547 	}
548 
549 	if (dfs->dfs_use_nol_subchannel_marking &&
550 	    !(dfs->dfs_bangradar || dfs->dfs_second_segment_bangradar))
551 		num_channels = dfs_find_radar_affected_subchans(dfs,
552 								radar_found,
553 								channels);
554 	else
555 		num_channels = dfs_get_bonding_channels(dfs->dfs_curchan,
556 							radar_found->segment_id,
557 							channels);
558 
559 	dfs_reset_bangradar(dfs);
560 	status = dfs_radar_add_channel_list_to_nol(dfs, channels, num_channels);
561 	if (QDF_IS_STATUS_ERROR(status)) {
562 		dfs_err(dfs, WLAN_DEBUG_DFS,
563 			"radar event received on invalid channel");
564 		return status;
565 	}
566 
567 	/*
568 	 * If precac is running and the radar found in secondary
569 	 * VHT80 mark the channel as radar and add to NOL list.
570 	 * Otherwise random channel selection can choose this
571 	 * channel.
572 	 */
573 	dfs_debug(dfs, WLAN_DEBUG_DFS,
574 		  "found_on_second=%d is_pre=%d",
575 		  dfs->is_radar_found_on_secondary_seg,
576 		  dfs_is_precac_timer_running(dfs));
577 
578 	/*
579 	 * Even if radar found on primary, we need to move the channel
580 	 * from precac-required-list and precac-done-list to
581 	 * precac-nol-list.
582 	 */
583 	if (dfs->dfs_precac_enable)
584 		dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg);
585 
586 	if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) {
587 		/* Remove chan from ETSI Pre-CAC Cleared List*/
588 		dfs_info(dfs, WLAN_DEBUG_DFS_NOL,
589 			 "%s : %d remove channel from ETSI PreCAC List\n",
590 			 __func__, __LINE__);
591 		dfs_mark_etsi_precac_dfs(dfs, channels, num_channels);
592 	}
593 
594 	if (!dfs->dfs_is_offload_enabled &&
595 	    dfs->is_radar_found_on_secondary_seg) {
596 		dfs_second_segment_radar_disable(dfs);
597 		dfs->is_radar_found_on_secondary_seg = 0;
598 
599 		if (dfs->is_radar_during_precac) {
600 			dfs->is_radar_during_precac = 0;
601 			return QDF_STATUS_SUCCESS;
602 		}
603 	}
604 
605 	/*
606 	 * This calls into the umac DFS code, which sets the umac
607 	 * related radar flags and begins the channel change
608 	 * machinery.
609 	 * XXX TODO: the umac NOL code isn't used, but
610 	 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac
611 	 * NOL code isn't used, that flag is never cleared. This
612 	 * needs to be fixed. See EV 105776.
613 	 */
614 	dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa);
615 	if (wait_for_csa)
616 		return QDF_STATUS_SUCCESS;
617 
618 	/*
619 	 * EV 129487 : We have detected radar in the channel,
620 	 * stop processing PHY error data as this can cause
621 	 * false detect in the new channel while channel
622 	 * change is in progress.
623 	 */
624 
625 	if (!dfs->dfs_is_offload_enabled) {
626 		dfs_radar_disable(dfs);
627 		dfs_second_segment_radar_disable(dfs);
628 	}
629 
630 	dfs_mlme_mark_dfs(dfs->dfs_pdev_obj,
631 			dfs->dfs_curchan->dfs_ch_ieee,
632 			dfs->dfs_curchan->dfs_ch_freq,
633 			dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2,
634 			dfs->dfs_curchan->dfs_ch_flags);
635 
636 	return QDF_STATUS_SUCCESS;
637 }
638