1  /*
2   * Copyright (c) 2013, 2016-2019, 2021 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  #include <wlan_objmgr_vdev_obj.h>
26  #include <wlan_reg_services_api.h>
27  #include "wlan_dfs_utils_api.h"
28  
29  /**
30   * dfs_reset_filtertype() - Reset filtertype.
31   * @ft: Pointer to dfs_filtertype structure.
32   */
dfs_reset_filtertype(struct dfs_filtertype * ft)33  static inline void dfs_reset_filtertype(
34  		struct dfs_filtertype *ft)
35  {
36  	int j;
37  	struct dfs_filter *rf;
38  	struct dfs_delayline *dl;
39  
40  	for (j = 0; j < ft->ft_numfilters; j++) {
41  		rf = ft->ft_filters[j];
42  		dl = &(rf->rf_dl);
43  		if (dl) {
44  			qdf_mem_zero(dl, sizeof(*dl));
45  			dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK;
46  		}
47  	}
48  }
49  
dfs_reset_alldelaylines(struct wlan_dfs * dfs)50  void dfs_reset_alldelaylines(struct wlan_dfs *dfs)
51  {
52  	struct dfs_filtertype *ft = NULL;
53  	struct dfs_pulseline *pl;
54  	int i;
55  
56  	if (!dfs) {
57  		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
58  		return;
59  	}
60  	pl = dfs->pulses;
61  
62  	if (!pl) {
63  		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "pl is NULL");
64  		return;
65  	}
66  
67  	/* Reset the pulse log. */
68  	pl->pl_firstelem = pl->pl_numelems = 0;
69  	pl->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK;
70  
71  	for (i = 0; i < DFS_MAX_RADAR_TYPES; i++) {
72  		if (dfs->dfs_radarf[i]) {
73  			ft = dfs->dfs_radarf[i];
74  			dfs_reset_filtertype(ft);
75  		}
76  	}
77  
78  	if (!(dfs->dfs_b5radars)) {
79  		if (dfs->dfs_rinfo.rn_numbin5radars > 0)
80  			dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
81  				"null dfs_b5radars, numbin5radars=%d domain=%d",
82  				dfs->dfs_rinfo.rn_numbin5radars,
83  				dfs->dfsdomain);
84  		return;
85  	}
86  
87  	for (i = 0; i < dfs->dfs_rinfo.rn_numbin5radars; i++) {
88  		qdf_mem_zero(&(dfs->dfs_b5radars[i].br_elems[0]),
89  				sizeof(struct dfs_bin5elem) * DFS_MAX_B5_SIZE);
90  		dfs->dfs_b5radars[i].br_firstelem = 0;
91  		dfs->dfs_b5radars[i].br_numelems = 0;
92  		dfs->dfs_b5radars[i].br_lastelem =
93  			(0xFFFFFFFF) & DFS_MAX_B5_MASK;
94  	}
95  }
96  
dfs_reset_delayline(struct dfs_delayline * dl)97  void dfs_reset_delayline(struct dfs_delayline *dl)
98  {
99  	qdf_mem_zero(&(dl->dl_elems[0]), sizeof(dl->dl_elems));
100  	dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK;
101  }
102  
dfs_reset_filter_delaylines(struct dfs_filtertype * dft)103  void dfs_reset_filter_delaylines(struct dfs_filtertype *dft)
104  {
105  	struct dfs_filter *df;
106  	int i;
107  
108  	for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) {
109  		df = dft->ft_filters[i];
110  		dfs_reset_delayline(&(df->rf_dl));
111  	}
112  }
113  
dfs_reset_radarq(struct wlan_dfs * dfs)114  void dfs_reset_radarq(struct wlan_dfs *dfs)
115  {
116  	struct dfs_event *event;
117  
118  	if (!dfs) {
119  		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
120  		return;
121  	}
122  
123  	WLAN_DFSQ_LOCK(dfs);
124  	WLAN_DFSEVENTQ_LOCK(dfs);
125  	while (!STAILQ_EMPTY(&(dfs->dfs_radarq))) {
126  		event = STAILQ_FIRST(&(dfs->dfs_radarq));
127  		STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list);
128  		qdf_mem_zero(event, sizeof(struct dfs_event));
129  		STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list);
130  	}
131  	WLAN_DFSEVENTQ_UNLOCK(dfs);
132  	WLAN_DFSQ_UNLOCK(dfs);
133  }
134  
135  /**
136   * dfs_fill_ft_index_table() - DFS fill ft index table.
137   * @dfs: Pointer to wlan_dfs structure.
138   * @i: Duration used as an index.
139   *
140   * Return: 1 if too many overlapping radar filters else 0.
141   */
dfs_fill_ft_index_table(struct wlan_dfs * dfs,int i)142  static inline bool dfs_fill_ft_index_table(
143  		struct wlan_dfs *dfs,
144  		int i)
145  {
146  	uint32_t stop = 0, tableindex = 0;
147  
148  	while ((tableindex < DFS_MAX_RADAR_OVERLAP) && (!stop)) {
149  		if ((dfs->dfs_ftindextable[i])[tableindex] == -1)
150  			stop = 1;
151  		else
152  			tableindex++;
153  	}
154  
155  	if (stop) {
156  		(dfs->dfs_ftindextable[i])[tableindex] =
157  			(int8_t)(dfs->dfs_rinfo.rn_ftindex);
158  	} else {
159  		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Too many overlapping radar filters");
160  		return 1;
161  	}
162  
163  	return 0;
164  }
165  
166  /**
167   * dfs_fill_filter_type() - DFS fill filter type.
168   * @dfs: Pointer to wlan_dfs structure.
169   * @ft: Double pointer to dfs_filtertype structure.
170   * @dfs_radars: Pointer to dfs_pulse structure.
171   * @min_rssithresh: Minimum RSSI threshold.
172   * @max_pulsedur: Maximum RSSI threshold.
173   * @p: Index to dfs_pulse structure.
174   *
175   * Return: 1 if too many overlapping radar filters else 0.
176   */
dfs_fill_filter_type(struct wlan_dfs * dfs,struct dfs_filtertype ** ft,struct dfs_pulse * dfs_radars,int32_t * min_rssithresh,uint32_t * max_pulsedur,int p)177  static inline bool dfs_fill_filter_type(
178  		struct wlan_dfs *dfs,
179  		struct dfs_filtertype **ft,
180  		struct dfs_pulse *dfs_radars,
181  		int32_t *min_rssithresh,
182  		uint32_t *max_pulsedur,
183  		int p)
184  {
185  	int i;
186  
187  	/* No filter of the appropriate dur was found. */
188  	if ((dfs->dfs_rinfo.rn_ftindex + 1) > DFS_MAX_RADAR_TYPES) {
189  		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Too many filter types");
190  		return 1;
191  	}
192  	(*ft) = dfs->dfs_radarf[dfs->dfs_rinfo.rn_ftindex];
193  	(*ft)->ft_numfilters = 0;
194  	(*ft)->ft_numpulses = dfs_radars[p].rp_numpulses;
195  	(*ft)->ft_patterntype = dfs_radars[p].rp_patterntype;
196  	(*ft)->ft_mindur = dfs_radars[p].rp_mindur;
197  	(*ft)->ft_maxdur = dfs_radars[p].rp_maxdur;
198  	(*ft)->ft_filterdur = dfs_radars[p].rp_pulsedur;
199  	(*ft)->ft_rssithresh = dfs_radars[p].rp_rssithresh;
200  	(*ft)->ft_rssimargin = dfs_radars[p].rp_rssimargin;
201  	(*ft)->ft_minpri = 1000000;
202  
203  	if ((*ft)->ft_rssithresh < *min_rssithresh)
204  		*min_rssithresh = (*ft)->ft_rssithresh;
205  
206  	if ((*ft)->ft_maxdur > *max_pulsedur)
207  		*max_pulsedur = (*ft)->ft_maxdur;
208  
209  	for (i = (*ft)->ft_mindur; i <= (*ft)->ft_maxdur; i++) {
210  		if (dfs_fill_ft_index_table(dfs, i))
211  			return 1;
212  	}
213  
214  	dfs->dfs_rinfo.rn_ftindex++;
215  
216  	return 0;
217  }
218  
dfs_init_radar_filters(struct wlan_dfs * dfs,struct wlan_dfs_radar_tab_info * radar_info)219  int dfs_init_radar_filters(struct wlan_dfs *dfs,
220  		struct wlan_dfs_radar_tab_info *radar_info)
221  {
222  	struct dfs_filtertype *ft = NULL;
223  	struct dfs_filter *rf = NULL;
224  	struct dfs_pulse *dfs_radars;
225  	struct dfs_bin5pulse *b5pulses = NULL;
226  	uint32_t T, Tmax;
227  	int32_t min_rssithresh = DFS_MAX_RSSI_VALUE;
228  	uint32_t max_pulsedur = 0;
229  	int numpulses, p, n, i;
230  	int numradars = 0, numb5radars = 0;
231  	int retval;
232  
233  	if (!dfs) {
234  		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
235  		return 1;
236  	}
237  
238  	dfs_debug(dfs, WLAN_DEBUG_DFS,
239  			"dfsdomain=%d, numradars=%d, numb5radars=%d",
240  			 radar_info->dfsdomain,
241  			radar_info->numradars, radar_info->numb5radars);
242  
243  	/* Clear up the dfs domain flag first. */
244  	dfs->wlan_dfs_isdfsregdomain = 0;
245  
246  	/*
247  	 * If radar_info is NULL or dfsdomain is NULL, treat the
248  	 * rest of the radar configuration as suspect.
249  	 */
250  	if (!radar_info || radar_info->dfsdomain == 0) {
251  		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "Unknown dfs domain %d",
252  				 dfs->dfsdomain);
253  		/* Disable radar detection since we don't have a radar domain.*/
254  		dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
255  		dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
256  		return 0;
257  	}
258  
259  	dfs->dfsdomain = radar_info->dfsdomain;
260  	dfs_radars = radar_info->dfs_radars;
261  	numradars = radar_info->numradars;
262  	b5pulses = radar_info->b5pulses;
263  	numb5radars = radar_info->numb5radars;
264  
265  	dfs->dfs_defaultparams = radar_info->dfs_defaultparams;
266  
267  	dfs->wlan_dfs_isdfsregdomain = 1;
268  	dfs->dfs_rinfo.rn_ftindex = 0;
269  	/* Clear filter type table. */
270  	for (n = 0; n < 256; n++) {
271  		for (i = 0; i < DFS_MAX_RADAR_OVERLAP; i++)
272  			(dfs->dfs_ftindextable[n])[i] = -1;
273  	}
274  
275  	/* Now, initialize the radar filters. */
276  	for (p = 0; p < numradars; p++) {
277  		ft = NULL;
278  		for (n = 0; n < dfs->dfs_rinfo.rn_ftindex; n++) {
279  			if ((dfs_radars[p].rp_pulsedur ==
280  				    dfs->dfs_radarf[n]->ft_filterdur) &&
281  				(dfs_radars[p].rp_numpulses ==
282  				 dfs->dfs_radarf[n]->ft_numpulses) &&
283  				(dfs_radars[p].rp_mindur ==
284  				 dfs->dfs_radarf[n]->ft_mindur) &&
285  				(dfs_radars[p].rp_maxdur ==
286  				 dfs->dfs_radarf[n]->ft_maxdur)) {
287  				ft = dfs->dfs_radarf[n];
288  				/* ft_rssithresh means the minimum rp_rssithresh
289  				 * among the same radar type.
290  				 * min_rssithresh means the minimum
291  				 * rp_rssithresh among all radar type.
292  				 */
293  				if (ft->ft_rssithresh >
294  				    dfs_radars[p].rp_rssithresh)
295  					ft->ft_rssithresh =
296  						dfs_radars[p].rp_rssithresh;
297  				if (min_rssithresh > ft->ft_rssithresh)
298  					min_rssithresh = ft->ft_rssithresh;
299  				break;
300  			}
301  		}
302  
303  		if (!ft) {
304  			retval = dfs_fill_filter_type(dfs, &ft, dfs_radars,
305  					&min_rssithresh, &max_pulsedur, p);
306  			if (retval == 1)
307  				goto bad4;
308  		}
309  
310  		rf = ft->ft_filters[ft->ft_numfilters++];
311  		dfs_reset_delayline(&rf->rf_dl);
312  		numpulses = dfs_radars[p].rp_numpulses;
313  
314  		rf->rf_numpulses = numpulses;
315  		rf->rf_patterntype = dfs_radars[p].rp_patterntype;
316  		rf->rf_sidx_spread = dfs_radars[p].rp_sidx_spread;
317  		rf->rf_check_delta_peak = dfs_radars[p].rp_check_delta_peak;
318  		rf->rf_pulseid = dfs_radars[p].rp_pulseid;
319  		rf->rf_mindur = dfs_radars[p].rp_mindur;
320  		rf->rf_maxdur = dfs_radars[p].rp_maxdur;
321  		rf->rf_numpulses = dfs_radars[p].rp_numpulses;
322  		rf->rf_ignore_pri_window = dfs_radars[p].rp_ignore_pri_window;
323  		T = (100000000 / dfs_radars[p].rp_max_pulsefreq) -
324  			100 * (dfs_radars[p].rp_meanoffset);
325  		rf->rf_minpri = dfs_round((int32_t)T -
326  				(100 * (dfs_radars[p].rp_pulsevar)));
327  		Tmax = (100000000 / dfs_radars[p].rp_pulsefreq) -
328  			100 * (dfs_radars[p].rp_meanoffset);
329  		rf->rf_maxpri = dfs_round((int32_t)Tmax +
330  				(100 * (dfs_radars[p].rp_pulsevar)));
331  
332  		if (rf->rf_minpri < ft->ft_minpri)
333  			ft->ft_minpri = rf->rf_minpri;
334  
335  		rf->rf_fixed_pri_radar_pulse = (
336  				dfs_radars[p].rp_max_pulsefreq ==
337  				dfs_radars[p].rp_pulsefreq) ?  1 : 0;
338  		rf->rf_threshold = dfs_radars[p].rp_threshold;
339  		rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses;
340  
341  		dfs_debug(dfs, WLAN_DEBUG_DFS2,
342  				"minprf = %d maxprf = %d pulsevar = %d thresh=%d",
343  				dfs_radars[p].rp_pulsefreq,
344  				dfs_radars[p].rp_max_pulsefreq,
345  				dfs_radars[p].rp_pulsevar,
346  				rf->rf_threshold);
347  
348  		dfs_debug(dfs, WLAN_DEBUG_DFS2,
349  				"minpri = %d maxpri = %d filterlen = %d filterID = %d",
350  				rf->rf_minpri, rf->rf_maxpri,
351  				rf->rf_filterlen, rf->rf_pulseid);
352  	}
353  
354  	dfs_print_filters(dfs);
355  
356  	dfs->dfs_rinfo.rn_numbin5radars  = numb5radars;
357  	if (dfs->dfs_b5radars) {
358  		qdf_mem_free(dfs->dfs_b5radars);
359  		dfs->dfs_b5radars = NULL;
360  	}
361  
362  	if (numb5radars) {
363  		dfs->dfs_b5radars = (struct dfs_bin5radars *)qdf_mem_malloc(
364  				numb5radars * sizeof(struct dfs_bin5radars));
365  		/*
366  		 * Malloc can return NULL if numb5radars is zero. But we still
367  		 * want to reset the delay lines.
368  		 */
369  		if (!(dfs->dfs_b5radars))
370  			goto bad4;
371  	}
372  
373  	for (n = 0; n < numb5radars; n++) {
374  		dfs->dfs_b5radars[n].br_pulse = b5pulses[n];
375  		dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= 1000000;
376  		if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh <
377  				min_rssithresh)
378  			min_rssithresh =
379  				dfs->dfs_b5radars[n].br_pulse.b5_rssithresh;
380  
381  		if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur)
382  			max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur;
383  	}
384  	dfs_reset_alldelaylines(dfs);
385  	dfs_reset_radarq(dfs);
386  	dfs->dfs_curchan_radindex = -1;
387  	dfs->dfs_extchan_radindex = -1;
388  	dfs->dfs_rinfo.rn_minrssithresh = min_rssithresh;
389  
390  	/* Convert durations to TSF ticks. */
391  	dfs->dfs_rinfo.rn_maxpulsedur =
392  		dfs_round((int32_t)((max_pulsedur * 100/80) * 100));
393  	/*
394  	 * Relax the max pulse duration a little bit due to inaccuracy
395  	 * caused by chirping.
396  	 */
397  	dfs->dfs_rinfo.rn_maxpulsedur = dfs->dfs_rinfo.rn_maxpulsedur + 20;
398  
399  	dfs_debug(dfs, WLAN_DEBUG_DFS, "DFS min filter rssiThresh = %d",
400  			min_rssithresh);
401  
402  	dfs_debug(dfs, WLAN_DEBUG_DFS, "DFS max pulse dur = %d ticks",
403  			dfs->dfs_rinfo.rn_maxpulsedur);
404  
405  	return 0;
406  
407  bad4:
408  	return 1;
409  }
410  
dfs_clear_stats(struct wlan_dfs * dfs)411  void dfs_clear_stats(struct wlan_dfs *dfs)
412  {
413  	if (!dfs)
414  		return;
415  
416  	qdf_mem_zero(&dfs->wlan_dfs_stats, sizeof(struct dfs_stats));
417  	dfs->wlan_dfs_stats.last_reset_tstamp =
418  	    lmac_get_tsf64(dfs->dfs_pdev_obj);
419  }
420  
dfs_check_intersect_excl(int low_freq,int high_freq,int center_freq)421  bool dfs_check_intersect_excl(int low_freq, int high_freq, int center_freq)
422  {
423  	return ((center_freq > low_freq) && (center_freq < high_freq));
424  }
425  
dfs_check_etsi_overlap(int center_freq,int chan_width,int en302_502_freq_low,int en302_502_freq_high)426  int dfs_check_etsi_overlap(int center_freq, int chan_width,
427  			   int en302_502_freq_low, int en302_502_freq_high)
428  {
429  	int chan_freq_low;
430  	int chan_freq_high;
431  
432  	/* Calculate low/high frequency ranges */
433  	chan_freq_low = center_freq - (chan_width / 2);
434  	chan_freq_high = center_freq + (chan_width / 2);
435  
436  	return ((chan_freq_high == en302_502_freq_low) ||
437  		dfs_check_intersect_excl(en302_502_freq_low,
438  					 en302_502_freq_high,
439  					 chan_freq_low) ||
440  		dfs_check_intersect_excl(en302_502_freq_low,
441  					 en302_502_freq_high,
442  					 chan_freq_high));
443  }
444  
445  #ifdef CONFIG_CHAN_FREQ_API
dfs_is_en302_502_applicable(struct wlan_dfs * dfs)446  bool dfs_is_en302_502_applicable(struct wlan_dfs *dfs)
447  {
448  	int chan_freq;
449  	int chan_width;
450  	int overlap = 0;
451  	struct wlan_objmgr_vdev *vdev = NULL;
452  	struct wlan_channel *bss_chan = NULL;
453  
454  	/* Get centre frequency */
455  	chan_freq = dfs->dfs_curchan->dfs_ch_mhz_freq_seg1;
456  	vdev = wlan_objmgr_pdev_get_first_vdev(dfs->dfs_pdev_obj, WLAN_DFS_ID);
457  	if (!vdev) {
458  		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "vdev is NULL");
459  		return false;
460  	}
461  
462  	bss_chan = wlan_vdev_mlme_get_bss_chan(vdev);
463  	wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID);
464  	/* Grab width */
465  	chan_width = wlan_reg_get_bw_value(bss_chan->ch_width);
466  
467  	if (WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) {
468  		/* HT80_80 mode has 2 segments and each segment must
469  		 * be checked for control channel first.
470  		 */
471  		overlap = dfs_check_etsi_overlap(
472  				chan_freq, chan_width / 2,
473  				ETSI_RADAR_EN302_502_FREQ_LOWER,
474  				ETSI_RADAR_EN302_502_FREQ_UPPER);
475  
476  		/* check for extension channel */
477  		chan_freq = dfs->dfs_curchan->dfs_ch_mhz_freq_seg2;
478  
479  		overlap += dfs_check_etsi_overlap(
480  				chan_freq, chan_width / 2,
481  				ETSI_RADAR_EN302_502_FREQ_LOWER,
482  				ETSI_RADAR_EN302_502_FREQ_UPPER);
483  	} else {
484  		overlap = dfs_check_etsi_overlap(
485  				chan_freq, chan_width,
486  				ETSI_RADAR_EN302_502_FREQ_LOWER,
487  				ETSI_RADAR_EN302_502_FREQ_UPPER);
488  	}
489  
490  	return(wlan_reg_is_regdmn_en302502_applicable(dfs->dfs_pdev_obj) &&
491  	       overlap);
492  }
493  #endif
494