xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
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 
31 /*
32  * Channel switch announcement (CSA)
33  * usenol=1 (default) make CSA and switch to a new channel on radar detect
34  * usenol=0, make CSA with next channel same as current on radar detect
35  * usenol=2, no CSA and stay on the same channel on radar detect
36  */
37 
38 static int usenol = 1;
39 
40 /**
41  * dfs_task() - The timer function to process the radar pulses.
42  */
43 static os_timer_func(dfs_task)
44 {
45 	struct wlan_dfs *dfs = NULL;
46 
47 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
48 
49 	if (!dfs) {
50 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
51 		return;
52 	}
53 
54 	dfs_process_radarevent(dfs, dfs->dfs_curchan);
55 
56 	dfs->wlan_radar_tasksched = 0;
57 }
58 
59 /**
60  * dfs_testtimer_task() - Sends CSA in the current channel.
61  *
62  * When the user sets usenol to 0 and inject the RADAR, AP does not mark the
63  * channel as RADAR and does not add the channel to NOL. It sends the CSA in
64  * the current channel.
65  */
66 static os_timer_func(dfs_testtimer_task)
67 {
68 	struct wlan_dfs *dfs = NULL;
69 
70 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
71 	dfs->wlan_dfstest = 0;
72 
73 	/*
74 	 * Flip the channel back to the original channel.
75 	 * Make sure this is done properly with a CSA.
76 	 */
77 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "go back to channel %d",
78 			dfs->wlan_dfstest_ieeechan);
79 	dfs_mlme_start_csa(dfs->dfs_pdev_obj,
80 			dfs->wlan_dfstest_ieeechan,
81 			dfs->dfs_curchan->dfs_ch_freq,
82 			dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2,
83 			dfs->dfs_curchan->dfs_ch_flags);
84 }
85 
86 static inline int dfs_fill_emulate_bang_radar_test(struct wlan_dfs *dfs,
87 		uint32_t segid,
88 		struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test)
89 {
90 	/*
91 	 * More parameters are to be added later indicating
92 	 * seg id, chirp and sidx values to be sent to fw.
93 	 */
94 	dfs_unit_test->num_args = DFS_UNIT_TEST_NUM_ARGS;
95 	dfs_unit_test->args[IDX_CMD_ID] =
96 			DFS_PHYERR_OFFLOAD_TEST_SET_RADAR;
97 	dfs_unit_test->args[IDX_PDEV_ID] =
98 			wlan_objmgr_pdev_get_pdev_id(dfs->dfs_pdev_obj);
99 	dfs_unit_test->args[IDX_SEG_ID] = segid;
100 
101 	if (tgt_dfs_process_emulate_bang_radar_cmd(dfs->dfs_pdev_obj,
102 				dfs_unit_test) == QDF_STATUS_E_FAILURE) {
103 		return -EINVAL;
104 	}
105 
106 	return 0;
107 }
108 
109 int dfs_get_debug_info(struct wlan_dfs *dfs, void *data)
110 {
111 	if (data)
112 		*(uint32_t *)data = dfs->dfs_proc_phyerr;
113 
114 	return (int)dfs->dfs_proc_phyerr;
115 }
116 
117 void dfs_main_task_timer_init(struct wlan_dfs *dfs)
118 {
119 	qdf_timer_init(NULL,
120 			&(dfs->wlan_dfs_task_timer),
121 			dfs_task,
122 			(void *)(dfs),
123 			QDF_TIMER_TYPE_WAKE_APPS);
124 }
125 
126 void dfs_main_task_testtimer_init(struct wlan_dfs *dfs)
127 {
128 	qdf_timer_init(NULL,
129 		&(dfs->wlan_dfstesttimer),
130 		dfs_testtimer_task, (void *)dfs,
131 		QDF_TIMER_TYPE_WAKE_APPS);
132 }
133 
134 int dfs_create_object(struct wlan_dfs **dfs)
135 {
136 	*dfs = (struct wlan_dfs *)qdf_mem_malloc(sizeof(**dfs));
137 	if (!(*dfs)) {
138 		dfs_alert(*dfs, WLAN_DEBUG_DFS_ALWAYS, "wlan_dfs allocation failed");
139 		return 1;
140 	}
141 
142 	qdf_mem_zero(*dfs, sizeof(**dfs));
143 
144 	(*dfs)->dfs_curchan = (struct dfs_channel *)qdf_mem_malloc(
145 			sizeof(struct dfs_channel));
146 
147 	if (!((*dfs)->dfs_curchan)) {
148 		dfs_alert(*dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_curchan allocation failed");
149 		return 1;
150 	}
151 
152 	return 0;
153 }
154 
155 int dfs_main_attach(struct wlan_dfs *dfs)
156 {
157 	int i, n;
158 	struct wlan_dfs_radar_tab_info radar_info;
159 
160 	if (!dfs) {
161 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
162 		return 0;
163 	}
164 
165 	/* If ignore_dfs is set to 1 then Radar detection is disabled. */
166 	if (dfs->dfs_ignore_dfs) {
167 		dfs_debug(dfs, WLAN_DEBUG_DFS1, "ignoring dfs");
168 		return 0;
169 	}
170 
171 	/*
172 	 * Zero out radar_info. It's possible that the attach function
173 	 * won't fetch an initial regulatory configuration; you really
174 	 * do want to ensure that the contents indicates there aren't
175 	 * any filters.
176 	 */
177 	qdf_mem_zero(&radar_info, sizeof(radar_info));
178 
179 	lmac_get_caps(dfs->dfs_pdev_obj, &(dfs->dfs_caps));
180 
181 	dfs_clear_stats(dfs);
182 	dfs->dfs_event_log_on = 1;
183 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "event log enabled by default");
184 
185 	dfs->dfs_enable = 1;
186 
187 	/*Verify : Passing NULL to qdf_timer_init().*/
188 	dfs_main_task_timer_init(dfs);
189 
190 	WLAN_DFSQ_LOCK_CREATE(dfs);
191 	STAILQ_INIT(&dfs->dfs_radarq);
192 	WLAN_ARQ_LOCK_CREATE(dfs);
193 	STAILQ_INIT(&dfs->dfs_arq);
194 	STAILQ_INIT(&(dfs->dfs_eventq));
195 	WLAN_DFSEVENTQ_LOCK_CREATE(dfs);
196 
197 	dfs->events = (struct dfs_event *)qdf_mem_malloc(
198 			sizeof(struct dfs_event)*DFS_MAX_EVENTS);
199 	if (!(dfs->events)) {
200 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "events allocation failed");
201 		return 1;
202 	}
203 	for (i = 0; i < DFS_MAX_EVENTS; i++)
204 		STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i],
205 				re_list);
206 
207 	dfs->pulses = (struct dfs_pulseline *)qdf_mem_malloc(
208 			sizeof(struct dfs_pulseline));
209 	if (!(dfs->pulses)) {
210 		qdf_mem_free(dfs->events);
211 		dfs->events = NULL;
212 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Pulse buffer allocation failed");
213 		return 1;
214 	}
215 
216 	dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK;
217 
218 	/* Allocate memory for radar filters. */
219 	for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) {
220 		dfs->dfs_radarf[n] = (struct dfs_filtertype *)
221 			qdf_mem_malloc(sizeof(struct dfs_filtertype));
222 		if (!(dfs->dfs_radarf[n])) {
223 			dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
224 					"cannot allocate memory for radar filter types");
225 			goto bad1;
226 		}
227 		qdf_mem_zero(dfs->dfs_radarf[n], sizeof(struct dfs_filtertype));
228 	}
229 
230 	/* Allocate memory for radar table. */
231 	dfs->dfs_ftindextable = (int8_t **)qdf_mem_malloc(256*sizeof(int8_t *));
232 	if (!(dfs->dfs_ftindextable)) {
233 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Cannot allocate memory for radar table");
234 		goto bad1;
235 	}
236 	for (n = 0; n < 256; n++) {
237 		dfs->dfs_ftindextable[n] = qdf_mem_malloc(
238 				DFS_MAX_RADAR_OVERLAP*sizeof(int8_t));
239 		if (!(dfs->dfs_ftindextable[n])) {
240 			dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
241 					"cannot allocate memory for radar table entry");
242 			goto bad2;
243 		}
244 	}
245 
246 	if (usenol == 0)
247 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "NOL disabled");
248 	else if (usenol == 2)
249 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "NOL disabled; no CSA");
250 
251 	dfs->dfs_use_nol = usenol;
252 
253 	/* Init the cached extension channel busy for false alarm reduction */
254 	dfs->dfs_rinfo.ext_chan_busy_ts = lmac_get_tsf64(dfs->dfs_pdev_obj);
255 	dfs->dfs_rinfo.dfs_ext_chan_busy = 0;
256 	/* Init the Bin5 chirping related data */
257 	dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts;
258 	dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR;
259 	dfs->dfs_b5radars = NULL;
260 
261 	/*
262 	 * If dfs_init_radar_filters() fails, we can abort here and
263 	 * reconfigure when the first valid channel + radar config
264 	 * is available.
265 	 */
266 	if (dfs_init_radar_filters(dfs, &radar_info)) {
267 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Radar Filter Intialization Failed");
268 		return 1;
269 	}
270 
271 	dfs->wlan_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE;
272 	dfs->wlan_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH;
273 	dfs->dfs_phyerr_freq_min     = 0x7fffffff;
274 	dfs->dfs_phyerr_freq_max     = 0;
275 	dfs->dfs_phyerr_queued_count = 0;
276 	dfs->dfs_phyerr_w53_counter  = 0;
277 	dfs->dfs_pri_multiplier      = 2;
278 	dfs_get_radars(dfs);
279 	dfs_set_phyerr_filter_offload(dfs);
280 
281 	return 0;
282 
283 bad2:
284 	qdf_mem_free(dfs->dfs_ftindextable);
285 	dfs->dfs_ftindextable = NULL;
286 bad1:
287 	for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) {
288 		if (dfs->dfs_radarf[n] != NULL) {
289 			qdf_mem_free(dfs->dfs_radarf[n]);
290 			dfs->dfs_radarf[n] = NULL;
291 		}
292 	}
293 	if (dfs->pulses) {
294 		qdf_mem_free(dfs->pulses);
295 		dfs->pulses = NULL;
296 	}
297 	qdf_mem_free(dfs->events);
298 	dfs->events = NULL;
299 
300 	return 1;
301 }
302 
303 int dfs_attach(struct wlan_dfs *dfs)
304 {
305 	int ret;
306 
307 	if (!dfs->dfs_is_offload_enabled) {
308 		ret = dfs_main_attach(dfs);
309 
310 	/*
311 	 * For full offload we have a wmi handler registered to process a radar
312 	 * event from firmware in the event of a radar detect.So ,init of timer,
313 	 * dfs_task is not required for full offload. dfs_task timer is called
314 	 * in dfs_main_timer_init within dfs_main_attach for partial offload
315 	 * in the event of radar detect.
316 	 */
317 		if (ret) {
318 			dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_main_attach failed");
319 			return ret;
320 		}
321 	}
322 	dfs_cac_attach(dfs);
323 	dfs_zero_cac_attach(dfs);
324 	dfs_nol_attach(dfs);
325 
326 	/*
327 	 * Init of timer ,dfs_testtimer_task is required by both partial
328 	 * and full offload, indicating test mode timer initilization for both.
329 	 */
330 	dfs_main_task_testtimer_init(dfs);
331 	return 0;
332 }
333 
334 void dfs_stop(struct wlan_dfs *dfs)
335 {
336 	dfs_nol_timer_cleanup(dfs);
337 	dfs_nol_workqueue_cleanup(dfs);
338 	dfs_clear_nolhistory(dfs);
339 }
340 
341 void dfs_main_timer_reset(struct wlan_dfs *dfs)
342 {
343 	if (dfs->wlan_radar_tasksched) {
344 		qdf_timer_stop(&dfs->wlan_dfs_task_timer);
345 		dfs->wlan_radar_tasksched = 0;
346 	}
347 
348 	if (dfs->wlan_dfstest) {
349 		qdf_timer_stop(&dfs->wlan_dfstesttimer);
350 		dfs->wlan_dfstest = 0;
351 	}
352 }
353 
354 void dfs_reset(struct wlan_dfs *dfs)
355 {
356 	if (!dfs) {
357 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
358 		return;
359 	}
360 
361 	dfs_cac_timer_reset(dfs);
362 	dfs_zero_cac_reset(dfs);
363 	if (!dfs->dfs_is_offload_enabled)
364 		dfs_main_timer_reset(dfs);
365 }
366 
367 void dfs_main_detach(struct wlan_dfs *dfs)
368 {
369 	int n, empty;
370 
371 	if (!dfs->dfs_enable)
372 		return;
373 
374 	dfs->dfs_enable = 0;
375 
376 	if (dfs->dfs_curchan != NULL) {
377 		qdf_mem_free(dfs->dfs_curchan);
378 		dfs->dfs_curchan = NULL;
379 	}
380 
381 	dfs_reset_radarq(dfs);
382 	dfs_reset_alldelaylines(dfs);
383 
384 	if (dfs->pulses != NULL) {
385 		qdf_mem_free(dfs->pulses);
386 		dfs->pulses = NULL;
387 	}
388 
389 	for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) {
390 		if (dfs->dfs_radarf[n] != NULL) {
391 			qdf_mem_free(dfs->dfs_radarf[n]);
392 			dfs->dfs_radarf[n] = NULL;
393 		}
394 	}
395 
396 	if (dfs->dfs_ftindextable != NULL) {
397 		for (n = 0; n < 256; n++) {
398 			if (dfs->dfs_ftindextable[n] != NULL) {
399 				qdf_mem_free(dfs->dfs_ftindextable[n]);
400 				dfs->dfs_ftindextable[n] = NULL;
401 			}
402 		}
403 		qdf_mem_free(dfs->dfs_ftindextable);
404 		dfs->dfs_ftindextable = NULL;
405 		dfs->wlan_dfs_isdfsregdomain = 0;
406 	}
407 
408 	if (dfs->dfs_b5radars != NULL) {
409 		qdf_mem_free(dfs->dfs_b5radars);
410 		dfs->dfs_b5radars = NULL;
411 	}
412 
413 	dfs_reset_ar(dfs);
414 
415 	WLAN_ARQ_LOCK(dfs);
416 	empty = STAILQ_EMPTY(&(dfs->dfs_arq));
417 	WLAN_ARQ_UNLOCK(dfs);
418 	if (!empty)
419 		dfs_reset_arq(dfs);
420 
421 	if (dfs->events != NULL) {
422 		qdf_mem_free(dfs->events);
423 		dfs->events = NULL;
424 	}
425 
426 	WLAN_DFSQ_LOCK_DESTROY(dfs);
427 	WLAN_ARQ_LOCK_DESTROY(dfs);
428 	WLAN_DFSEVENTQ_LOCK_DESTROY(dfs);
429 }
430 
431 void dfs_detach(struct wlan_dfs *dfs)
432 {
433 	if (!dfs->dfs_is_offload_enabled)
434 		dfs_main_detach(dfs);
435 	dfs_zero_cac_detach(dfs);
436 	dfs_nol_detach(dfs);
437 }
438 
439 void dfs_destroy_object(struct wlan_dfs *dfs)
440 {
441 	qdf_mem_free(dfs->dfs_curchan);
442 	qdf_mem_free(dfs);
443 }
444 
445 int dfs_radar_disable(struct wlan_dfs *dfs)
446 {
447 	dfs->dfs_proc_phyerr &= ~DFS_AR_EN;
448 	dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
449 
450 	return 0;
451 }
452 
453 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs)
454 {
455 	dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
456 
457 	return 0;
458 }
459 
460 void dfs_phyerr_param_copy(struct wlan_dfs_phyerr_param *dst,
461 		struct wlan_dfs_phyerr_param *src)
462 {
463 	memcpy(dst, src, sizeof(*dst));
464 }
465 
466 struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index,
467 		int ext_chan_flag)
468 {
469 	struct dfs_state *rs = NULL;
470 	struct dfs_channel *cmp_ch, cmp_ch1;
471 	int i;
472 	QDF_STATUS err;
473 
474 	if (!dfs) {
475 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
476 		return NULL;
477 	}
478 
479 	cmp_ch = &cmp_ch1;
480 	if (ext_chan_flag) {
481 		err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj,
482 				&(cmp_ch->dfs_ch_freq),
483 				&(cmp_ch->dfs_ch_flags),
484 				&(cmp_ch->dfs_ch_flagext),
485 				&(cmp_ch->dfs_ch_ieee),
486 				&(cmp_ch->dfs_ch_vhtop_ch_freq_seg1),
487 				&(cmp_ch->dfs_ch_vhtop_ch_freq_seg2));
488 
489 		if (err == QDF_STATUS_SUCCESS) {
490 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
491 					"Extension channel freq = %u flags=0x%x",
492 					cmp_ch->dfs_ch_freq,
493 					cmp_ch->dfs_ch_flagext);
494 		} else
495 			return NULL;
496 	} else {
497 		cmp_ch = dfs->dfs_curchan;
498 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
499 				"Primary channel freq = %u flags=0x%x",
500 				cmp_ch->dfs_ch_freq, cmp_ch->dfs_ch_flagext);
501 	}
502 
503 	for (i = 0; i < DFS_NUM_RADAR_STATES; i++) {
504 		if ((dfs->dfs_radar[i].rs_chan.dfs_ch_freq ==
505 					cmp_ch->dfs_ch_freq) &&
506 			(dfs->dfs_radar[i].rs_chan.dfs_ch_flags ==
507 			 cmp_ch->dfs_ch_flags)
508 				) {
509 			if (index != NULL)
510 				*index = (uint8_t)i;
511 			return &(dfs->dfs_radar[i]);
512 		}
513 	}
514 	/* No existing channel found, look for first free channel state entry.*/
515 	for (i = 0; i < DFS_NUM_RADAR_STATES; i++) {
516 		if (dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 0) {
517 			rs = &(dfs->dfs_radar[i]);
518 			/* Found one, set channel info and default thresholds.*/
519 			rs->rs_chan = *cmp_ch;
520 
521 			/* Copy the parameters from the default set. */
522 			dfs_phyerr_param_copy(&rs->rs_param,
523 					&dfs->dfs_defaultparams);
524 
525 			if (index != NULL)
526 				*index = (uint8_t)i;
527 
528 			return rs;
529 		}
530 	}
531 	dfs_debug(dfs, WLAN_DEBUG_DFS2, "No more radar states left.");
532 
533 	return NULL;
534 }
535 
536 void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode)
537 {
538 	int is_ext_ch;
539 	int is_fastclk = 0;
540 	struct dfs_channel *ext_ch, extchan;
541 	QDF_STATUS err = QDF_STATUS_E_FAILURE;
542 
543 	if (!dfs) {
544 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
545 		return;
546 	}
547 
548 	is_ext_ch = WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan);
549 	lmac_dfs_disable(dfs->dfs_pdev_obj, no_cac);
550 
551 	/*
552 	 * In all modes, if the primary is DFS then we have to
553 	 * enable radar detection. In HT80_80, we can have
554 	 * primary non-DFS 80MHz with extension 80MHz DFS.
555 	 */
556 	if ((WLAN_IS_CHAN_DFS(dfs->dfs_curchan) ||
557 			((WLAN_IS_CHAN_11AC_VHT160(dfs->dfs_curchan) ||
558 		  WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) &&
559 		 WLAN_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) ||
560 			(dfs_is_precac_timer_running(dfs))) {
561 		struct dfs_state *rs_pri = NULL, *rs_ext = NULL;
562 		uint8_t index_pri, index_ext;
563 
564 		dfs->dfs_proc_phyerr |= DFS_AR_EN;
565 		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
566 		dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN;
567 
568 		ext_ch = &extchan;
569 		if (is_ext_ch)
570 			err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj,
571 					&(ext_ch->dfs_ch_freq),
572 					&(ext_ch->dfs_ch_flags),
573 					&(ext_ch->dfs_ch_flagext),
574 					&(ext_ch->dfs_ch_ieee),
575 					&(ext_ch->dfs_ch_vhtop_ch_freq_seg1),
576 					&(ext_ch->dfs_ch_vhtop_ch_freq_seg2));
577 
578 
579 		dfs_reset_alldelaylines(dfs);
580 
581 		rs_pri = dfs_getchanstate(dfs, &index_pri, 0);
582 		if (err == QDF_STATUS_SUCCESS) {
583 			rs_ext = dfs_getchanstate(dfs, &index_ext, 1);
584 		}
585 
586 		if (rs_pri != NULL && ((err == QDF_STATUS_E_FAILURE) ||
587 			    (rs_ext != NULL))) {
588 			struct wlan_dfs_phyerr_param pe;
589 
590 			qdf_mem_set(&pe, sizeof(pe), '\0');
591 
592 			if (index_pri != dfs->dfs_curchan_radindex)
593 				dfs_reset_alldelaylines(dfs);
594 
595 			dfs->dfs_curchan_radindex = (int16_t)index_pri;
596 
597 			if (rs_ext)
598 				dfs->dfs_extchan_radindex = (int16_t)index_ext;
599 
600 			dfs_phyerr_param_copy(&pe, &rs_pri->rs_param);
601 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
602 					"firpwr=%d, rssi=%d, height=%d, prssi=%d, inband=%d, relpwr=%d, relstep=%d, maxlen=%d",
603 					 pe.pe_firpwr,
604 					pe.pe_rrssi, pe.pe_height,
605 					pe.pe_prssi, pe.pe_inband,
606 					pe.pe_relpwr, pe.pe_relstep,
607 					pe.pe_maxlen);
608 
609 			lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk,
610 					&pe, dfs->dfsdomain);
611 			dfs_debug(dfs, WLAN_DEBUG_DFS,
612 					"Enabled radar detection on channel %d",
613 					dfs->dfs_curchan->dfs_ch_freq);
614 
615 			dfs->dur_multiplier = is_fastclk ?
616 				DFS_FAST_CLOCK_MULTIPLIER :
617 				DFS_NO_FAST_CLOCK_MULTIPLIER;
618 
619 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
620 					"duration multiplier is %d",
621 					 dfs->dur_multiplier);
622 		} else
623 			dfs_debug(dfs, WLAN_DEBUG_DFS,
624 					"No more radar states left");
625 	}
626 }
627 
628 int dfs_control(struct wlan_dfs *dfs,
629 		u_int id,
630 		void *indata,
631 		uint32_t insize,
632 		void *outdata,
633 		uint32_t *outsize)
634 {
635 	struct wlan_dfs_phyerr_param peout;
636 	struct dfs_ioctl_params *dfsparams;
637 	int error = 0;
638 	uint32_t val = 0;
639 	struct dfsreq_nolinfo *nol;
640 	uint32_t *data = NULL;
641 	int i;
642 	struct dfs_emulate_bang_radar_test_cmd dfs_unit_test;
643 
644 	qdf_mem_zero(&dfs_unit_test, sizeof(dfs_unit_test));
645 
646 	if (!dfs) {
647 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
648 		goto bad;
649 	}
650 
651 	switch (id) {
652 	case DFS_SET_THRESH:
653 		if (insize < sizeof(struct dfs_ioctl_params) || !indata) {
654 			dfs_debug(dfs, WLAN_DEBUG_DFS1,
655 					"insize = %d, expected = %zu bytes, indata = %pK",
656 					insize,
657 					sizeof(struct dfs_ioctl_params),
658 					indata);
659 			error = -EINVAL;
660 			break;
661 		}
662 		dfsparams = (struct dfs_ioctl_params *)indata;
663 		if (!dfs_set_thresholds(dfs, DFS_PARAM_FIRPWR,
664 					dfsparams->dfs_firpwr))
665 			error = -EINVAL;
666 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RRSSI,
667 					dfsparams->dfs_rrssi))
668 			error = -EINVAL;
669 		if (!dfs_set_thresholds(dfs, DFS_PARAM_HEIGHT,
670 					dfsparams->dfs_height))
671 			error = -EINVAL;
672 		if (!dfs_set_thresholds(dfs, DFS_PARAM_PRSSI,
673 					dfsparams->dfs_prssi))
674 			error = -EINVAL;
675 		if (!dfs_set_thresholds(dfs, DFS_PARAM_INBAND,
676 					dfsparams->dfs_inband))
677 			error = -EINVAL;
678 
679 		/* 5413 speicfic. */
680 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RELPWR,
681 					dfsparams->dfs_relpwr))
682 			error = -EINVAL;
683 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RELSTEP,
684 					dfsparams->dfs_relstep))
685 			error = -EINVAL;
686 		if (!dfs_set_thresholds(dfs, DFS_PARAM_MAXLEN,
687 					dfsparams->dfs_maxlen))
688 			error = -EINVAL;
689 		break;
690 	case DFS_GET_THRESH:
691 		if (!outdata || !outsize ||
692 				*outsize < sizeof(struct dfs_ioctl_params)) {
693 			error = -EINVAL;
694 			break;
695 		}
696 		*outsize = sizeof(struct dfs_ioctl_params);
697 		dfsparams = (struct dfs_ioctl_params *) outdata;
698 
699 		/* Fetch the DFS thresholds using the internal representation */
700 		(void) dfs_get_thresholds(dfs, &peout);
701 
702 		/* Convert them to the dfs IOCTL representation. */
703 		wlan_dfs_dfsparam_to_ioctlparam(&peout, dfsparams);
704 		break;
705 	case DFS_RADARDETECTS:
706 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
707 			error = -EINVAL;
708 			break;
709 		}
710 		*outsize = sizeof(uint32_t);
711 		*((uint32_t *)outdata) = dfs->wlan_dfs_stats.num_radar_detects;
712 		break;
713 	case DFS_DISABLE_DETECT:
714 		dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
715 		dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
716 		dfs->dfs_ignore_dfs = 1;
717 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
718 				"enable detects, ignore_dfs %d",
719 				dfs->dfs_ignore_dfs ? 1:0);
720 		break;
721 	case DFS_ENABLE_DETECT:
722 		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
723 		dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN;
724 		dfs->dfs_ignore_dfs = 0;
725 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS
726 				, "enable detects, ignore_dfs %d",
727 				dfs->dfs_ignore_dfs ? 1:0);
728 		break;
729 	case DFS_DISABLE_FFT:
730 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
731 				"TODO disable FFT val=0x%x", val);
732 		break;
733 	case DFS_ENABLE_FFT:
734 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
735 				"TODO enable FFT val=0x%x", val);
736 		break;
737 	case DFS_SET_DEBUG_LEVEL:
738 		if (insize < sizeof(uint32_t) || !indata) {
739 			error = -EINVAL;
740 			break;
741 		}
742 		dfs->dfs_debug_mask = *(uint32_t *)indata;
743 
744 		/* Do not allow user to set the ALWAYS/MAX bit.
745 		 * It will be used internally  by dfs print macro(s)
746 		 * to print messages when dfs is NULL.
747 		 */
748 		dfs->dfs_debug_mask &= ~(WLAN_DEBUG_DFS_ALWAYS);
749 
750 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
751 				"debug level now = 0x%x", dfs->dfs_debug_mask);
752 		if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS3) {
753 			/* Enable debug Radar Event */
754 			dfs->dfs_event_log_on = 1;
755 		} else {
756 			dfs->dfs_event_log_on = 0;
757 		}
758 		break;
759 	case DFS_SET_FALSE_RSSI_THRES:
760 		if (insize < sizeof(uint32_t) || !indata) {
761 			error = -EINVAL;
762 			break;
763 		}
764 		dfs->wlan_dfs_false_rssi_thres = *(uint32_t *)indata;
765 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
766 				"false RSSI threshold now = 0x%x",
767 				dfs->wlan_dfs_false_rssi_thres);
768 		break;
769 	case DFS_SET_PEAK_MAG:
770 		if (insize < sizeof(uint32_t) || !indata) {
771 			error = -EINVAL;
772 			break;
773 		}
774 		dfs->wlan_dfs_peak_mag = *(uint32_t *)indata;
775 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
776 				"peak_mag now = 0x%x",
777 				dfs->wlan_dfs_peak_mag);
778 		break;
779 	case DFS_GET_CAC_VALID_TIME:
780 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
781 			error = -EINVAL;
782 			break;
783 		}
784 		*outsize = sizeof(uint32_t);
785 		*((uint32_t *)outdata) = dfs->dfs_cac_valid_time;
786 		break;
787 	case DFS_SET_CAC_VALID_TIME:
788 		if (insize < sizeof(uint32_t) || !indata) {
789 			error = -EINVAL;
790 			break;
791 		}
792 		dfs->dfs_cac_valid_time = *(uint32_t *)indata;
793 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
794 				"dfs timeout = %d", dfs->dfs_cac_valid_time);
795 		break;
796 	case DFS_IGNORE_CAC:
797 		if (insize < sizeof(uint32_t) || !indata) {
798 			error = -EINVAL;
799 			break;
800 		}
801 
802 		if (*(uint32_t *)indata)
803 			dfs->dfs_ignore_cac = 1;
804 		else
805 			dfs->dfs_ignore_cac = 0;
806 
807 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
808 				"ignore cac = 0x%x", dfs->dfs_ignore_cac);
809 		break;
810 	case DFS_SET_NOL_TIMEOUT:
811 		if (insize < sizeof(uint32_t) || !indata) {
812 			error = -EINVAL;
813 			break;
814 		}
815 		if (*(int *)indata)
816 			dfs->wlan_dfs_nol_timeout = *(int *)indata;
817 		else
818 			dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S;
819 
820 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol timeout = %d sec",
821 				dfs->wlan_dfs_nol_timeout);
822 		break;
823 	case DFS_MUTE_TIME:
824 		if (insize < sizeof(uint32_t) || !indata) {
825 			error = -EINVAL;
826 			break;
827 		}
828 		data = (uint32_t *) indata;
829 		dfs->wlan_dfstesttime = *data;
830 		dfs->wlan_dfstesttime *= (1000); /* convert sec into ms */
831 		break;
832 	case DFS_GET_USENOL:
833 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
834 			error = -EINVAL;
835 			break;
836 		}
837 		*outsize = sizeof(uint32_t);
838 		*((uint32_t *)outdata) = dfs->dfs_use_nol;
839 
840 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
841 				"#Phyerr=%d, #false detect=%d, #queued=%d",
842 				 dfs->dfs_phyerr_count,
843 				dfs->dfs_phyerr_reject_count,
844 				dfs->dfs_phyerr_queued_count);
845 
846 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
847 				"dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d",
848 				 dfs->dfs_phyerr_freq_min,
849 				dfs->dfs_phyerr_freq_max);
850 
851 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
852 				"Total radar events detected=%d, entries in the radar queue follows:",
853 				 dfs->dfs_event_log_count);
854 
855 		for (i = 0; (i < DFS_EVENT_LOG_SIZE) &&
856 				(i < dfs->dfs_event_log_count); i++) {
857 #define FREQ_OFFSET1 ((int)dfs->radar_log[i].freq_offset_khz / 1000)
858 #define FREQ_OFFSET2 ((int)abs(dfs->radar_log[i].freq_offset_khz) % 1000)
859 			dfs_debug(dfs, WLAN_DEBUG_DFS,
860 					"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\n",
861 					dfs->radar_log[i].ts,
862 					dfs->radar_log[i].diff_ts,
863 					dfs->radar_log[i].rssi,
864 					dfs->radar_log[i].dur,
865 					dfs->radar_log[i].is_chirp,
866 					dfs->radar_log[i].seg_id,
867 					dfs->radar_log[i].sidx,
868 					FREQ_OFFSET1,
869 					FREQ_OFFSET2,
870 					dfs->radar_log[i].peak_mag,
871 					dfs->radar_log[i].total_gain,
872 					dfs->radar_log[i].mb_gain,
873 					dfs->radar_log[i].relpwr_db,
874 					dfs->radar_log[i].delta_diff,
875 					dfs->radar_log[i].delta_peak);
876 		}
877 		dfs->dfs_event_log_count = 0;
878 		dfs->dfs_phyerr_count = 0;
879 		dfs->dfs_phyerr_reject_count = 0;
880 		dfs->dfs_phyerr_queued_count = 0;
881 		dfs->dfs_phyerr_freq_min = 0x7fffffff;
882 		dfs->dfs_phyerr_freq_max = 0;
883 		break;
884 	case DFS_SET_USENOL:
885 		if (insize < sizeof(uint32_t) || !indata) {
886 			error = -EINVAL;
887 			break;
888 		}
889 		dfs->dfs_use_nol = *(uint32_t *)indata;
890 		break;
891 	case DFS_GET_NOL:
892 		if (!outdata || !outsize ||
893 				*outsize < sizeof(struct dfsreq_nolinfo)) {
894 			error = -EINVAL;
895 			break;
896 		}
897 		*outsize = sizeof(struct dfsreq_nolinfo);
898 		nol = (struct dfsreq_nolinfo *)outdata;
899 		DFS_GET_NOL_LOCKED(dfs,
900 				(struct dfsreq_nolelem *)nol->dfs_nol,
901 				&nol->dfs_ch_nchans);
902 		DFS_PRINT_NOL_LOCKED(dfs);
903 		break;
904 	case DFS_SET_NOL:
905 		if (insize < sizeof(struct dfsreq_nolinfo) || !indata) {
906 			error = -EINVAL;
907 			break;
908 		}
909 		nol = (struct dfsreq_nolinfo *) indata;
910 		dfs_set_nol(dfs,
911 				(struct dfsreq_nolelem *)nol->dfs_nol,
912 				nol->dfs_ch_nchans);
913 		break;
914 	case DFS_SHOW_NOL:
915 		DFS_PRINT_NOL_LOCKED(dfs);
916 		break;
917 	case DFS_SHOW_NOLHISTORY:
918 		dfs_print_nolhistory(dfs);
919 		break;
920 	case DFS_BANGRADAR:
921 		if (dfs->dfs_is_offload_enabled) {
922 			error = dfs_fill_emulate_bang_radar_test(dfs,
923 					SEG_ID_PRIMARY,
924 					&dfs_unit_test);
925 		} else {
926 			dfs->dfs_bangradar = 1;
927 			dfs->wlan_radar_tasksched = 1;
928 			qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0);
929 			error = 0;
930 		}
931 		break;
932 	case DFS_SHOW_PRECAC_LISTS:
933 		dfs_print_precaclists(dfs);
934 		break;
935 	case DFS_RESET_PRECAC_LISTS:
936 		dfs_reset_precac_lists(dfs);
937 		break;
938 	case DFS_SECOND_SEGMENT_BANGRADAR:
939 		if (dfs->dfs_is_offload_enabled) {
940 			error = dfs_fill_emulate_bang_radar_test(dfs,
941 					SEG_ID_SECONDARY,
942 					&dfs_unit_test);
943 		} else {
944 			dfs->dfs_second_segment_bangradar = 1;
945 			dfs->wlan_radar_tasksched = 1;
946 			qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0);
947 			error = 0;
948 		}
949 		break;
950 	default:
951 		error = -EINVAL;
952 	}
953 
954 bad:
955 	return error;
956 }
957 
958 int dfs_set_thresholds(struct wlan_dfs *dfs, const uint32_t threshtype,
959 		const uint32_t value)
960 {
961 	int16_t chanindex;
962 	struct dfs_state *rs;
963 	struct wlan_dfs_phyerr_param pe;
964 	int is_fastclk = 0;
965 
966 	if (!dfs) {
967 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
968 		return 0;
969 	}
970 
971 	chanindex = dfs->dfs_curchan_radindex;
972 	if ((chanindex < 0) || (chanindex >= DFS_NUM_RADAR_STATES)) {
973 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
974 				"chanindex = %d, DFS_NUM_RADAR_STATES=%d",
975 				 chanindex, DFS_NUM_RADAR_STATES);
976 		return 0;
977 	}
978 
979 	dfs_debug(dfs, WLAN_DEBUG_DFS,
980 			"threshtype=%d, value=%d", threshtype, value);
981 
982 	wlan_dfs_phyerr_init_noval(&pe);
983 
984 	rs = &(dfs->dfs_radar[chanindex]);
985 	switch (threshtype) {
986 	case DFS_PARAM_FIRPWR:
987 		rs->rs_param.pe_firpwr = (int32_t) value;
988 		pe.pe_firpwr = value;
989 		break;
990 	case DFS_PARAM_RRSSI:
991 		rs->rs_param.pe_rrssi = value;
992 		pe.pe_rrssi = value;
993 		break;
994 	case DFS_PARAM_HEIGHT:
995 		rs->rs_param.pe_height = value;
996 		pe.pe_height = value;
997 		break;
998 	case DFS_PARAM_PRSSI:
999 		rs->rs_param.pe_prssi = value;
1000 		pe.pe_prssi = value;
1001 		break;
1002 	case DFS_PARAM_INBAND:
1003 		rs->rs_param.pe_inband = value;
1004 		pe.pe_inband = value;
1005 		break;
1006 		/* 5413 specific */
1007 	case DFS_PARAM_RELPWR:
1008 		rs->rs_param.pe_relpwr = value;
1009 		pe.pe_relpwr = value;
1010 		break;
1011 	case DFS_PARAM_RELSTEP:
1012 		rs->rs_param.pe_relstep = value;
1013 		pe.pe_relstep = value;
1014 		break;
1015 	case DFS_PARAM_MAXLEN:
1016 		rs->rs_param.pe_maxlen = value;
1017 		pe.pe_maxlen = value;
1018 		break;
1019 	default:
1020 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
1021 				"unknown threshtype (%d)", threshtype);
1022 		break;
1023 	}
1024 
1025 	/*
1026 	 * The driver layer dfs_enable routine is tasked with translating
1027 	 * values from the global format to the per-device (HAL, offload)
1028 	 * format.
1029 	 */
1030 	lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk,
1031 			&pe, dfs->dfsdomain);
1032 
1033 	return 1;
1034 }
1035 
1036 int dfs_get_thresholds(struct wlan_dfs *dfs,
1037 		struct wlan_dfs_phyerr_param *param)
1038 {
1039 	qdf_mem_zero(param, sizeof(*param));
1040 
1041 	lmac_dfs_get_thresholds(dfs->dfs_pdev_obj, param);
1042 
1043 	return 1;
1044 }
1045 
1046 void dfs_set_current_channel(struct wlan_dfs *dfs,
1047 		uint16_t dfs_ch_freq,
1048 		uint64_t dfs_ch_flags,
1049 		uint16_t dfs_ch_flagext,
1050 		uint8_t dfs_ch_ieee,
1051 		uint8_t dfs_ch_vhtop_ch_freq_seg1,
1052 		uint8_t dfs_ch_vhtop_ch_freq_seg2)
1053 {
1054 	if (!dfs) {
1055 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
1056 		return;
1057 	}
1058 
1059 	dfs->dfs_curchan->dfs_ch_freq = dfs_ch_freq;
1060 	dfs->dfs_curchan->dfs_ch_flags = dfs_ch_flags;
1061 	dfs->dfs_curchan->dfs_ch_flagext = dfs_ch_flagext;
1062 	dfs->dfs_curchan->dfs_ch_ieee = dfs_ch_ieee;
1063 	dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 = dfs_ch_vhtop_ch_freq_seg1;
1064 	dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 = dfs_ch_vhtop_ch_freq_seg2;
1065 }
1066 
1067 uint16_t dfs_chan2freq(struct dfs_channel *chan)
1068 {
1069 	if (!chan)
1070 		return 0;
1071 
1072 	return chan == WLAN_CHAN_ANYC ?
1073 		WLAN_CHAN_ANY : chan->dfs_ch_freq;
1074 }
1075 
1076 void dfs_update_cur_chan_flags(struct wlan_dfs *dfs,
1077 		uint64_t flags,
1078 		uint16_t flagext)
1079 {
1080 	dfs->dfs_curchan->dfs_ch_flags = flags;
1081 	dfs->dfs_curchan->dfs_ch_flagext = flagext;
1082 }
1083 
1084 #ifdef QCA_MCL_DFS_SUPPORT
1085 void dfs_set_phyerr_filter_offload(struct wlan_dfs *dfs)
1086 {
1087 	tgt_dfs_set_phyerr_filter_offload(dfs->dfs_pdev_obj);
1088 }
1089 #else
1090 void dfs_set_phyerr_filter_offload(struct wlan_dfs *dfs)
1091 {
1092 }
1093 #endif
1094