xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c (revision 27d564647e9b50e713c60b0d7e5ea2a9b0a3ae74)
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 wlan_dfs *dfs,
412 				 struct dfs_channel *curchan,
413 				 uint32_t segment_id,
414 				 uint8_t *channels)
415 {
416 	uint8_t center_chan;
417 	uint8_t nchannels = 0;
418 
419 	if (!segment_id)
420 		center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1;
421 	else {
422 		/* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is
423 		 * zero and "dfs_precac_secondary_freq" holds the secondary
424 		 * frequency.
425 		 */
426 		if (dfs_is_precac_timer_running(dfs))
427 			center_chan = dfs->dfs_precac_secondary_freq;
428 		else
429 			center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2;
430 	}
431 
432 	if (WLAN_IS_CHAN_MODE_20(curchan)) {
433 		nchannels = 1;
434 		channels[0] = center_chan;
435 	} else if (WLAN_IS_CHAN_MODE_40(curchan)) {
436 		nchannels = 2;
437 		channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
438 		channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
439 	} else if (WLAN_IS_CHAN_MODE_80(curchan) ||
440 		   WLAN_IS_CHAN_MODE_80_80(curchan)) {
441 		nchannels = 4;
442 		channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
443 		channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
444 		channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
445 		channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
446 	} else if (WLAN_IS_CHAN_MODE_160(curchan)) {
447 		nchannels = 8;
448 		center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2;
449 		channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET;
450 		channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET;
451 		channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET;
452 		channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET;
453 		channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET;
454 		channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET;
455 		channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET;
456 		channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET;
457 	}
458 
459 	return nchannels;
460 }
461 
462 int dfs_radarevent_basic_sanity(struct wlan_dfs *dfs,
463 		struct dfs_channel *chan)
464 {
465 	if (!(dfs->dfs_second_segment_bangradar ||
466 				dfs_is_precac_timer_running(dfs)))
467 		if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) {
468 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
469 					"radar event on non-DFS chan");
470 			if (!(dfs->dfs_is_offload_enabled)) {
471 				dfs_reset_radarq(dfs);
472 				dfs_reset_alldelaylines(dfs);
473 				dfs->dfs_bangradar = 0;
474 			}
475 			return 0;
476 		}
477 
478 	return 1;
479 }
480 
481 /**
482  * dfs_send_csa_to_current_chan() - Send CSA to current channel
483  * @dfs: Pointer to wlan_dfs structure.
484  *
485  * For the test mode(usenol = 0), don't do a CSA; but setup the test timer so
486  * we get a CSA _back_ to the current operating channel.
487  */
488 static inline void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs)
489 {
490 	qdf_timer_stop(&dfs->wlan_dfstesttimer);
491 	dfs->wlan_dfstest = 1;
492 	dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee;
493 	dfs->wlan_dfstesttime = 1;   /* 1ms */
494 	qdf_timer_mod(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime);
495 }
496 
497 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs)
498 {
499 	dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
500 
501 	return 0;
502 }
503 
504 static inline void dfs_reset_bangradar(struct wlan_dfs *dfs)
505 {
506 	dfs->dfs_bangradar  = 0;
507 	dfs->dfs_second_segment_bangradar = 0;
508 }
509 
510 QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs,
511 				 struct radar_found_info *radar_found)
512 {
513 	bool wait_for_csa = false;
514 	uint8_t channels[NUM_CHANNELS_160MHZ];
515 	uint8_t num_channels;
516 	QDF_STATUS status;
517 
518 	if (!dfs->dfs_curchan) {
519 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs->dfs_curchan is NULL");
520 		return QDF_STATUS_E_FAILURE;
521 	}
522 
523 	/* Check if the current channel is a non DFS channel */
524 	if (!dfs_radarevent_basic_sanity(dfs, dfs->dfs_curchan)) {
525 		dfs_err(dfs, WLAN_DEBUG_DFS,
526 			"radar event on a non-DFS channel");
527 		return QDF_STATUS_E_FAILURE;
528 	}
529 
530 	/* For Full Offload, FW sends segment id,freq_offset and chirp
531 	 * information and gets assigned when there is radar detect. In
532 	 * case of radartool bangradar enhanced command and real radar
533 	 * for DA and PO, we assign these information here.
534 	 */
535 	if (!(dfs->dfs_is_offload_enabled && dfs->dfs_radar_found_for_fo)) {
536 		radar_found->segment_id = dfs->dfs_seg_id;
537 		radar_found->freq_offset = dfs->dfs_freq_offset;
538 		radar_found->is_chirp = dfs->dfs_is_chirp;
539 	}
540 
541 	if (radar_found->segment_id == SEG_ID_SECONDARY)
542 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
543 			 "Radar found on second segment VHT80 freq=%d MHz",
544 			 dfs->dfs_precac_secondary_freq);
545 	else
546 		dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS,
547 			 "Radar found on channel=%d, freq=%d MHz",
548 			 dfs->dfs_curchan->dfs_ch_ieee,
549 			 dfs->dfs_curchan->dfs_ch_freq);
550 
551 	if (!dfs->dfs_use_nol) {
552 		dfs_reset_bangradar(dfs);
553 		dfs_send_csa_to_current_chan(dfs);
554 		return QDF_STATUS_SUCCESS;
555 	}
556 
557 	if (dfs->dfs_use_nol_subchannel_marking &&
558 	    !(dfs->dfs_bangradar || dfs->dfs_second_segment_bangradar))
559 		num_channels = dfs_find_radar_affected_subchans(dfs,
560 								radar_found,
561 								channels);
562 	else
563 		num_channels = dfs_get_bonding_channels(dfs,
564 							dfs->dfs_curchan,
565 							radar_found->segment_id,
566 							channels);
567 
568 	dfs_reset_bangradar(dfs);
569 	status = dfs_radar_add_channel_list_to_nol(dfs, channels, num_channels);
570 	if (QDF_IS_STATUS_ERROR(status)) {
571 		dfs_err(dfs, WLAN_DEBUG_DFS,
572 			"radar event received on invalid channel");
573 		return status;
574 	}
575 
576 	/*
577 	 * If precac is running and the radar found in secondary
578 	 * VHT80 mark the channel as radar and add to NOL list.
579 	 * Otherwise random channel selection can choose this
580 	 * channel.
581 	 */
582 	dfs_debug(dfs, WLAN_DEBUG_DFS,
583 		  "found_on_second=%d is_pre=%d",
584 		  dfs->is_radar_found_on_secondary_seg,
585 		  dfs_is_precac_timer_running(dfs));
586 
587 	/*
588 	 * Even if radar found on primary, we need to move the channel
589 	 * from precac-required-list and precac-done-list to
590 	 * precac-nol-list.
591 	 */
592 	if (dfs->dfs_precac_enable)
593 		dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg);
594 
595 	if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) {
596 		/* Remove chan from ETSI Pre-CAC Cleared List*/
597 		dfs_info(dfs, WLAN_DEBUG_DFS_NOL,
598 			 "%s : %d remove channel from ETSI PreCAC List\n",
599 			 __func__, __LINE__);
600 		dfs_mark_etsi_precac_dfs(dfs, channels, num_channels);
601 	}
602 
603 	if (!dfs->dfs_is_offload_enabled &&
604 	    dfs->is_radar_found_on_secondary_seg) {
605 		dfs_second_segment_radar_disable(dfs);
606 		dfs->is_radar_found_on_secondary_seg = 0;
607 
608 		if (dfs->is_radar_during_precac) {
609 			dfs->is_radar_during_precac = 0;
610 			return QDF_STATUS_SUCCESS;
611 		}
612 	}
613 
614 	/*
615 	 * This calls into the umac DFS code, which sets the umac
616 	 * related radar flags and begins the channel change
617 	 * machinery.
618 	 * XXX TODO: the umac NOL code isn't used, but
619 	 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac
620 	 * NOL code isn't used, that flag is never cleared. This
621 	 * needs to be fixed. See EV 105776.
622 	 */
623 	dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa);
624 	if (wait_for_csa)
625 		return QDF_STATUS_SUCCESS;
626 
627 	/*
628 	 * EV 129487 : We have detected radar in the channel,
629 	 * stop processing PHY error data as this can cause
630 	 * false detect in the new channel while channel
631 	 * change is in progress.
632 	 */
633 
634 	if (!dfs->dfs_is_offload_enabled) {
635 		dfs_radar_disable(dfs);
636 		dfs_second_segment_radar_disable(dfs);
637 	}
638 
639 	dfs_mlme_mark_dfs(dfs->dfs_pdev_obj,
640 			dfs->dfs_curchan->dfs_ch_ieee,
641 			dfs->dfs_curchan->dfs_ch_freq,
642 			dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2,
643 			dfs->dfs_curchan->dfs_ch_flags);
644 
645 	return QDF_STATUS_SUCCESS;
646 }
647