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