xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs.c (revision ccf6794c7efeda37a9772e5eb4d4dab2ab5af07a)
1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2002-2006, Atheros Communications Inc.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: This file contains the dfs_attach() and dfs_detach() functions as well
20  * as the dfs_control() function which is used to process ioctls related to DFS.
21  * For Linux/Mac,  "radartool" is the command line tool that can be used to call
22  * various ioctls to set and get radar detection thresholds.
23  */
24 
25 #include "../dfs_zero_cac.h"
26 #include "wlan_dfs_lmac_api.h"
27 #include "wlan_dfs_mlme_api.h"
28 #include "wlan_dfs_tgt_api.h"
29 #include "../dfs_internal.h"
30 #include "../dfs_filter_init.h"
31 #include <wlan_objmgr_vdev_obj.h>
32 #include "wlan_dfs_utils_api.h"
33 #include "../dfs_process_radar_found_ind.h"
34 #include "../dfs_partial_offload_radar.h"
35 
36 /* Disable NOL in FW. */
37 #define DISABLE_NOL_FW 0
38 
39 #ifndef WLAN_DFS_STATIC_MEM_ALLOC
40 /*
41  * dfs_alloc_wlan_dfs() - allocate wlan_dfs buffer
42  *
43  * Return: buffer, null on failure.
44  */
45 static inline struct wlan_dfs *dfs_alloc_wlan_dfs(void)
46 {
47 	return qdf_mem_malloc(sizeof(struct wlan_dfs));
48 }
49 
50 /*
51  * dfs_free_wlan_dfs() - Free wlan_dfs buffer
52  * @dfs: wlan_dfs buffer pointer
53  *
54  * Return: None
55  */
56 static inline void dfs_free_wlan_dfs(struct wlan_dfs *dfs)
57 {
58 	qdf_mem_free(dfs);
59 }
60 
61 /*
62  * dfs_alloc_dfs_curchan() - allocate dfs_channel buffer
63  *
64  * Return: buffer, null on failure.
65  */
66 static inline struct dfs_channel *dfs_alloc_dfs_curchan(void)
67 {
68 	return qdf_mem_malloc(sizeof(struct dfs_channel));
69 }
70 
71 static inline struct dfs_channel *dfs_alloc_dfs_prevchan(void)
72 {
73 	return qdf_mem_malloc(sizeof(struct dfs_channel));
74 }
75 
76 /*
77  * dfs_free_dfs_chan() - Free dfs_channel buffer
78  * @dfs_chan: dfs_channel buffer pointer
79  *
80  * Return: None
81  */
82 static inline void dfs_free_dfs_chan(struct dfs_channel *dfs_chan)
83 {
84 	qdf_mem_free(dfs_chan);
85 }
86 
87 #else
88 
89 /* Static buffers for DFS objects */
90 static struct wlan_dfs global_dfs;
91 static struct dfs_channel global_dfs_curchan;
92 static struct dfs_channel global_dfs_prevchan;
93 
94 static inline struct wlan_dfs *dfs_alloc_wlan_dfs(void)
95 {
96 	return &global_dfs;
97 }
98 
99 static inline void dfs_free_wlan_dfs(struct wlan_dfs *dfs)
100 {
101 }
102 
103 static inline struct dfs_channel *dfs_alloc_dfs_curchan(void)
104 {
105 	return &global_dfs_curchan;
106 }
107 
108 static inline struct dfs_channel *dfs_alloc_dfs_prevchan(void)
109 {
110 	return &global_dfs_prevchan;
111 }
112 
113 static inline void dfs_free_dfs_chan(struct dfs_channel *dfs_chan)
114 {
115 }
116 #endif
117 
118 /**
119  * dfs_testtimer_task() - Sends CSA in the current channel.
120  *
121  * When the user sets usenol to 0 and inject the RADAR, AP does not mark the
122  * channel as RADAR and does not add the channel to NOL. It sends the CSA in
123  * the current channel.
124  */
125 #ifdef CONFIG_CHAN_FREQ_API
126 static os_timer_func(dfs_testtimer_task)
127 {
128 	struct wlan_dfs *dfs = NULL;
129 
130 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
131 	dfs->wlan_dfstest = 0;
132 
133 	/*
134 	 * Flip the channel back to the original channel.
135 	 * Make sure this is done properly with a CSA.
136 	 */
137 	dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "go back to channel %d",
138 		  dfs->wlan_dfstest_ieeechan);
139 	dfs_mlme_start_csa_for_freq(dfs->dfs_pdev_obj,
140 				    dfs->wlan_dfstest_ieeechan,
141 				    dfs->dfs_curchan->dfs_ch_freq,
142 				    dfs->dfs_curchan->dfs_ch_mhz_freq_seg2,
143 				    dfs->dfs_curchan->dfs_ch_flags);
144 }
145 #endif
146 
147 int dfs_get_debug_info(struct wlan_dfs *dfs, void *data)
148 {
149 	if (data)
150 		*(uint32_t *)data = dfs->dfs_proc_phyerr;
151 
152 	return (int)dfs->dfs_proc_phyerr;
153 }
154 
155 void dfs_main_task_testtimer_init(struct wlan_dfs *dfs)
156 {
157 	qdf_timer_init(NULL,
158 		&(dfs->wlan_dfstesttimer),
159 		dfs_testtimer_task, (void *)dfs,
160 		QDF_TIMER_TYPE_WAKE_APPS);
161 }
162 
163 int dfs_create_object(struct wlan_dfs **dfs)
164 {
165 	*dfs = dfs_alloc_wlan_dfs();
166 	if (!(*dfs))
167 		return 1;
168 
169 	qdf_mem_zero(*dfs, sizeof(**dfs));
170 
171 	(*dfs)->dfs_curchan = dfs_alloc_dfs_curchan();
172 	if (!((*dfs)->dfs_curchan)) {
173 		dfs_free_wlan_dfs(*dfs);
174 		return 1;
175 	}
176 
177 	(*dfs)->dfs_prevchan = dfs_alloc_dfs_prevchan();
178 	if (!((*dfs)->dfs_prevchan)) {
179 		dfs_free_wlan_dfs(*dfs);
180 		return 1;
181 	}
182 	qdf_mem_zero((*dfs)->dfs_prevchan, sizeof(struct dfs_channel));
183 	return 0;
184 }
185 
186 int dfs_attach(struct wlan_dfs *dfs)
187 {
188 	int ret;
189 
190 	if (!dfs->dfs_is_offload_enabled) {
191 		ret = dfs_main_attach(dfs);
192 
193 		/*
194 		 * For full offload we have a wmi handler registered to process
195 		 * a radar event from firmware in the event of a radar detect.
196 		 * So, init of timer, dfs_task is not required for
197 		 * full-offload. dfs_task timer is called in
198 		 * dfs_main_timer_init within dfs_main_attach for
199 		 * partial-offload in the event of radar detect.
200 		 */
201 		if (ret) {
202 			dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_main_attach failed");
203 			return ret;
204 		}
205 	}
206 	dfs_cac_timer_attach(dfs);
207 	dfs_zero_cac_attach(dfs);
208 	dfs_nol_attach(dfs);
209 	dfs_postnol_attach(dfs);
210 
211 	/*
212 	 * Init of timer ,dfs_testtimer_task is required by both partial
213 	 * and full offload, indicating test mode timer initialization for both.
214 	 */
215 	dfs_main_task_testtimer_init(dfs);
216 	return 0;
217 }
218 
219 void dfs_stop(struct wlan_dfs *dfs)
220 {
221 	dfs_nol_timer_cleanup(dfs);
222 	dfs_nol_workqueue_cleanup(dfs);
223 	dfs_clear_nolhistory(dfs);
224 }
225 
226 void dfs_task_testtimer_reset(struct wlan_dfs *dfs)
227 {
228 	if (dfs->wlan_dfstest) {
229 		qdf_timer_sync_cancel(&dfs->wlan_dfstesttimer);
230 		dfs->wlan_dfstest = 0;
231 	}
232 }
233 
234 void dfs_task_testtimer_detach(struct wlan_dfs *dfs)
235 {
236 	qdf_timer_free(&dfs->wlan_dfstesttimer);
237 	dfs->wlan_dfstest = 0;
238 }
239 
240 void dfs_reset(struct wlan_dfs *dfs)
241 {
242 	if (!dfs) {
243 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
244 		return;
245 	}
246 
247 	dfs_cac_timer_reset(dfs);
248 	dfs_zero_cac_reset(dfs);
249 	if (!dfs->dfs_is_offload_enabled) {
250 		dfs_main_timer_reset(dfs);
251 		dfs_host_wait_timer_reset(dfs);
252 		dfs_false_radarfound_reset_vars(dfs);
253 	}
254 	dfs_task_testtimer_reset(dfs);
255 }
256 
257 void dfs_timer_detach(struct wlan_dfs *dfs)
258 {
259 	dfs_cac_timer_detach(dfs);
260 	dfs_zero_cac_timer_detach(dfs->dfs_soc_obj);
261 
262 	if (!dfs->dfs_is_offload_enabled) {
263 		dfs_main_timer_detach(dfs);
264 		dfs_host_wait_timer_detach(dfs);
265 	}
266 
267 	dfs_task_testtimer_detach(dfs);
268 }
269 
270 void dfs_detach(struct wlan_dfs *dfs)
271 {
272 	dfs_timer_detach(dfs);
273 	if (!dfs->dfs_is_offload_enabled)
274 		dfs_main_detach(dfs);
275 	dfs_zero_cac_detach(dfs);
276 	dfs_nol_detach(dfs);
277 }
278 
279 #ifndef WLAN_DFS_STATIC_MEM_ALLOC
280 void dfs_destroy_object(struct wlan_dfs *dfs)
281 {
282 	dfs_free_dfs_chan(dfs->dfs_prevchan);
283 	dfs_free_dfs_chan(dfs->dfs_curchan);
284 	dfs_free_wlan_dfs(dfs);
285 }
286 #else
287 void dfs_destroy_object(struct wlan_dfs *dfs)
288 {
289 }
290 #endif
291 
292 /* dfs_set_disable_radar_marking()- Set the flag to mark/unmark a radar flag
293  * on NOL channel.
294  * @dfs: Pointer to wlan_dfs structure.
295  * @disable_radar_marking: Flag to enable/disable marking channel as radar.
296  */
297 #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD)
298 static void dfs_set_disable_radar_marking(struct wlan_dfs *dfs,
299 					  bool disable_radar_marking)
300 {
301 	dfs->dfs_disable_radar_marking = disable_radar_marking;
302 }
303 #else
304 static inline void dfs_set_disable_radar_marking(struct wlan_dfs *dfs,
305 						 bool disable_radar_marking)
306 {
307 }
308 #endif
309 
310 #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD)
311 bool dfs_get_disable_radar_marking(struct wlan_dfs *dfs)
312 {
313 	return dfs->dfs_disable_radar_marking;
314 }
315 #endif
316 
317 int dfs_control(struct wlan_dfs *dfs,
318 		u_int id,
319 		void *indata,
320 		uint32_t insize,
321 		void *outdata,
322 		uint32_t *outsize)
323 {
324 	struct wlan_dfs_phyerr_param peout;
325 	struct dfs_ioctl_params *dfsparams;
326 	int error = 0;
327 	uint32_t val = 0;
328 	struct dfsreq_nolinfo *nol;
329 	uint32_t *data = NULL;
330 	int i;
331 	int usenol_pdev_param;
332 
333 	if (!dfs) {
334 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
335 		goto bad;
336 	}
337 
338 	switch (id) {
339 	case DFS_SET_THRESH:
340 		if (insize < sizeof(struct dfs_ioctl_params) || !indata) {
341 			dfs_debug(dfs, WLAN_DEBUG_DFS1,
342 					"insize = %d, expected = %zu bytes, indata = %pK",
343 					insize,
344 					sizeof(struct dfs_ioctl_params),
345 					indata);
346 			error = -EINVAL;
347 			break;
348 		}
349 		dfsparams = (struct dfs_ioctl_params *)indata;
350 		if (!dfs_set_thresholds(dfs, DFS_PARAM_FIRPWR,
351 					dfsparams->dfs_firpwr))
352 			error = -EINVAL;
353 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RRSSI,
354 					dfsparams->dfs_rrssi))
355 			error = -EINVAL;
356 		if (!dfs_set_thresholds(dfs, DFS_PARAM_HEIGHT,
357 					dfsparams->dfs_height))
358 			error = -EINVAL;
359 		if (!dfs_set_thresholds(dfs, DFS_PARAM_PRSSI,
360 					dfsparams->dfs_prssi))
361 			error = -EINVAL;
362 		if (!dfs_set_thresholds(dfs, DFS_PARAM_INBAND,
363 					dfsparams->dfs_inband))
364 			error = -EINVAL;
365 
366 		/* 5413 speicfic. */
367 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RELPWR,
368 					dfsparams->dfs_relpwr))
369 			error = -EINVAL;
370 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RELSTEP,
371 					dfsparams->dfs_relstep))
372 			error = -EINVAL;
373 		if (!dfs_set_thresholds(dfs, DFS_PARAM_MAXLEN,
374 					dfsparams->dfs_maxlen))
375 			error = -EINVAL;
376 		break;
377 	case DFS_BANGRADAR:
378 		error = dfs_bang_radar(dfs, indata, insize);
379 		break;
380 	case DFS_GET_THRESH:
381 		if (!outdata || !outsize ||
382 				*outsize < sizeof(struct dfs_ioctl_params)) {
383 			error = -EINVAL;
384 			break;
385 		}
386 		*outsize = sizeof(struct dfs_ioctl_params);
387 		dfsparams = (struct dfs_ioctl_params *) outdata;
388 
389 		qdf_mem_zero(&peout, sizeof(struct wlan_dfs_phyerr_param));
390 
391 		/* Fetch the DFS thresholds using the internal representation */
392 		(void) dfs_get_thresholds(dfs, &peout);
393 
394 		/* Convert them to the dfs IOCTL representation. */
395 		wlan_dfs_dfsparam_to_ioctlparam(&peout, dfsparams);
396 		break;
397 	case DFS_RADARDETECTS:
398 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
399 			error = -EINVAL;
400 			break;
401 		}
402 		*outsize = sizeof(uint32_t);
403 		*((uint32_t *)outdata) = dfs->wlan_dfs_stats.num_radar_detects;
404 		break;
405 	case DFS_DISABLE_DETECT:
406 		dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
407 		dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
408 		dfs->dfs_ignore_dfs = 1;
409 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
410 			  "enable detects, ignore_dfs %d",
411 			  dfs->dfs_ignore_dfs ? 1 : 0);
412 		break;
413 	case DFS_ENABLE_DETECT:
414 		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
415 		dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN;
416 		dfs->dfs_ignore_dfs = 0;
417 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
418 			  "enable detects, ignore_dfs %d",
419 			  dfs->dfs_ignore_dfs ? 1 : 0);
420 		break;
421 	case DFS_DISABLE_FFT:
422 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
423 			  "TODO disable FFT val=0x%x", val);
424 		break;
425 	case DFS_ENABLE_FFT:
426 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
427 			  "TODO enable FFT val=0x%x", val);
428 		break;
429 	case DFS_SET_DEBUG_LEVEL:
430 		if (insize < sizeof(uint32_t) || !indata) {
431 			error = -EINVAL;
432 			break;
433 		}
434 		dfs->dfs_debug_mask = *(uint32_t *)indata;
435 
436 		/* Do not allow user to set the ALWAYS/MAX bit.
437 		 * It will be used internally  by dfs print macro(s)
438 		 * to print messages when dfs is NULL.
439 		 */
440 		dfs->dfs_debug_mask &= ~(WLAN_DEBUG_DFS_ALWAYS);
441 
442 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
443 			  "debug level now = 0x%x", dfs->dfs_debug_mask);
444 		if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS3) {
445 			/* Enable debug Radar Event */
446 			dfs->dfs_event_log_on = 1;
447 		} else if ((utils_get_dfsdomain(dfs->dfs_pdev_obj) ==
448 		    DFS_FCC_DOMAIN) &&
449 		    lmac_is_host_dfs_check_support_enabled(dfs->dfs_pdev_obj)) {
450 			dfs->dfs_event_log_on = 1;
451 		} else {
452 			dfs->dfs_event_log_on = 0;
453 		}
454 		break;
455 	case DFS_SET_FALSE_RSSI_THRES:
456 		if (insize < sizeof(uint32_t) || !indata) {
457 			error = -EINVAL;
458 			break;
459 		}
460 		dfs->wlan_dfs_false_rssi_thres = *(uint32_t *)indata;
461 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
462 			  "false RSSI threshold now = 0x%x",
463 			  dfs->wlan_dfs_false_rssi_thres);
464 		break;
465 	case DFS_SET_PEAK_MAG:
466 		if (insize < sizeof(uint32_t) || !indata) {
467 			error = -EINVAL;
468 			break;
469 		}
470 		dfs->wlan_dfs_peak_mag = *(uint32_t *)indata;
471 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
472 			  "peak_mag now = 0x%x",
473 				dfs->wlan_dfs_peak_mag);
474 		break;
475 	case DFS_GET_CAC_VALID_TIME:
476 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
477 			error = -EINVAL;
478 			break;
479 		}
480 		*outsize = sizeof(uint32_t);
481 		*((uint32_t *)outdata) = dfs->dfs_cac_valid_time;
482 		break;
483 	case DFS_SET_CAC_VALID_TIME:
484 		if (insize < sizeof(uint32_t) || !indata) {
485 			error = -EINVAL;
486 			break;
487 		}
488 		dfs->dfs_cac_valid_time = *(uint32_t *)indata;
489 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
490 			  "dfs timeout = %d", dfs->dfs_cac_valid_time);
491 		break;
492 	case DFS_IGNORE_CAC:
493 		if (insize < sizeof(uint32_t) || !indata) {
494 			error = -EINVAL;
495 			break;
496 		}
497 
498 		if (*(uint32_t *)indata)
499 			dfs->dfs_ignore_cac = 1;
500 		else
501 			dfs->dfs_ignore_cac = 0;
502 
503 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
504 			  "ignore cac = 0x%x", dfs->dfs_ignore_cac);
505 		break;
506 	case DFS_SET_NOL_TIMEOUT:
507 		if (insize < sizeof(uint32_t) || !indata) {
508 			error = -EINVAL;
509 			break;
510 		}
511 		if (*(int *)indata)
512 			dfs->wlan_dfs_nol_timeout = *(int *)indata;
513 		else
514 			dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S;
515 
516 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol timeout = %d sec",
517 			  dfs->wlan_dfs_nol_timeout);
518 		break;
519 	case DFS_MUTE_TIME:
520 		if (insize < sizeof(uint32_t) || !indata) {
521 			error = -EINVAL;
522 			break;
523 		}
524 		data = (uint32_t *) indata;
525 		dfs->wlan_dfstesttime = *data;
526 		dfs->wlan_dfstesttime *= (1000); /* convert sec into ms */
527 		break;
528 	case DFS_GET_USENOL:
529 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
530 			error = -EINVAL;
531 			break;
532 		}
533 		*outsize = sizeof(uint32_t);
534 		*((uint32_t *)outdata) = dfs->dfs_use_nol;
535 
536 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
537 			  "#Phyerr=%d, #false detect=%d, #queued=%d",
538 			  dfs->dfs_phyerr_count,
539 			  dfs->dfs_phyerr_reject_count,
540 			  dfs->dfs_phyerr_queued_count);
541 
542 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
543 			 "dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d",
544 			 dfs->dfs_phyerr_freq_min,
545 			 dfs->dfs_phyerr_freq_max);
546 
547 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
548 			 "Total radar events detected=%d, entries in the radar queue follows:",
549 			 dfs->dfs_event_log_count);
550 
551 		for (i = 0; (i < DFS_EVENT_LOG_SIZE) &&
552 				(i < dfs->dfs_event_log_count); i++) {
553 #define FREQ_OFFSET1 ((int)dfs->radar_log[i].freq_offset_khz / 1000)
554 #define FREQ_OFFSET2 ((int)abs(dfs->radar_log[i].freq_offset_khz) % 1000)
555 			dfs_debug(dfs, WLAN_DEBUG_DFS,
556 				  "ts=%llu diff_ts=%u rssi=%u dur=%u, is_chirp=%d, seg_id=%d, sidx=%d, freq_offset=%d.%dMHz, peak_mag=%d, total_gain=%d, mb_gain=%d, relpwr_db=%d, delta_diff=%d, delta_peak=%d, psidx_diff=%d\n",
557 				  dfs->radar_log[i].ts,
558 				  dfs->radar_log[i].diff_ts,
559 				  dfs->radar_log[i].rssi,
560 				  dfs->radar_log[i].dur,
561 				  dfs->radar_log[i].is_chirp,
562 				  dfs->radar_log[i].seg_id,
563 				  dfs->radar_log[i].sidx,
564 				  FREQ_OFFSET1,
565 				  FREQ_OFFSET2,
566 				  dfs->radar_log[i].peak_mag,
567 				  dfs->radar_log[i].total_gain,
568 				  dfs->radar_log[i].mb_gain,
569 				  dfs->radar_log[i].relpwr_db,
570 				  dfs->radar_log[i].delta_diff,
571 				  dfs->radar_log[i].delta_peak,
572 				  dfs->radar_log[i].psidx_diff);
573 		}
574 		dfs->dfs_event_log_count = 0;
575 		dfs->dfs_phyerr_count = 0;
576 		dfs->dfs_phyerr_reject_count = 0;
577 		dfs->dfs_phyerr_queued_count = 0;
578 		dfs->dfs_phyerr_freq_min = 0x7fffffff;
579 		dfs->dfs_phyerr_freq_max = 0;
580 		break;
581 	case DFS_SET_USENOL:
582 		if (insize < sizeof(uint32_t) || !indata) {
583 			error = -EINVAL;
584 			break;
585 		}
586 		dfs->dfs_use_nol = *(uint32_t *)indata;
587 		usenol_pdev_param = dfs->dfs_use_nol;
588 		if (dfs->dfs_is_offload_enabled) {
589 			if (dfs->dfs_use_nol ==
590 				USENOL_ENABLE_NOL_HOST_DISABLE_NOL_FW)
591 				usenol_pdev_param = DISABLE_NOL_FW;
592 			tgt_dfs_send_usenol_pdev_param(dfs->dfs_pdev_obj,
593 						       usenol_pdev_param);
594 		}
595 		break;
596 	case DFS_SET_DISABLE_RADAR_MARKING:
597 		if (dfs->dfs_is_offload_enabled &&
598 		    (utils_get_dfsdomain(dfs->dfs_pdev_obj) ==
599 			 DFS_FCC_DOMAIN)) {
600 			if (insize < sizeof(uint32_t) || !indata) {
601 				error = -EINVAL;
602 				break;
603 			}
604 			dfs_set_disable_radar_marking(dfs, *(uint8_t *)indata);
605 		}
606 		break;
607 	case DFS_GET_DISABLE_RADAR_MARKING:
608 		if (!outdata || !outsize || *outsize < sizeof(uint8_t)) {
609 			error = -EINVAL;
610 			break;
611 		}
612 		if (dfs->dfs_is_offload_enabled) {
613 			*outsize = sizeof(uint8_t);
614 			*((uint8_t *)outdata) =
615 				dfs_get_disable_radar_marking(dfs);
616 		}
617 		break;
618 	case DFS_GET_NOL:
619 		if (!outdata || !outsize ||
620 				*outsize < sizeof(struct dfsreq_nolinfo)) {
621 			error = -EINVAL;
622 			break;
623 		}
624 		*outsize = sizeof(struct dfsreq_nolinfo);
625 		nol = (struct dfsreq_nolinfo *)outdata;
626 		DFS_GET_NOL_LOCKED(dfs,
627 				(struct dfsreq_nolelem *)nol->dfs_nol,
628 				&nol->dfs_ch_nchans);
629 		DFS_PRINT_NOL_LOCKED(dfs);
630 		break;
631 	case DFS_SET_NOL:
632 		if (insize < sizeof(struct dfsreq_nolinfo) || !indata) {
633 			error = -EINVAL;
634 			break;
635 		}
636 		nol = (struct dfsreq_nolinfo *) indata;
637 		dfs_set_nol(dfs,
638 				(struct dfsreq_nolelem *)nol->dfs_nol,
639 				nol->dfs_ch_nchans);
640 		break;
641 	case DFS_SHOW_NOL:
642 		DFS_PRINT_NOL_LOCKED(dfs);
643 		break;
644 	case DFS_SHOW_NOLHISTORY:
645 		dfs_print_nolhistory(dfs);
646 		break;
647 	case DFS_SHOW_PRECAC_LISTS:
648 		dfs_print_precaclists(dfs);
649 		break;
650 	case DFS_RESET_PRECAC_LISTS:
651 		dfs_reset_precac_lists(dfs);
652 		break;
653 	case DFS_INJECT_SEQUENCE:
654 		error = dfs_inject_synthetic_pulse_sequence(dfs, indata);
655 		if (error)
656 			dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
657 				  "Not injected Synthetic pulse");
658 		break;
659 
660 	case DFS_ALLOW_HW_PULSES:
661 		if (insize < sizeof(u_int8_t) || !indata) {
662 			error = -EINVAL;
663 			break;
664 		}
665 		dfs_allow_hw_pulses(dfs, !!(*(u_int8_t *)indata));
666 		break;
667 	case DFS_SET_PRI_MULTIPILER:
668 		dfs->dfs_pri_multiplier = *(int *)indata;
669 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
670 			  "Set dfs pri multiplier to %d, dfsdomain %d",
671 			  dfs->dfs_pri_multiplier, dfs->dfsdomain);
672 		break;
673 	default:
674 		error = -EINVAL;
675 	}
676 
677 bad:
678 	return error;
679 }
680 
681 #ifdef WLAN_FEATURE_11BE
682 static inline bool
683 dfs_is_chan_punc_same_as_given_punc(struct dfs_channel *dfs_curchan,
684 				    uint16_t dfs_chan_punc_pattern)
685 {
686 	return (dfs_curchan->dfs_ch_punc_pattern == dfs_chan_punc_pattern);
687 }
688 #else
689 static inline bool
690 dfs_is_chan_punc_same_as_given_punc(struct dfs_channel *dfs_curchan,
691 				    uint16_t dfs_chan_punc_pattern)
692 {
693 	return true;
694 }
695 #endif
696 /**
697  * dfs_is_curchan_same_as_given_chan() - Find if dfs_curchan has the same
698  * channel parameters provided.
699  * @dfs_curchan: Pointer to DFS current channel structure.
700  * @dfs_ch_freq: New curchan's primary frequency.
701  * @dfs_ch_flags: New curchan's channel flags.
702  * @dfs_ch_flagext: New curchan's channel flags extension.
703  * @dfs_ch_vhtop_ch_freq_seg1: New curchan's primary centre IEEE.
704  * @dfs_ch_vhtop_ch_freq_seg2: New curchan's secondary centre IEEE.
705  *
706  * Return: True if curchan has the same channel parameters of the given channel,
707  * else false.
708  */
709 static bool
710 dfs_is_curchan_same_as_given_chan(struct dfs_channel *dfs_curchan,
711 				  uint16_t dfs_ch_freq,
712 				  uint64_t dfs_ch_flags,
713 				  uint16_t dfs_ch_flagext,
714 				  uint8_t dfs_ch_vhtop_ch_freq_seg1,
715 				  uint8_t dfs_ch_vhtop_ch_freq_seg2,
716 				  uint16_t dfs_chan_punc_pattern)
717 {
718 	if ((dfs_curchan->dfs_ch_freq == dfs_ch_freq) &&
719 	    (dfs_curchan->dfs_ch_flags == dfs_ch_flags) &&
720 	    (dfs_curchan->dfs_ch_flagext == dfs_ch_flagext) &&
721 	    (dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 ==
722 	     dfs_ch_vhtop_ch_freq_seg1) &&
723 	    (dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 ==
724 	     dfs_ch_vhtop_ch_freq_seg2) &&
725 	    (dfs_is_chan_punc_same_as_given_punc(dfs_curchan,
726 						 dfs_chan_punc_pattern)))
727 		return true;
728 
729 	return false;
730 }
731 
732 #ifdef WLAN_FEATURE_11BE
733 static inline void
734 dfs_set_cur_chan_punc_pattern(struct wlan_dfs *dfs,
735 			      uint16_t dfs_ch_punc_pattern)
736 {
737 	dfs->dfs_curchan->dfs_ch_punc_pattern = dfs_ch_punc_pattern;
738 }
739 #else
740 static inline void
741 dfs_set_cur_chan_punc_pattern(struct wlan_dfs *dfs,
742 			      uint16_t dfs_ch_punc_pattern)
743 {
744 }
745 #endif
746 
747 #ifdef CONFIG_CHAN_FREQ_API
748 void dfs_set_current_channel_for_freq(struct wlan_dfs *dfs,
749 				      uint16_t dfs_chan_freq,
750 				      uint64_t dfs_chan_flags,
751 				      uint16_t dfs_chan_flagext,
752 				      uint8_t dfs_chan_ieee,
753 				      uint8_t dfs_chan_vhtop_freq_seg1,
754 				      uint8_t dfs_chan_vhtop_freq_seg2,
755 				      uint16_t dfs_chan_mhz_freq_seg1,
756 				      uint16_t dfs_chan_mhz_freq_seg2,
757 				      uint16_t dfs_ch_punc_pattern,
758 				      bool *is_channel_updated)
759 {
760 	if (is_channel_updated)
761 		*is_channel_updated = false;
762 
763 	if (!dfs) {
764 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
765 		return;
766 	}
767 
768 	/* Check if the input parameters are the same as that of dfs_curchan */
769 	if (dfs_is_curchan_same_as_given_chan(dfs->dfs_curchan,
770 					      dfs_chan_freq,
771 					      dfs_chan_flags,
772 					      dfs_chan_flagext,
773 					      dfs_chan_vhtop_freq_seg1,
774 					      dfs_chan_vhtop_freq_seg2,
775 					      dfs_ch_punc_pattern)) {
776 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
777 			 "dfs_curchan already updated");
778 		return;
779 	}
780 
781 	/* Update dfs previous channel with the old dfs_curchan, if it exists */
782 	if (dfs->dfs_curchan->dfs_ch_freq)
783 		qdf_mem_copy(dfs->dfs_prevchan,
784 			     dfs->dfs_curchan,
785 			     sizeof(struct dfs_channel));
786 
787 	dfs->dfs_curchan->dfs_ch_freq = dfs_chan_freq;
788 	dfs->dfs_curchan->dfs_ch_flags = dfs_chan_flags;
789 	dfs->dfs_curchan->dfs_ch_flagext = dfs_chan_flagext;
790 	dfs->dfs_curchan->dfs_ch_ieee = dfs_chan_ieee;
791 	dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 = dfs_chan_vhtop_freq_seg1;
792 	dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 = dfs_chan_vhtop_freq_seg2;
793 	dfs->dfs_curchan->dfs_ch_mhz_freq_seg1 = dfs_chan_mhz_freq_seg1;
794 	dfs->dfs_curchan->dfs_ch_mhz_freq_seg2 = dfs_chan_mhz_freq_seg2;
795 	dfs_set_cur_chan_punc_pattern(dfs, dfs_ch_punc_pattern);
796 
797 	if (is_channel_updated)
798 		*is_channel_updated = true;
799 }
800 #endif
801 
802 void dfs_update_cur_chan_flags(struct wlan_dfs *dfs,
803 		uint64_t flags,
804 		uint16_t flagext)
805 {
806 	dfs->dfs_curchan->dfs_ch_flags = flags;
807 	dfs->dfs_curchan->dfs_ch_flagext = flagext;
808 }
809 
810 int dfs_reinit_timers(struct wlan_dfs *dfs)
811 {
812 	dfs_cac_timer_attach(dfs);
813 	dfs_zero_cac_timer_init(dfs->dfs_soc_obj);
814 	dfs_main_task_testtimer_init(dfs);
815 	return 0;
816 }
817 
818 void dfs_reset_dfs_prevchan(struct wlan_dfs *dfs)
819 {
820 	qdf_mem_zero(dfs->dfs_prevchan, sizeof(struct dfs_channel));
821 }
822 
823 #ifdef WLAN_DFS_TRUE_160MHZ_SUPPORT
824 bool dfs_is_true_160mhz_supported(struct wlan_dfs *dfs)
825 {
826 	struct wlan_objmgr_psoc *psoc = dfs->dfs_soc_obj->psoc;
827 	struct wlan_lmac_if_target_tx_ops *tgt_tx_ops;
828 	struct wlan_lmac_if_tx_ops *tx_ops;
829 	uint32_t target_type;
830 
831 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
832 	if (!tx_ops) {
833 		 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "tx_ops is NULL");
834 		 return false;
835 	}
836 	target_type = lmac_get_target_type(dfs->dfs_pdev_obj);
837 	tgt_tx_ops = &tx_ops->target_tx_ops;
838 	if (tgt_tx_ops->tgt_is_tgt_type_qcn9000 &&
839 	    tgt_tx_ops->tgt_is_tgt_type_qcn9000(target_type))
840 		return true;
841 
842 	if (tgt_tx_ops->tgt_is_tgt_type_qcn6122 &&
843 	    tgt_tx_ops->tgt_is_tgt_type_qcn6122(target_type))
844 		return true;
845 
846 	return false;
847 }
848 
849 bool dfs_is_restricted_80p80mhz_supported(struct wlan_dfs *dfs)
850 {
851 	return wlan_psoc_nif_fw_ext_cap_get(dfs->dfs_soc_obj->psoc,
852 					    WLAN_SOC_RESTRICTED_80P80_SUPPORT);
853 }
854 #endif
855 
856 #ifdef QCA_SUPPORT_AGILE_DFS
857 uint8_t dfs_get_agile_detector_id(struct wlan_dfs *dfs)
858 {
859 	return dfs->dfs_agile_detector_id;
860 }
861 #endif
862