xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_filter_init.c (revision dae10a5fbc53d54c53c4ba24fa018ad8b1e7c008)
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_partial_offload_radar.h"
32 
33 #ifndef WLAN_DFS_STATIC_MEM_ALLOC
34 /*
35  * dfs_alloc_dfs_events() - allocate dfs events buffer
36  *
37  * Return: events buffer, null on failure.
38  */
39 static inline struct dfs_event *dfs_alloc_dfs_events(void)
40 {
41 	return qdf_mem_malloc(sizeof(struct dfs_event) * DFS_MAX_EVENTS);
42 }
43 
44 /*
45  * dfs_free_dfs_events() - Free events buffer
46  * @events: Events buffer pointer
47  *
48  * Return: None
49  */
50 static inline void dfs_free_dfs_events(struct dfs_event *events)
51 {
52 	qdf_mem_free(events);
53 }
54 
55 /*
56  * dfs_alloc_dfs_pulseline() - allocate buffer for dfs pulses
57  *
58  * Return: events buffer, null on failure.
59  */
60 static inline struct dfs_pulseline *dfs_alloc_dfs_pulseline(void)
61 {
62 	return qdf_mem_malloc(sizeof(struct dfs_pulseline));
63 }
64 
65 /*
66  * dfs_free_dfs_pulseline() - Free pulse buffer
67  * @pulses: Pulses buffer pointer
68  *
69  * Return: None
70  */
71 static inline void dfs_free_dfs_pulseline(struct dfs_pulseline *pulses)
72 {
73 	qdf_mem_free(pulses);
74 }
75 #else
76 /* Static buffers for DFS objects */
77 static struct dfs_event global_dfs_event[DFS_MAX_EVENTS];
78 static struct dfs_pulseline global_dfs_pulseline;
79 
80 static inline struct dfs_event *dfs_alloc_dfs_events(void)
81 {
82 	return global_dfs_event;
83 }
84 
85 static inline void dfs_free_dfs_events(struct dfs_event *events)
86 {
87 }
88 
89 static inline struct dfs_pulseline *dfs_alloc_dfs_pulseline(void)
90 {
91 	return &global_dfs_pulseline;
92 }
93 
94 static inline void dfs_free_dfs_pulseline(struct dfs_pulseline *pulses)
95 {
96 }
97 #endif
98 
99 /*
100  * Channel switch announcement (CSA)
101  * usenol=1 (default) make CSA and switch to a new channel on radar detect
102  * usenol=0, make CSA with next channel same as current on radar detect
103  * usenol=2, no CSA and stay on the same channel on radar detect
104  */
105 
106 /**
107  * dfs_task() - The timer function to process the radar pulses.
108  */
109 static os_timer_func(dfs_task)
110 {
111 	struct wlan_dfs *dfs = NULL;
112 
113 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
114 
115 	if (!dfs) {
116 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
117 		return;
118 	}
119 
120 	dfs_process_radarevent(dfs, dfs->dfs_curchan);
121 
122 	dfs->wlan_radar_tasksched = 0;
123 }
124 
125 /**
126  * dfs_main_task_timer_init() - Initialize dfs task timer.
127  * @dfs: Pointer to wlan_dfs structure.
128  */
129 static void dfs_main_task_timer_init(struct wlan_dfs *dfs)
130 {
131 	qdf_timer_init(NULL,
132 			&(dfs->wlan_dfs_task_timer),
133 			dfs_task,
134 			(void *)(dfs),
135 			QDF_TIMER_TYPE_WAKE_APPS);
136 }
137 
138 /**
139  * dfs_free_filter() - free memory allocated for dfs ft_filters
140  * @radarf: pointer holding ft_filters.
141  *
142  * Return: None
143  */
144 static void dfs_free_filter(struct dfs_filtertype *radarf)
145 {
146 	uint8_t i;
147 
148 	for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) {
149 		if (radarf->ft_filters[i]) {
150 			qdf_mem_free(radarf->ft_filters[i]);
151 			radarf->ft_filters[i] = NULL;
152 		}
153 	}
154 }
155 
156 /**
157  * dfs_alloc_mem_filter() - allocate memory for dfs ft_filters
158  * @radarf: pointer holding ft_filters.
159  *
160  * Return: QDF_STATUS
161  */
162 static QDF_STATUS dfs_alloc_mem_filter(struct dfs_filtertype *radarf)
163 {
164 	uint8_t i;
165 
166 	for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) {
167 		radarf->ft_filters[i] = qdf_mem_malloc(sizeof(struct
168 							      dfs_filter));
169 		if (!radarf->ft_filters[i]) {
170 			/* Free all the filter if malloc failed */
171 			dfs_free_filter(radarf);
172 			return QDF_STATUS_E_FAILURE;
173 		}
174 	}
175 
176 	return QDF_STATUS_SUCCESS;
177 }
178 
179 int dfs_main_attach(struct wlan_dfs *dfs)
180 {
181 	int i, n;
182 	QDF_STATUS status;
183 	struct wlan_dfs_radar_tab_info radar_info;
184 
185 	if (!dfs) {
186 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
187 		return 0;
188 	}
189 
190 	/* If ignore_dfs is set to 1 then Radar detection is disabled. */
191 	if (dfs->dfs_ignore_dfs) {
192 		dfs_debug(dfs, WLAN_DEBUG_DFS1, "ignoring dfs");
193 		return 0;
194 	}
195 
196 	/*
197 	 * Zero out radar_info. It's possible that the attach function
198 	 * won't fetch an initial regulatory configuration; you really
199 	 * do want to ensure that the contents indicates there aren't
200 	 * any filters.
201 	 */
202 	qdf_mem_zero(&radar_info, sizeof(radar_info));
203 
204 	lmac_get_caps(dfs->dfs_pdev_obj, &(dfs->dfs_caps));
205 
206 	dfs_clear_stats(dfs);
207 	dfs->dfs_event_log_on = 1;
208 	dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "event log enabled by default");
209 
210 	dfs->dfs_enable = 1;
211 
212 	/*Verify : Passing NULL to qdf_timer_init().*/
213 	dfs_main_task_timer_init(dfs);
214 
215 	dfs_host_wait_timer_init(dfs);
216 
217 	WLAN_DFSQ_LOCK_CREATE(dfs);
218 	STAILQ_INIT(&dfs->dfs_radarq);
219 	WLAN_ARQ_LOCK_CREATE(dfs);
220 	STAILQ_INIT(&dfs->dfs_arq);
221 	STAILQ_INIT(&(dfs->dfs_eventq));
222 	WLAN_DFSEVENTQ_LOCK_CREATE(dfs);
223 
224 	dfs->events = dfs_alloc_dfs_events();
225 	if (!(dfs->events)) {
226 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
227 			  "events allocation failed");
228 		return 1;
229 	}
230 
231 	for (i = 0; i < DFS_MAX_EVENTS; i++)
232 		STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i],
233 				re_list);
234 
235 	dfs->pulses = dfs_alloc_dfs_pulseline();
236 	if (!(dfs->pulses)) {
237 		dfs_free_dfs_events(dfs->events);
238 		dfs->events = NULL;
239 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
240 			  "Pulse buffer allocation failed");
241 		return 1;
242 	}
243 
244 	dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK;
245 
246 	/* Allocate memory for radar filters. */
247 	for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) {
248 		dfs->dfs_radarf[n] = (struct dfs_filtertype *)
249 			qdf_mem_malloc(sizeof(struct dfs_filtertype));
250 		if (!(dfs->dfs_radarf[n])) {
251 			dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
252 					"cannot allocate memory for radar filter types");
253 			goto bad1;
254 		}
255 		qdf_mem_zero(dfs->dfs_radarf[n],
256 			     sizeof(struct dfs_filtertype));
257 		status = dfs_alloc_mem_filter(dfs->dfs_radarf[n]);
258 		if (!QDF_IS_STATUS_SUCCESS(status)) {
259 			dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
260 				  "mem alloc for dfs_filter failed");
261 			goto bad1;
262 		}
263 	}
264 
265 	/* Allocate memory for radar table. */
266 	dfs->dfs_ftindextable = (int8_t **)qdf_mem_malloc(
267 			DFS_NUM_FT_IDX_TBL_ROWS*sizeof(int8_t *));
268 	if (!(dfs->dfs_ftindextable)) {
269 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Cannot allocate memory for radar table");
270 		goto bad1;
271 	}
272 	for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) {
273 		dfs->dfs_ftindextable[n] = qdf_mem_malloc(
274 				DFS_MAX_RADAR_OVERLAP*sizeof(int8_t));
275 		if (!(dfs->dfs_ftindextable[n])) {
276 			dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
277 					"cannot allocate memory for radar table entry");
278 			goto bad2;
279 		}
280 	}
281 
282 	dfs->dfs_use_nol = 1;
283 
284 	/* Init the cached extension channel busy for false alarm reduction */
285 	dfs->dfs_rinfo.ext_chan_busy_ts = lmac_get_tsf64(dfs->dfs_pdev_obj);
286 	dfs->dfs_rinfo.dfs_ext_chan_busy = 0;
287 	/* Init the Bin5 chirping related data */
288 	dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts;
289 	dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR;
290 	dfs->dfs_b5radars = NULL;
291 
292 	/*
293 	 * If dfs_init_radar_filters() fails, we can abort here and
294 	 * reconfigure when the first valid channel + radar config
295 	 * is available.
296 	 */
297 	if (dfs_init_radar_filters(dfs, &radar_info)) {
298 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Radar Filter Intialization Failed");
299 		return 1;
300 	}
301 
302 	dfs->wlan_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE;
303 	dfs->wlan_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH;
304 	dfs->dfs_phyerr_freq_min     = 0x7fffffff;
305 	dfs->dfs_phyerr_freq_max     = 0;
306 	dfs->dfs_phyerr_queued_count = 0;
307 	dfs->dfs_phyerr_w53_counter  = 0;
308 	dfs->dfs_pri_multiplier      = 2;
309 	dfs_get_radars(dfs);
310 
311 	return 0;
312 
313 bad2:
314 	qdf_mem_free(dfs->dfs_ftindextable);
315 	dfs->dfs_ftindextable = NULL;
316 bad1:
317 	for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) {
318 		if (dfs->dfs_radarf[n] != NULL) {
319 			dfs_free_filter(dfs->dfs_radarf[n]);
320 			qdf_mem_free(dfs->dfs_radarf[n]);
321 			dfs->dfs_radarf[n] = NULL;
322 		}
323 	}
324 	if (dfs->pulses) {
325 		dfs_free_dfs_pulseline(dfs->pulses);
326 		dfs->pulses = NULL;
327 	}
328 	if (dfs->events) {
329 		dfs_free_dfs_events(dfs->events);
330 		dfs->events = NULL;
331 	}
332 
333 	return 1;
334 }
335 
336 void dfs_main_timer_reset(struct wlan_dfs *dfs)
337 {
338 	if (dfs->wlan_radar_tasksched) {
339 		qdf_timer_sync_cancel(&dfs->wlan_dfs_task_timer);
340 		dfs->wlan_radar_tasksched = 0;
341 	}
342 }
343 
344 void dfs_main_timer_detach(struct wlan_dfs *dfs)
345 {
346 	qdf_timer_free(&dfs->wlan_dfs_task_timer);
347 	dfs->wlan_radar_tasksched = 0;
348 }
349 
350 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST)
351 void dfs_host_wait_timer_detach(struct wlan_dfs *dfs)
352 {
353 	qdf_timer_free(&dfs->dfs_host_wait_timer);
354 }
355 #endif
356 
357 void dfs_main_detach(struct wlan_dfs *dfs)
358 {
359 	int n, empty;
360 
361 	if (!dfs->dfs_enable) {
362 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "Already detached");
363 		return;
364 	}
365 
366 	dfs->dfs_enable = 0;
367 
368 	dfs_reset_radarq(dfs);
369 	dfs_reset_alldelaylines(dfs);
370 
371 	if (dfs->pulses != NULL) {
372 		dfs_free_dfs_pulseline(dfs->pulses);
373 		dfs->pulses = NULL;
374 	}
375 
376 	for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) {
377 		if (dfs->dfs_radarf[n] != NULL) {
378 			dfs_free_filter(dfs->dfs_radarf[n]);
379 			qdf_mem_free(dfs->dfs_radarf[n]);
380 			dfs->dfs_radarf[n] = NULL;
381 		}
382 	}
383 
384 	if (dfs->dfs_ftindextable != NULL) {
385 		for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) {
386 			if (dfs->dfs_ftindextable[n] != NULL) {
387 				qdf_mem_free(dfs->dfs_ftindextable[n]);
388 				dfs->dfs_ftindextable[n] = NULL;
389 			}
390 		}
391 		qdf_mem_free(dfs->dfs_ftindextable);
392 		dfs->dfs_ftindextable = NULL;
393 		dfs->wlan_dfs_isdfsregdomain = 0;
394 	}
395 
396 	if (dfs->dfs_b5radars != NULL) {
397 		qdf_mem_free(dfs->dfs_b5radars);
398 		dfs->dfs_b5radars = NULL;
399 	}
400 
401 	dfs_reset_ar(dfs);
402 
403 	WLAN_ARQ_LOCK(dfs);
404 	empty = STAILQ_EMPTY(&(dfs->dfs_arq));
405 	WLAN_ARQ_UNLOCK(dfs);
406 	if (!empty)
407 		dfs_reset_arq(dfs);
408 
409 	if (dfs->events != NULL) {
410 		dfs_free_dfs_events(dfs->events);
411 		dfs->events = NULL;
412 	}
413 
414 	WLAN_DFSQ_LOCK_DESTROY(dfs);
415 	WLAN_ARQ_LOCK_DESTROY(dfs);
416 	WLAN_DFSEVENTQ_LOCK_DESTROY(dfs);
417 }
418 
419 int dfs_start_host_based_bangradar(struct wlan_dfs *dfs)
420 {
421 	dfs->wlan_radar_tasksched = 1;
422 	qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0);
423 
424 	return 0;
425 }
426