xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs_filter_init.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
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 
32 /*
33  * Channel switch announcement (CSA)
34  * usenol=1 (default) make CSA and switch to a new channel on radar detect
35  * usenol=0, make CSA with next channel same as current on radar detect
36  * usenol=2, no CSA and stay on the same channel on radar detect
37  */
38 
39 /**
40  * dfs_task() - The timer function to process the radar pulses.
41  */
42 static os_timer_func(dfs_task)
43 {
44 	struct wlan_dfs *dfs = NULL;
45 
46 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
47 
48 	if (!dfs) {
49 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
50 		return;
51 	}
52 
53 	dfs_process_radarevent(dfs, dfs->dfs_curchan);
54 
55 	dfs->wlan_radar_tasksched = 0;
56 }
57 
58 /**
59  * dfs_main_task_timer_init() - Initialize dfs task timer.
60  * @dfs: Pointer to wlan_dfs structure.
61  */
62 static void dfs_main_task_timer_init(struct wlan_dfs *dfs)
63 {
64 	qdf_timer_init(NULL,
65 			&(dfs->wlan_dfs_task_timer),
66 			dfs_task,
67 			(void *)(dfs),
68 			QDF_TIMER_TYPE_WAKE_APPS);
69 }
70 
71 int dfs_main_attach(struct wlan_dfs *dfs)
72 {
73 	int i, n;
74 	struct wlan_dfs_radar_tab_info radar_info;
75 
76 	if (!dfs) {
77 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
78 		return 0;
79 	}
80 
81 	/* If ignore_dfs is set to 1 then Radar detection is disabled. */
82 	if (dfs->dfs_ignore_dfs) {
83 		dfs_debug(dfs, WLAN_DEBUG_DFS1, "ignoring dfs");
84 		return 0;
85 	}
86 
87 	/*
88 	 * Zero out radar_info. It's possible that the attach function
89 	 * won't fetch an initial regulatory configuration; you really
90 	 * do want to ensure that the contents indicates there aren't
91 	 * any filters.
92 	 */
93 	qdf_mem_zero(&radar_info, sizeof(radar_info));
94 
95 	lmac_get_caps(dfs->dfs_pdev_obj, &(dfs->dfs_caps));
96 
97 	dfs_clear_stats(dfs);
98 	dfs->dfs_event_log_on = 1;
99 	dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "event log enabled by default");
100 
101 	dfs->dfs_enable = 1;
102 
103 	/*Verify : Passing NULL to qdf_timer_init().*/
104 	dfs_main_task_timer_init(dfs);
105 
106 	WLAN_DFSQ_LOCK_CREATE(dfs);
107 	STAILQ_INIT(&dfs->dfs_radarq);
108 	WLAN_ARQ_LOCK_CREATE(dfs);
109 	STAILQ_INIT(&dfs->dfs_arq);
110 	STAILQ_INIT(&(dfs->dfs_eventq));
111 	WLAN_DFSEVENTQ_LOCK_CREATE(dfs);
112 
113 	dfs->events = (struct dfs_event *)qdf_mem_malloc(
114 			sizeof(struct dfs_event)*DFS_MAX_EVENTS);
115 	if (!(dfs->events)) {
116 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "events allocation failed");
117 		return 1;
118 	}
119 	for (i = 0; i < DFS_MAX_EVENTS; i++)
120 		STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i],
121 				re_list);
122 
123 	dfs->pulses = (struct dfs_pulseline *)qdf_mem_malloc(
124 			sizeof(struct dfs_pulseline));
125 	if (!(dfs->pulses)) {
126 		qdf_mem_free(dfs->events);
127 		dfs->events = NULL;
128 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Pulse buffer allocation failed");
129 		return 1;
130 	}
131 
132 	dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK;
133 
134 	/* Allocate memory for radar filters. */
135 	for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) {
136 		dfs->dfs_radarf[n] = (struct dfs_filtertype *)
137 			qdf_mem_malloc(sizeof(struct dfs_filtertype));
138 		if (!(dfs->dfs_radarf[n])) {
139 			dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
140 					"cannot allocate memory for radar filter types");
141 			goto bad1;
142 		}
143 		qdf_mem_zero(dfs->dfs_radarf[n], sizeof(struct dfs_filtertype));
144 	}
145 
146 	/* Allocate memory for radar table. */
147 	dfs->dfs_ftindextable = (int8_t **)qdf_mem_malloc(
148 			DFS_NUM_FT_IDX_TBL_ROWS*sizeof(int8_t *));
149 	if (!(dfs->dfs_ftindextable)) {
150 		dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Cannot allocate memory for radar table");
151 		goto bad1;
152 	}
153 	for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) {
154 		dfs->dfs_ftindextable[n] = qdf_mem_malloc(
155 				DFS_MAX_RADAR_OVERLAP*sizeof(int8_t));
156 		if (!(dfs->dfs_ftindextable[n])) {
157 			dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
158 					"cannot allocate memory for radar table entry");
159 			goto bad2;
160 		}
161 	}
162 
163 	dfs->dfs_use_nol = 1;
164 
165 	/* Init the cached extension channel busy for false alarm reduction */
166 	dfs->dfs_rinfo.ext_chan_busy_ts = lmac_get_tsf64(dfs->dfs_pdev_obj);
167 	dfs->dfs_rinfo.dfs_ext_chan_busy = 0;
168 	/* Init the Bin5 chirping related data */
169 	dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts;
170 	dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR;
171 	dfs->dfs_b5radars = NULL;
172 
173 	/*
174 	 * If dfs_init_radar_filters() fails, we can abort here and
175 	 * reconfigure when the first valid channel + radar config
176 	 * is available.
177 	 */
178 	if (dfs_init_radar_filters(dfs, &radar_info)) {
179 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Radar Filter Intialization Failed");
180 		return 1;
181 	}
182 
183 	dfs->wlan_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE;
184 	dfs->wlan_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH;
185 	dfs->dfs_phyerr_freq_min     = 0x7fffffff;
186 	dfs->dfs_phyerr_freq_max     = 0;
187 	dfs->dfs_phyerr_queued_count = 0;
188 	dfs->dfs_phyerr_w53_counter  = 0;
189 	dfs->dfs_pri_multiplier      = 2;
190 	dfs_get_radars(dfs);
191 
192 	return 0;
193 
194 bad2:
195 	qdf_mem_free(dfs->dfs_ftindextable);
196 	dfs->dfs_ftindextable = NULL;
197 bad1:
198 	for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) {
199 		if (dfs->dfs_radarf[n] != NULL) {
200 			qdf_mem_free(dfs->dfs_radarf[n]);
201 			dfs->dfs_radarf[n] = NULL;
202 		}
203 	}
204 	if (dfs->pulses) {
205 		qdf_mem_free(dfs->pulses);
206 		dfs->pulses = NULL;
207 	}
208 	if (dfs->events) {
209 		qdf_mem_free(dfs->events);
210 		dfs->events = NULL;
211 	}
212 
213 	return 1;
214 }
215 
216 void dfs_main_timer_reset(struct wlan_dfs *dfs)
217 {
218 	if (dfs->wlan_radar_tasksched) {
219 		qdf_timer_stop(&dfs->wlan_dfs_task_timer);
220 		dfs->wlan_radar_tasksched = 0;
221 	}
222 
223 	if (dfs->wlan_dfstest) {
224 		qdf_timer_stop(&dfs->wlan_dfstesttimer);
225 		dfs->wlan_dfstest = 0;
226 	}
227 }
228 
229 void dfs_main_detach(struct wlan_dfs *dfs)
230 {
231 	int n, empty;
232 
233 	if (!dfs->dfs_enable) {
234 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "Already detached");
235 		return;
236 	}
237 
238 	dfs->dfs_enable = 0;
239 
240 	if (dfs->dfs_curchan != NULL) {
241 		qdf_mem_free(dfs->dfs_curchan);
242 		dfs->dfs_curchan = NULL;
243 	}
244 
245 	dfs_reset_radarq(dfs);
246 	dfs_reset_alldelaylines(dfs);
247 
248 	if (dfs->pulses != NULL) {
249 		qdf_mem_free(dfs->pulses);
250 		dfs->pulses = NULL;
251 	}
252 
253 	for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) {
254 		if (dfs->dfs_radarf[n] != NULL) {
255 			qdf_mem_free(dfs->dfs_radarf[n]);
256 			dfs->dfs_radarf[n] = NULL;
257 		}
258 	}
259 
260 	if (dfs->dfs_ftindextable != NULL) {
261 		for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) {
262 			if (dfs->dfs_ftindextable[n] != NULL) {
263 				qdf_mem_free(dfs->dfs_ftindextable[n]);
264 				dfs->dfs_ftindextable[n] = NULL;
265 			}
266 		}
267 		qdf_mem_free(dfs->dfs_ftindextable);
268 		dfs->dfs_ftindextable = NULL;
269 		dfs->wlan_dfs_isdfsregdomain = 0;
270 	}
271 
272 	if (dfs->dfs_b5radars != NULL) {
273 		qdf_mem_free(dfs->dfs_b5radars);
274 		dfs->dfs_b5radars = NULL;
275 	}
276 
277 	dfs_reset_ar(dfs);
278 
279 	WLAN_ARQ_LOCK(dfs);
280 	empty = STAILQ_EMPTY(&(dfs->dfs_arq));
281 	WLAN_ARQ_UNLOCK(dfs);
282 	if (!empty)
283 		dfs_reset_arq(dfs);
284 
285 	if (dfs->events != NULL) {
286 		qdf_mem_free(dfs->events);
287 		dfs->events = NULL;
288 	}
289 
290 	WLAN_DFSQ_LOCK_DESTROY(dfs);
291 	WLAN_ARQ_LOCK_DESTROY(dfs);
292 	WLAN_DFSEVENTQ_LOCK_DESTROY(dfs);
293 }
294 
295 int dfs_start_host_based_bangradar(struct wlan_dfs *dfs)
296 {
297 	dfs->wlan_radar_tasksched = 1;
298 	qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0);
299 
300 	return 0;
301 }
302