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