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