xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs.c (revision 1397a33f48ea6455be40871470b286e535820eb8)
1 /*
2  * Copyright (c) 2016-2018 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 "../dfs_full_offload.h"
32 #include "wlan_dfs_utils_api.h"
33 #include "../dfs_etsi_precac.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 /*
72  * dfs_free_dfs_curchan() - Free dfs_channel buffer
73  * @dfs_curchan: dfs_channel buffer pointer
74  *
75  * Return: None
76  */
77 static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan)
78 {
79 	qdf_mem_free(dfs_curchan);
80 }
81 
82 #else
83 
84 /* Static buffers for DFS objects */
85 static struct wlan_dfs global_dfs;
86 static struct dfs_channel global_dfs_curchan;
87 
88 static inline struct wlan_dfs *dfs_alloc_wlan_dfs(void)
89 {
90 	return &global_dfs;
91 }
92 
93 static inline void dfs_free_wlan_dfs(struct wlan_dfs *dfs)
94 {
95 }
96 
97 static inline struct dfs_channel *dfs_alloc_dfs_curchan(void)
98 {
99 	return &global_dfs_curchan;
100 }
101 
102 static inline void dfs_free_dfs_curchan(struct dfs_channel *dfs_curchan)
103 {
104 }
105 #endif
106 
107 /**
108  * dfs_testtimer_task() - Sends CSA in the current channel.
109  *
110  * When the user sets usenol to 0 and inject the RADAR, AP does not mark the
111  * channel as RADAR and does not add the channel to NOL. It sends the CSA in
112  * the current channel.
113  */
114 static os_timer_func(dfs_testtimer_task)
115 {
116 	struct wlan_dfs *dfs = NULL;
117 
118 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
119 	dfs->wlan_dfstest = 0;
120 
121 	/*
122 	 * Flip the channel back to the original channel.
123 	 * Make sure this is done properly with a CSA.
124 	 */
125 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "go back to channel %d",
126 			dfs->wlan_dfstest_ieeechan);
127 	dfs_mlme_start_csa(dfs->dfs_pdev_obj,
128 			dfs->wlan_dfstest_ieeechan,
129 			dfs->dfs_curchan->dfs_ch_freq,
130 			dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2,
131 			dfs->dfs_curchan->dfs_ch_flags);
132 }
133 
134 int dfs_get_debug_info(struct wlan_dfs *dfs, void *data)
135 {
136 	if (data)
137 		*(uint32_t *)data = dfs->dfs_proc_phyerr;
138 
139 	return (int)dfs->dfs_proc_phyerr;
140 }
141 
142 void dfs_main_task_testtimer_init(struct wlan_dfs *dfs)
143 {
144 	qdf_timer_init(NULL,
145 		&(dfs->wlan_dfstesttimer),
146 		dfs_testtimer_task, (void *)dfs,
147 		QDF_TIMER_TYPE_WAKE_APPS);
148 }
149 
150 int dfs_create_object(struct wlan_dfs **dfs)
151 {
152 	*dfs = dfs_alloc_wlan_dfs();
153 	if (!(*dfs)) {
154 		dfs_alert(NULL, WLAN_DEBUG_DFS_ALWAYS,
155 			  "wlan_dfs allocation failed");
156 		return 1;
157 	}
158 
159 	qdf_mem_zero(*dfs, sizeof(**dfs));
160 
161 	(*dfs)->dfs_curchan = dfs_alloc_dfs_curchan();
162 	if (!((*dfs)->dfs_curchan)) {
163 		dfs_free_wlan_dfs(*dfs);
164 		dfs_alert(*dfs, WLAN_DEBUG_DFS_ALWAYS,
165 			  "dfs_curchan allocation failed");
166 		return 1;
167 	}
168 
169 	return 0;
170 }
171 
172 int dfs_attach(struct wlan_dfs *dfs)
173 {
174 	int ret;
175 
176 	if (!dfs->dfs_is_offload_enabled) {
177 		ret = dfs_main_attach(dfs);
178 
179 		/*
180 		 * For full offload we have a wmi handler registered to process
181 		 * a radar event from firmware in the event of a radar detect.
182 		 * So, init of timer, dfs_task is not required for
183 		 * full-offload. dfs_task timer is called in
184 		 * dfs_main_timer_init within dfs_main_attach for
185 		 * partial-offload in the event of radar detect.
186 		 */
187 		if (ret) {
188 			dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_main_attach failed");
189 			return ret;
190 		}
191 	}
192 	dfs_cac_attach(dfs);
193 	dfs_zero_cac_attach(dfs);
194 	dfs_etsi_precac_attach(dfs);
195 	dfs_nol_attach(dfs);
196 
197 	/*
198 	 * Init of timer ,dfs_testtimer_task is required by both partial
199 	 * and full offload, indicating test mode timer initialization for both.
200 	 */
201 	dfs_main_task_testtimer_init(dfs);
202 	return 0;
203 }
204 
205 void dfs_stop(struct wlan_dfs *dfs)
206 {
207 	dfs_nol_timer_cleanup(dfs);
208 	dfs_nol_workqueue_cleanup(dfs);
209 	dfs_clear_nolhistory(dfs);
210 }
211 
212 void dfs_task_testtimer_reset(struct wlan_dfs *dfs)
213 {
214 	if (dfs->wlan_dfstest) {
215 		qdf_timer_sync_cancel(&dfs->wlan_dfstesttimer);
216 		dfs->wlan_dfstest = 0;
217 	}
218 }
219 
220 void dfs_task_testtimer_detach(struct wlan_dfs *dfs)
221 {
222 	qdf_timer_free(&dfs->wlan_dfstesttimer);
223 	dfs->wlan_dfstest = 0;
224 }
225 
226 void dfs_reset(struct wlan_dfs *dfs)
227 {
228 	if (!dfs) {
229 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
230 		return;
231 	}
232 
233 	dfs_cac_timer_reset(dfs);
234 	dfs_zero_cac_reset(dfs);
235 	if (!dfs->dfs_is_offload_enabled) {
236 		dfs_main_timer_reset(dfs);
237 		dfs_host_wait_timer_reset(dfs);
238 		dfs_false_radarfound_reset_vars(dfs);
239 	}
240 	dfs_task_testtimer_reset(dfs);
241 }
242 
243 void dfs_timer_detach(struct wlan_dfs *dfs)
244 {
245 	dfs_cac_timer_detach(dfs);
246 	dfs_zero_cac_timer_detach(dfs);
247 
248 	if (!dfs->dfs_is_offload_enabled) {
249 		dfs_main_timer_detach(dfs);
250 		dfs_host_wait_timer_detach(dfs);
251 	}
252 
253 	dfs_task_testtimer_detach(dfs);
254 	dfs_nol_timer_detach(dfs);
255 }
256 
257 void dfs_detach(struct wlan_dfs *dfs)
258 {
259 	dfs_timer_detach(dfs);
260 	if (!dfs->dfs_is_offload_enabled)
261 		dfs_main_detach(dfs);
262 	dfs_etsi_precac_detach(dfs);
263 	dfs_zero_cac_detach(dfs);
264 	dfs_nol_detach(dfs);
265 }
266 
267 #ifndef WLAN_DFS_STATIC_MEM_ALLOC
268 void dfs_destroy_object(struct wlan_dfs *dfs)
269 {
270 	dfs_free_dfs_curchan(dfs->dfs_curchan);
271 	dfs_free_wlan_dfs(dfs);
272 }
273 #else
274 void dfs_destroy_object(struct wlan_dfs *dfs)
275 {
276 }
277 #endif
278 
279 /* dfs_set_disable_radar_marking()- Set the flag to mark/unmark a radar flag
280  * on NOL channel.
281  * @dfs: Pointer to wlan_dfs structure.
282  * @disable_radar_marking: Flag to enable/disable marking channel as radar.
283  */
284 #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD)
285 static void dfs_set_disable_radar_marking(struct wlan_dfs *dfs,
286 					  bool disable_radar_marking)
287 {
288 	dfs->dfs_disable_radar_marking = disable_radar_marking;
289 }
290 #else
291 static inline void dfs_set_disable_radar_marking(struct wlan_dfs *dfs,
292 						 bool disable_radar_marking)
293 {
294 }
295 #endif
296 
297 #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD)
298 bool dfs_get_disable_radar_marking(struct wlan_dfs *dfs)
299 {
300 	return dfs->dfs_disable_radar_marking;
301 }
302 #else
303 static inline bool dfs_get_disable_radar_marking(struct wlan_dfs *dfs)
304 {
305 	return QDF_STATUS_SUCCESS;
306 }
307 #endif
308 int dfs_control(struct wlan_dfs *dfs,
309 		u_int id,
310 		void *indata,
311 		uint32_t insize,
312 		void *outdata,
313 		uint32_t *outsize)
314 {
315 	struct wlan_dfs_phyerr_param peout;
316 	struct dfs_ioctl_params *dfsparams;
317 	struct dfs_bangradar_enh_params *bangradar_enh_params;
318 	int error = 0;
319 	uint32_t val = 0;
320 	struct dfsreq_nolinfo *nol;
321 	uint32_t *data = NULL;
322 	int i;
323 	struct dfs_emulate_bang_radar_test_cmd dfs_unit_test;
324 	int usenol_pdev_param;
325 
326 	qdf_mem_zero(&dfs_unit_test, sizeof(dfs_unit_test));
327 
328 	if (!dfs) {
329 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
330 		goto bad;
331 	}
332 
333 	switch (id) {
334 	case DFS_SET_THRESH:
335 		if (insize < sizeof(struct dfs_ioctl_params) || !indata) {
336 			dfs_debug(dfs, WLAN_DEBUG_DFS1,
337 					"insize = %d, expected = %zu bytes, indata = %pK",
338 					insize,
339 					sizeof(struct dfs_ioctl_params),
340 					indata);
341 			error = -EINVAL;
342 			break;
343 		}
344 		dfsparams = (struct dfs_ioctl_params *)indata;
345 		if (!dfs_set_thresholds(dfs, DFS_PARAM_FIRPWR,
346 					dfsparams->dfs_firpwr))
347 			error = -EINVAL;
348 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RRSSI,
349 					dfsparams->dfs_rrssi))
350 			error = -EINVAL;
351 		if (!dfs_set_thresholds(dfs, DFS_PARAM_HEIGHT,
352 					dfsparams->dfs_height))
353 			error = -EINVAL;
354 		if (!dfs_set_thresholds(dfs, DFS_PARAM_PRSSI,
355 					dfsparams->dfs_prssi))
356 			error = -EINVAL;
357 		if (!dfs_set_thresholds(dfs, DFS_PARAM_INBAND,
358 					dfsparams->dfs_inband))
359 			error = -EINVAL;
360 
361 		/* 5413 speicfic. */
362 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RELPWR,
363 					dfsparams->dfs_relpwr))
364 			error = -EINVAL;
365 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RELSTEP,
366 					dfsparams->dfs_relstep))
367 			error = -EINVAL;
368 		if (!dfs_set_thresholds(dfs, DFS_PARAM_MAXLEN,
369 					dfsparams->dfs_maxlen))
370 			error = -EINVAL;
371 		break;
372 	case DFS_BANGRADAR_ENH:
373 		if (insize < sizeof(struct dfs_bangradar_enh_params) ||
374 		    !indata) {
375 			dfs_debug(dfs, WLAN_DEBUG_DFS1,
376 				  "insize = %d, expected = %zu bytes, indata = %pK",
377 				  insize,
378 				  sizeof(struct dfs_bangradar_enh_params),
379 				  indata);
380 			error = -EINVAL;
381 			break;
382 		}
383 		bangradar_enh_params =
384 				      (struct dfs_bangradar_enh_params *)indata;
385 		if (bangradar_enh_params) {
386 			if (abs(bangradar_enh_params->freq_offset) >
387 			    FREQ_OFFSET_BOUNDARY_FOR_80MHZ) {
388 				dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
389 					 "Frequency Offset out of bound");
390 				error = -EINVAL;
391 				break;
392 			}
393 			dfs->dfs_seg_id = bangradar_enh_params->seg_id;
394 			dfs->dfs_is_chirp = bangradar_enh_params->is_chirp;
395 			dfs->dfs_freq_offset =
396 					      bangradar_enh_params->freq_offset;
397 
398 			if (dfs->dfs_is_offload_enabled) {
399 				error = dfs_fill_emulate_bang_radar_test
400 						 (dfs, dfs->dfs_seg_id,
401 						  &dfs_unit_test);
402 			} else {
403 				dfs->dfs_enh_bangradar = true;
404 				dfs->dfs_bangradar = 0;
405 				error = dfs_start_host_based_bangradar(dfs);
406 			}
407 		} else {
408 			dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "bangradar_enh_params is NULL");
409 		}
410 
411 		break;
412 	case DFS_GET_THRESH:
413 		if (!outdata || !outsize ||
414 				*outsize < sizeof(struct dfs_ioctl_params)) {
415 			error = -EINVAL;
416 			break;
417 		}
418 		*outsize = sizeof(struct dfs_ioctl_params);
419 		dfsparams = (struct dfs_ioctl_params *) outdata;
420 
421 		qdf_mem_zero(&peout, sizeof(struct wlan_dfs_phyerr_param));
422 
423 		/* Fetch the DFS thresholds using the internal representation */
424 		(void) dfs_get_thresholds(dfs, &peout);
425 
426 		/* Convert them to the dfs IOCTL representation. */
427 		wlan_dfs_dfsparam_to_ioctlparam(&peout, dfsparams);
428 		break;
429 	case DFS_RADARDETECTS:
430 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
431 			error = -EINVAL;
432 			break;
433 		}
434 		*outsize = sizeof(uint32_t);
435 		*((uint32_t *)outdata) = dfs->wlan_dfs_stats.num_radar_detects;
436 		break;
437 	case DFS_DISABLE_DETECT:
438 		dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
439 		dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
440 		dfs->dfs_ignore_dfs = 1;
441 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
442 				"enable detects, ignore_dfs %d",
443 				dfs->dfs_ignore_dfs ? 1:0);
444 		break;
445 	case DFS_ENABLE_DETECT:
446 		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
447 		dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN;
448 		dfs->dfs_ignore_dfs = 0;
449 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS
450 				, "enable detects, ignore_dfs %d",
451 				dfs->dfs_ignore_dfs ? 1:0);
452 		break;
453 	case DFS_DISABLE_FFT:
454 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
455 				"TODO disable FFT val=0x%x", val);
456 		break;
457 	case DFS_ENABLE_FFT:
458 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
459 				"TODO enable FFT val=0x%x", val);
460 		break;
461 	case DFS_SET_DEBUG_LEVEL:
462 		if (insize < sizeof(uint32_t) || !indata) {
463 			error = -EINVAL;
464 			break;
465 		}
466 		dfs->dfs_debug_mask = *(uint32_t *)indata;
467 
468 		/* Do not allow user to set the ALWAYS/MAX bit.
469 		 * It will be used internally  by dfs print macro(s)
470 		 * to print messages when dfs is NULL.
471 		 */
472 		dfs->dfs_debug_mask &= ~(WLAN_DEBUG_DFS_ALWAYS);
473 
474 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
475 				"debug level now = 0x%x", dfs->dfs_debug_mask);
476 		if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS3) {
477 			/* Enable debug Radar Event */
478 			dfs->dfs_event_log_on = 1;
479 		} else if ((utils_get_dfsdomain(dfs->dfs_pdev_obj) ==
480 		    DFS_FCC_DOMAIN) &&
481 		    lmac_is_host_dfs_check_support_enabled(dfs->dfs_pdev_obj)) {
482 			dfs->dfs_event_log_on = 1;
483 		} else {
484 			dfs->dfs_event_log_on = 0;
485 		}
486 		break;
487 	case DFS_SET_FALSE_RSSI_THRES:
488 		if (insize < sizeof(uint32_t) || !indata) {
489 			error = -EINVAL;
490 			break;
491 		}
492 		dfs->wlan_dfs_false_rssi_thres = *(uint32_t *)indata;
493 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
494 				"false RSSI threshold now = 0x%x",
495 				dfs->wlan_dfs_false_rssi_thres);
496 		break;
497 	case DFS_SET_PEAK_MAG:
498 		if (insize < sizeof(uint32_t) || !indata) {
499 			error = -EINVAL;
500 			break;
501 		}
502 		dfs->wlan_dfs_peak_mag = *(uint32_t *)indata;
503 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
504 				"peak_mag now = 0x%x",
505 				dfs->wlan_dfs_peak_mag);
506 		break;
507 	case DFS_GET_CAC_VALID_TIME:
508 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
509 			error = -EINVAL;
510 			break;
511 		}
512 		*outsize = sizeof(uint32_t);
513 		*((uint32_t *)outdata) = dfs->dfs_cac_valid_time;
514 		break;
515 	case DFS_SET_CAC_VALID_TIME:
516 		if (insize < sizeof(uint32_t) || !indata) {
517 			error = -EINVAL;
518 			break;
519 		}
520 		dfs->dfs_cac_valid_time = *(uint32_t *)indata;
521 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
522 				"dfs timeout = %d", dfs->dfs_cac_valid_time);
523 		break;
524 	case DFS_IGNORE_CAC:
525 		if (insize < sizeof(uint32_t) || !indata) {
526 			error = -EINVAL;
527 			break;
528 		}
529 
530 		if (*(uint32_t *)indata)
531 			dfs->dfs_ignore_cac = 1;
532 		else
533 			dfs->dfs_ignore_cac = 0;
534 
535 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
536 				"ignore cac = 0x%x", dfs->dfs_ignore_cac);
537 		break;
538 	case DFS_SET_NOL_TIMEOUT:
539 		if (insize < sizeof(uint32_t) || !indata) {
540 			error = -EINVAL;
541 			break;
542 		}
543 		if (*(int *)indata)
544 			dfs->wlan_dfs_nol_timeout = *(int *)indata;
545 		else
546 			dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S;
547 
548 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol timeout = %d sec",
549 				dfs->wlan_dfs_nol_timeout);
550 		break;
551 	case DFS_MUTE_TIME:
552 		if (insize < sizeof(uint32_t) || !indata) {
553 			error = -EINVAL;
554 			break;
555 		}
556 		data = (uint32_t *) indata;
557 		dfs->wlan_dfstesttime = *data;
558 		dfs->wlan_dfstesttime *= (1000); /* convert sec into ms */
559 		break;
560 	case DFS_GET_USENOL:
561 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
562 			error = -EINVAL;
563 			break;
564 		}
565 		*outsize = sizeof(uint32_t);
566 		*((uint32_t *)outdata) = dfs->dfs_use_nol;
567 
568 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
569 				"#Phyerr=%d, #false detect=%d, #queued=%d",
570 				 dfs->dfs_phyerr_count,
571 				dfs->dfs_phyerr_reject_count,
572 				dfs->dfs_phyerr_queued_count);
573 
574 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
575 				"dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d",
576 				 dfs->dfs_phyerr_freq_min,
577 				dfs->dfs_phyerr_freq_max);
578 
579 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
580 				"Total radar events detected=%d, entries in the radar queue follows:",
581 				 dfs->dfs_event_log_count);
582 
583 		for (i = 0; (i < DFS_EVENT_LOG_SIZE) &&
584 				(i < dfs->dfs_event_log_count); i++) {
585 #define FREQ_OFFSET1 ((int)dfs->radar_log[i].freq_offset_khz / 1000)
586 #define FREQ_OFFSET2 ((int)abs(dfs->radar_log[i].freq_offset_khz) % 1000)
587 			dfs_debug(dfs, WLAN_DEBUG_DFS,
588 					"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",
589 					dfs->radar_log[i].ts,
590 					dfs->radar_log[i].diff_ts,
591 					dfs->radar_log[i].rssi,
592 					dfs->radar_log[i].dur,
593 					dfs->radar_log[i].is_chirp,
594 					dfs->radar_log[i].seg_id,
595 					dfs->radar_log[i].sidx,
596 					FREQ_OFFSET1,
597 					FREQ_OFFSET2,
598 					dfs->radar_log[i].peak_mag,
599 					dfs->radar_log[i].total_gain,
600 					dfs->radar_log[i].mb_gain,
601 					dfs->radar_log[i].relpwr_db,
602 					dfs->radar_log[i].delta_diff,
603 					dfs->radar_log[i].delta_peak,
604 					dfs->radar_log[i].psidx_diff);
605 		}
606 		dfs->dfs_event_log_count = 0;
607 		dfs->dfs_phyerr_count = 0;
608 		dfs->dfs_phyerr_reject_count = 0;
609 		dfs->dfs_phyerr_queued_count = 0;
610 		dfs->dfs_phyerr_freq_min = 0x7fffffff;
611 		dfs->dfs_phyerr_freq_max = 0;
612 		break;
613 	case DFS_SET_USENOL:
614 		if (insize < sizeof(uint32_t) || !indata) {
615 			error = -EINVAL;
616 			break;
617 		}
618 		dfs->dfs_use_nol = *(uint32_t *)indata;
619 		usenol_pdev_param = dfs->dfs_use_nol;
620 		if (dfs->dfs_is_offload_enabled) {
621 			if (dfs->dfs_use_nol ==
622 				USENOL_ENABLE_NOL_HOST_DISABLE_NOL_FW)
623 				usenol_pdev_param = DISABLE_NOL_FW;
624 			tgt_dfs_send_usenol_pdev_param(dfs->dfs_pdev_obj,
625 						       usenol_pdev_param);
626 		}
627 		break;
628 	case DFS_SET_DISABLE_RADAR_MARKING:
629 		if (dfs->dfs_is_offload_enabled &&
630 		    (utils_get_dfsdomain(dfs->dfs_pdev_obj) ==
631 			 DFS_FCC_DOMAIN)) {
632 			if (insize < sizeof(uint32_t) || !indata) {
633 				error = -EINVAL;
634 				break;
635 			}
636 			dfs_set_disable_radar_marking(dfs, *(uint8_t *)indata);
637 		}
638 		break;
639 	case DFS_GET_DISABLE_RADAR_MARKING:
640 		if (!outdata || !outsize || *outsize < sizeof(uint8_t)) {
641 			error = -EINVAL;
642 			break;
643 		}
644 		if (dfs->dfs_is_offload_enabled) {
645 			*outsize = sizeof(uint8_t);
646 			*((uint8_t *)outdata) =
647 				dfs_get_disable_radar_marking(dfs);
648 		}
649 		break;
650 	case DFS_GET_NOL:
651 		if (!outdata || !outsize ||
652 				*outsize < sizeof(struct dfsreq_nolinfo)) {
653 			error = -EINVAL;
654 			break;
655 		}
656 		*outsize = sizeof(struct dfsreq_nolinfo);
657 		nol = (struct dfsreq_nolinfo *)outdata;
658 		DFS_GET_NOL_LOCKED(dfs,
659 				(struct dfsreq_nolelem *)nol->dfs_nol,
660 				&nol->dfs_ch_nchans);
661 		DFS_PRINT_NOL_LOCKED(dfs);
662 		break;
663 	case DFS_SET_NOL:
664 		if (insize < sizeof(struct dfsreq_nolinfo) || !indata) {
665 			error = -EINVAL;
666 			break;
667 		}
668 		nol = (struct dfsreq_nolinfo *) indata;
669 		dfs_set_nol(dfs,
670 				(struct dfsreq_nolelem *)nol->dfs_nol,
671 				nol->dfs_ch_nchans);
672 		break;
673 	case DFS_SHOW_NOL:
674 		DFS_PRINT_NOL_LOCKED(dfs);
675 		break;
676 	case DFS_SHOW_NOLHISTORY:
677 		dfs_print_nolhistory(dfs);
678 		break;
679 	case DFS_BANGRADAR:
680 		dfs->dfs_bangradar = 1;
681 		if (dfs->dfs_is_offload_enabled) {
682 			error = dfs_fill_emulate_bang_radar_test(dfs,
683 					SEG_ID_PRIMARY,
684 					&dfs_unit_test);
685 		} else {
686 			error = dfs_start_host_based_bangradar(dfs);
687 		}
688 		break;
689 	case DFS_SHOW_PRECAC_LISTS:
690 		dfs_print_precaclists(dfs);
691 		dfs_print_etsi_precaclists(dfs);
692 		break;
693 	case DFS_RESET_PRECAC_LISTS:
694 		dfs_reset_precac_lists(dfs);
695 		dfs_reset_etsi_precac_lists(dfs);
696 		break;
697 	case DFS_SECOND_SEGMENT_BANGRADAR:
698 		if (dfs->dfs_is_offload_enabled) {
699 			error = dfs_fill_emulate_bang_radar_test(dfs,
700 					SEG_ID_SECONDARY,
701 					&dfs_unit_test);
702 		} else {
703 			dfs->dfs_second_segment_bangradar = 1;
704 			error = dfs_start_host_based_bangradar(dfs);
705 		}
706 		break;
707 	default:
708 		error = -EINVAL;
709 	}
710 
711 bad:
712 	return error;
713 }
714 
715 void dfs_set_current_channel(struct wlan_dfs *dfs,
716 		uint16_t dfs_ch_freq,
717 		uint64_t dfs_ch_flags,
718 		uint16_t dfs_ch_flagext,
719 		uint8_t dfs_ch_ieee,
720 		uint8_t dfs_ch_vhtop_ch_freq_seg1,
721 		uint8_t dfs_ch_vhtop_ch_freq_seg2)
722 {
723 	if (!dfs) {
724 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
725 		return;
726 	}
727 
728 	dfs->dfs_curchan->dfs_ch_freq = dfs_ch_freq;
729 	dfs->dfs_curchan->dfs_ch_flags = dfs_ch_flags;
730 	dfs->dfs_curchan->dfs_ch_flagext = dfs_ch_flagext;
731 	dfs->dfs_curchan->dfs_ch_ieee = dfs_ch_ieee;
732 	dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 = dfs_ch_vhtop_ch_freq_seg1;
733 	dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 = dfs_ch_vhtop_ch_freq_seg2;
734 }
735 
736 void dfs_update_cur_chan_flags(struct wlan_dfs *dfs,
737 		uint64_t flags,
738 		uint16_t flagext)
739 {
740 	dfs->dfs_curchan->dfs_ch_flags = flags;
741 	dfs->dfs_curchan->dfs_ch_flagext = flagext;
742 }
743