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