xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_init.c (revision 1b9674e21e24478fba4530f5ae7396b9555e9c6a)
1 /*
2  * Copyright (c) 2013, 2016-2018 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2002-2010, 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 initialization functions and functions that reset
20  * internal data structures.
21  */
22 
23 #include "../dfs.h"
24 #include "wlan_dfs_lmac_api.h"
25 
26 /**
27  * dfs_reset_filtertype() - Reset filtertype.
28  * @ft: Pointer to dfs_filtertype structure.
29  */
30 static inline void dfs_reset_filtertype(
31 		struct dfs_filtertype *ft)
32 {
33 	int j;
34 	struct dfs_filter *rf;
35 	struct dfs_delayline *dl;
36 
37 	for (j = 0; j < ft->ft_numfilters; j++) {
38 		rf = &(ft->ft_filters[j]);
39 		dl = &(rf->rf_dl);
40 		if (dl != NULL) {
41 			qdf_mem_zero(dl, sizeof(*dl));
42 			dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK;
43 		}
44 	}
45 }
46 
47 void dfs_reset_alldelaylines(struct wlan_dfs *dfs)
48 {
49 	struct dfs_filtertype *ft = NULL;
50 	struct dfs_pulseline *pl;
51 	int i;
52 
53 	if (!dfs) {
54 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
55 		return;
56 	}
57 	pl = dfs->pulses;
58 
59 	if (!pl) {
60 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "pl is NULL");
61 		return;
62 	}
63 
64 	/* Reset the pulse log. */
65 	pl->pl_firstelem = pl->pl_numelems = 0;
66 	pl->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK;
67 
68 	for (i = 0; i < DFS_MAX_RADAR_TYPES; i++) {
69 		if (dfs->dfs_radarf[i] != NULL) {
70 			ft = dfs->dfs_radarf[i];
71 			dfs_reset_filtertype(ft);
72 		}
73 	}
74 
75 	if (!(dfs->dfs_b5radars)) {
76 		if (dfs->dfs_rinfo.rn_numbin5radars > 0)
77 			dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
78 				"null dfs_b5radars, numbin5radars=%d domain=%d",
79 				dfs->dfs_rinfo.rn_numbin5radars,
80 				dfs->dfsdomain);
81 		return;
82 	}
83 
84 	for (i = 0; i < dfs->dfs_rinfo.rn_numbin5radars; i++) {
85 		qdf_mem_zero(&(dfs->dfs_b5radars[i].br_elems[0]),
86 				sizeof(struct dfs_bin5elem) * DFS_MAX_B5_SIZE);
87 		dfs->dfs_b5radars[i].br_firstelem = 0;
88 		dfs->dfs_b5radars[i].br_numelems = 0;
89 		dfs->dfs_b5radars[i].br_lastelem =
90 			(0xFFFFFFFF) & DFS_MAX_B5_MASK;
91 	}
92 }
93 
94 void dfs_reset_delayline(struct dfs_delayline *dl)
95 {
96 	qdf_mem_zero(&(dl->dl_elems[0]), sizeof(dl->dl_elems));
97 	dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK;
98 }
99 
100 void dfs_reset_filter_delaylines(struct dfs_filtertype *dft)
101 {
102 	struct dfs_filter *df;
103 	int i;
104 
105 	for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) {
106 		df = &dft->ft_filters[i];
107 		dfs_reset_delayline(&(df->rf_dl));
108 	}
109 }
110 
111 void dfs_reset_radarq(struct wlan_dfs *dfs)
112 {
113 	struct dfs_event *event;
114 
115 	if (!dfs) {
116 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
117 		return;
118 	}
119 
120 	WLAN_DFSQ_LOCK(dfs);
121 	WLAN_DFSEVENTQ_LOCK(dfs);
122 	while (!STAILQ_EMPTY(&(dfs->dfs_radarq))) {
123 		event = STAILQ_FIRST(&(dfs->dfs_radarq));
124 		STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list);
125 		qdf_mem_zero(event, sizeof(struct dfs_event));
126 		STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list);
127 	}
128 	WLAN_DFSEVENTQ_UNLOCK(dfs);
129 	WLAN_DFSQ_UNLOCK(dfs);
130 }
131 
132 /**
133  * dfs_fill_ft_index_table() - DFS fill ft index table.
134  * @dfs: Pointer to wlan_dfs structure.
135  * @i: Duration used as an index.
136  *
137  * Return: 1 if too many overlapping radar filters else 0.
138  */
139 static inline bool dfs_fill_ft_index_table(
140 		struct wlan_dfs *dfs,
141 		int i)
142 {
143 	uint32_t stop = 0, tableindex = 0;
144 
145 	while ((tableindex < DFS_MAX_RADAR_OVERLAP) && (!stop)) {
146 		if ((dfs->dfs_ftindextable[i])[tableindex] == -1)
147 			stop = 1;
148 		else
149 			tableindex++;
150 	}
151 
152 	if (stop) {
153 		(dfs->dfs_ftindextable[i])[tableindex] =
154 			(int8_t)(dfs->dfs_rinfo.rn_ftindex);
155 	} else {
156 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Too many overlapping radar filters");
157 		return 1;
158 	}
159 
160 	return 0;
161 }
162 
163 /**
164  * dfs_fill_filter_type() - DFS fill filter type.
165  * @dfs: Pointer to wlan_dfs structure.
166  * @ft: Double pointer to dfs_filtertype structure.
167  * @dfs_radars: Pointer to dfs_pulse structure.
168  * @min_rssithresh: Minimum RSSI threshold.
169  * @max_pulsedur: Maximum RSSI threshold.
170  * @p: Index to dfs_pulse structure.
171  *
172  * Return: 1 if too many overlapping radar filters else 0.
173  */
174 static inline bool dfs_fill_filter_type(
175 		struct wlan_dfs *dfs,
176 		struct dfs_filtertype **ft,
177 		struct dfs_pulse *dfs_radars,
178 		int32_t *min_rssithresh,
179 		uint32_t *max_pulsedur,
180 		int p)
181 {
182 	int i;
183 
184 	/* No filter of the appropriate dur was found. */
185 	if ((dfs->dfs_rinfo.rn_ftindex + 1) > DFS_MAX_RADAR_TYPES) {
186 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Too many filter types");
187 		return 1;
188 	}
189 	(*ft) = dfs->dfs_radarf[dfs->dfs_rinfo.rn_ftindex];
190 	(*ft)->ft_numfilters = 0;
191 	(*ft)->ft_numpulses = dfs_radars[p].rp_numpulses;
192 	(*ft)->ft_patterntype = dfs_radars[p].rp_patterntype;
193 	(*ft)->ft_mindur = dfs_radars[p].rp_mindur;
194 	(*ft)->ft_maxdur = dfs_radars[p].rp_maxdur;
195 	(*ft)->ft_filterdur = dfs_radars[p].rp_pulsedur;
196 	(*ft)->ft_rssithresh = dfs_radars[p].rp_rssithresh;
197 	(*ft)->ft_rssimargin = dfs_radars[p].rp_rssimargin;
198 	(*ft)->ft_minpri = 1000000;
199 
200 	if ((*ft)->ft_rssithresh < *min_rssithresh)
201 		*min_rssithresh = (*ft)->ft_rssithresh;
202 
203 	if ((*ft)->ft_maxdur > *max_pulsedur)
204 		*max_pulsedur = (*ft)->ft_maxdur;
205 
206 	for (i = (*ft)->ft_mindur; i <= (*ft)->ft_maxdur; i++) {
207 		if (dfs_fill_ft_index_table(dfs, i))
208 			return 1;
209 	}
210 
211 	dfs->dfs_rinfo.rn_ftindex++;
212 
213 	return 0;
214 }
215 
216 int dfs_init_radar_filters(struct wlan_dfs *dfs,
217 		struct wlan_dfs_radar_tab_info *radar_info)
218 {
219 	struct dfs_filtertype *ft = NULL;
220 	struct dfs_filter *rf = NULL;
221 	struct dfs_pulse *dfs_radars;
222 	struct dfs_bin5pulse *b5pulses = NULL;
223 	uint32_t T, Tmax;
224 	int32_t min_rssithresh = DFS_MAX_RSSI_VALUE;
225 	uint32_t max_pulsedur = 0;
226 	int numpulses, p, n, i;
227 	int numradars = 0, numb5radars = 0;
228 	int retval;
229 
230 	if (!dfs) {
231 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
232 		return 1;
233 	}
234 
235 	dfs_debug(dfs, WLAN_DEBUG_DFS,
236 			"dfsdomain=%d, numradars=%d, numb5radars=%d",
237 			 radar_info->dfsdomain,
238 			radar_info->numradars, radar_info->numb5radars);
239 
240 	/* Clear up the dfs domain flag first. */
241 	dfs->wlan_dfs_isdfsregdomain = 0;
242 
243 	/*
244 	 * If radar_info is NULL or dfsdomain is NULL, treat the
245 	 * rest of the radar configuration as suspect.
246 	 */
247 	if (!radar_info || radar_info->dfsdomain == 0) {
248 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Unknown dfs domain %d",
249 				 dfs->dfsdomain);
250 		/* Disable radar detection since we don't have a radar domain.*/
251 		dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
252 		dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
253 		return 0;
254 	}
255 
256 	dfs->dfsdomain = radar_info->dfsdomain;
257 	dfs_radars = radar_info->dfs_radars;
258 	numradars = radar_info->numradars;
259 	b5pulses = radar_info->b5pulses;
260 	numb5radars = radar_info->numb5radars;
261 
262 	dfs->dfs_defaultparams = radar_info->dfs_defaultparams;
263 
264 	dfs->wlan_dfs_isdfsregdomain = 1;
265 	dfs->dfs_rinfo.rn_ftindex = 0;
266 	/* Clear filter type table. */
267 	for (n = 0; n < 256; n++) {
268 		for (i = 0; i < DFS_MAX_RADAR_OVERLAP; i++)
269 			(dfs->dfs_ftindextable[n])[i] = -1;
270 	}
271 
272 	/* Now, initialize the radar filters. */
273 	for (p = 0; p < numradars; p++) {
274 		ft = NULL;
275 		for (n = 0; n < dfs->dfs_rinfo.rn_ftindex; n++) {
276 			if ((dfs_radars[p].rp_pulsedur ==
277 				    dfs->dfs_radarf[n]->ft_filterdur) &&
278 				(dfs_radars[p].rp_numpulses ==
279 				 dfs->dfs_radarf[n]->ft_numpulses) &&
280 				(dfs_radars[p].rp_mindur ==
281 				 dfs->dfs_radarf[n]->ft_mindur) &&
282 				(dfs_radars[p].rp_maxdur ==
283 				 dfs->dfs_radarf[n]->ft_maxdur)) {
284 				ft = dfs->dfs_radarf[n];
285 				break;
286 			}
287 		}
288 
289 		if (!ft) {
290 			retval = dfs_fill_filter_type(dfs, &ft, dfs_radars,
291 					&min_rssithresh, &max_pulsedur, p);
292 			if (retval == 1)
293 				goto bad4;
294 		}
295 
296 		rf = &(ft->ft_filters[ft->ft_numfilters++]);
297 		dfs_reset_delayline(&rf->rf_dl);
298 		numpulses = dfs_radars[p].rp_numpulses;
299 
300 		rf->rf_numpulses = numpulses;
301 		rf->rf_patterntype = dfs_radars[p].rp_patterntype;
302 		rf->rf_sidx_spread = dfs_radars[p].rp_sidx_spread;
303 		rf->rf_check_delta_peak = dfs_radars[p].rp_check_delta_peak;
304 		rf->rf_pulseid = dfs_radars[p].rp_pulseid;
305 		rf->rf_mindur = dfs_radars[p].rp_mindur;
306 		rf->rf_maxdur = dfs_radars[p].rp_maxdur;
307 		rf->rf_numpulses = dfs_radars[p].rp_numpulses;
308 		rf->rf_ignore_pri_window = dfs_radars[p].rp_ignore_pri_window;
309 		T = (100000000 / dfs_radars[p].rp_max_pulsefreq) -
310 			100 * (dfs_radars[p].rp_meanoffset);
311 		rf->rf_minpri = dfs_round((int32_t)T -
312 				(100 * (dfs_radars[p].rp_pulsevar)));
313 		Tmax = (100000000 / dfs_radars[p].rp_pulsefreq) -
314 			100 * (dfs_radars[p].rp_meanoffset);
315 		rf->rf_maxpri = dfs_round((int32_t)Tmax +
316 				(100 * (dfs_radars[p].rp_pulsevar)));
317 
318 		if (rf->rf_minpri < ft->ft_minpri)
319 			ft->ft_minpri = rf->rf_minpri;
320 
321 		rf->rf_fixed_pri_radar_pulse = (
322 				dfs_radars[p].rp_max_pulsefreq ==
323 				dfs_radars[p].rp_pulsefreq) ?  1 : 0;
324 		rf->rf_threshold = dfs_radars[p].rp_threshold;
325 		rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses;
326 
327 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
328 				"minprf = %d maxprf = %d pulsevar = %d thresh=%d",
329 				dfs_radars[p].rp_pulsefreq,
330 				dfs_radars[p].rp_max_pulsefreq,
331 				dfs_radars[p].rp_pulsevar,
332 				rf->rf_threshold);
333 
334 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
335 				"minpri = %d maxpri = %d filterlen = %d filterID = %d",
336 				rf->rf_minpri, rf->rf_maxpri,
337 				rf->rf_filterlen, rf->rf_pulseid);
338 	}
339 
340 	dfs_print_filters(dfs);
341 
342 	dfs->dfs_rinfo.rn_numbin5radars  = numb5radars;
343 	if (dfs->dfs_b5radars) {
344 		qdf_mem_free(dfs->dfs_b5radars);
345 		dfs->dfs_b5radars = NULL;
346 	}
347 
348 	if (numb5radars) {
349 		dfs->dfs_b5radars = (struct dfs_bin5radars *)qdf_mem_malloc(
350 				numb5radars * sizeof(struct dfs_bin5radars));
351 		/*
352 		 * Malloc can return NULL if numb5radars is zero. But we still
353 		 * want to reset the delay lines.
354 		 */
355 		if (!(dfs->dfs_b5radars)) {
356 			dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS,
357 					"cannot allocate memory for bin5 radars");
358 			goto bad4;
359 		}
360 	}
361 
362 	for (n = 0; n < numb5radars; n++) {
363 		dfs->dfs_b5radars[n].br_pulse = b5pulses[n];
364 		dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= 1000000;
365 		if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh <
366 				min_rssithresh)
367 			min_rssithresh =
368 				dfs->dfs_b5radars[n].br_pulse.b5_rssithresh;
369 
370 		if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur)
371 			max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur;
372 	}
373 	dfs_reset_alldelaylines(dfs);
374 	dfs_reset_radarq(dfs);
375 	dfs->dfs_curchan_radindex = -1;
376 	dfs->dfs_extchan_radindex = -1;
377 	dfs->dfs_rinfo.rn_minrssithresh = min_rssithresh;
378 
379 	/* Convert durations to TSF ticks. */
380 	dfs->dfs_rinfo.rn_maxpulsedur =
381 		dfs_round((int32_t)((max_pulsedur * 100/80) * 100));
382 	/*
383 	 * Relax the max pulse duration a little bit due to inaccuracy
384 	 * caused by chirping.
385 	 */
386 	dfs->dfs_rinfo.rn_maxpulsedur = dfs->dfs_rinfo.rn_maxpulsedur + 20;
387 
388 	dfs_debug(dfs, WLAN_DEBUG_DFS, "DFS min filter rssiThresh = %d",
389 			min_rssithresh);
390 
391 	dfs_debug(dfs, WLAN_DEBUG_DFS, "DFS max pulse dur = %d ticks",
392 			dfs->dfs_rinfo.rn_maxpulsedur);
393 
394 	return 0;
395 
396 bad4:
397 	return 1;
398 }
399 
400 void dfs_clear_stats(struct wlan_dfs *dfs)
401 {
402 	if (!dfs)
403 		return;
404 
405 	qdf_mem_zero(&dfs->wlan_dfs_stats, sizeof(struct dfs_stats));
406 	dfs->wlan_dfs_stats.last_reset_tstamp =
407 	    lmac_get_tsf64(dfs->dfs_pdev_obj);
408 }
409