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