blob: ca259c4af8eae0cdd1b4be8e00628301cd22eb03 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/*===========================================================================
29
30 dfs_init.c
31
32 OVERVIEW:
33
34 Source code borrowed from QCA_MAIN DFS module
35
36 DEPENDENCIES:
37
38 Are listed for each API below.
39
40 ===========================================================================*/
41
42/*===========================================================================
43
44 EDIT HISTORY FOR FILE
45
46 This section contains comments describing changes made to the module.
47 Notice that changes are listed in reverse chronological order.
48
49 when who what, where, why
50 ---------- --- --------------------------------------------------------
51
52 ===========================================================================*/
53
54#include "dfs.h"
55/* TO DO DFS
56 #include <ieee80211_var.h>
57 */
58#ifdef ATH_SUPPORT_DFS
59
60extern int domainoverride;
61
62/*
63 * Clear all delay lines for all filter types
64 *
65 * This may be called before any radar pulses are configured
66 * (eg on a non-DFS channel, with radar PHY errors still showing up.)
67 * In that case, just drop out early.
68 */
69void dfs_reset_alldelaylines(struct ath_dfs *dfs)
70{
71 struct dfs_filtertype *ft = NULL;
72 struct dfs_filter *rf;
73 struct dfs_delayline *dl;
74 struct dfs_pulseline *pl;
75 int i, j;
76
77 if (dfs == NULL) {
78 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
79 "%s[%d]: sc_dfs is NULL", __func__, __LINE__);
80 return;
81 }
82 pl = dfs->pulses;
83
84 if (pl == NULL) {
85 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
86 "%s[%d]: pl==NULL, dfs=%p", __func__, __LINE__, dfs);
87 return;
88 }
89
90 if (dfs->dfs_b5radars == NULL) {
91 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
92 "%s[%d]: pl==NULL, b5radars=%p", __func__, __LINE__,
93 dfs->dfs_b5radars);
94 return;
95 }
96
97 /* reset the pulse log */
98 pl->pl_firstelem = pl->pl_numelems = 0;
99 pl->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK;
100
101 for (i = 0; i < DFS_MAX_RADAR_TYPES; i++) {
102 if (dfs->dfs_radarf[i] != NULL) {
103 ft = dfs->dfs_radarf[i];
104 if (NULL != ft) {
105 for (j = 0; j < ft->ft_numfilters; j++) {
106 rf = &(ft->ft_filters[j]);
107 dl = &(rf->rf_dl);
108 if (dl != NULL) {
109 OS_MEMZERO(dl,
110 sizeof(struct
111 dfs_delayline));
112 dl->dl_lastelem =
113 (0xFFFFFFFF) &
114 DFS_MAX_DL_MASK;
115 }
116 }
117 }
118 }
119 }
120 for (i = 0; i < dfs->dfs_rinfo.rn_numbin5radars; i++) {
121 OS_MEMZERO(&(dfs->dfs_b5radars[i].br_elems[0]),
122 sizeof(struct dfs_bin5elem) * DFS_MAX_B5_SIZE);
123 dfs->dfs_b5radars[i].br_firstelem = 0;
124 dfs->dfs_b5radars[i].br_numelems = 0;
125 dfs->dfs_b5radars[i].br_lastelem =
126 (0xFFFFFFFF) & DFS_MAX_B5_MASK;
127 }
128}
129
130/*
131 * Clear only a single delay line
132 */
133
134void dfs_reset_delayline(struct dfs_delayline *dl)
135{
136 OS_MEMZERO(&(dl->dl_elems[0]), sizeof(dl->dl_elems));
137 dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK;
138}
139
140void dfs_reset_filter_delaylines(struct dfs_filtertype *dft)
141{
142 int i;
143 struct dfs_filter *df;
144 for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) {
145 df = &dft->ft_filters[i];
146 dfs_reset_delayline(&(df->rf_dl));
147 }
148}
149
150void dfs_reset_radarq(struct ath_dfs *dfs)
151{
152 struct dfs_event *event;
153 if (dfs == NULL) {
154 DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL", __func__);
155 return;
156 }
157 ATH_DFSQ_LOCK(dfs);
158 ATH_DFSEVENTQ_LOCK(dfs);
159 while (!STAILQ_EMPTY(&(dfs->dfs_radarq))) {
160 event = STAILQ_FIRST(&(dfs->dfs_radarq));
161 STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list);
162 OS_MEMZERO(event, sizeof(struct dfs_event));
163 STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list);
164 }
165 ATH_DFSEVENTQ_UNLOCK(dfs);
166 ATH_DFSQ_UNLOCK(dfs);
167}
168
169/* This function Initialize the radar filter tables
170 * if the ath dfs domain is uninitalized or
171 * ath dfs domain is different from hal dfs domain
172 */
173int dfs_init_radar_filters(struct ieee80211com *ic,
174 struct ath_dfs_radar_tab_info *radar_info)
175{
176 uint32_t T, Tmax;
177 int numpulses, p, n, i;
178 int numradars = 0, numb5radars = 0;
179 struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs;
180 struct dfs_filtertype *ft = NULL;
181 struct dfs_filter *rf = NULL;
182 struct dfs_pulse *dfs_radars;
183 struct dfs_bin5pulse *b5pulses = NULL;
184 int32_t min_rssithresh = DFS_MAX_RSSI_VALUE;
185 uint32_t max_pulsedur = 0;
186
187 if (dfs == NULL) {
188 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
189 "%s[%d]: dfs is NULL", __func__, __LINE__);
190 return DFS_STATUS_FAIL;
191 }
192 /* clear up the dfs domain flag first */
193#ifndef ATH_DFS_RADAR_DETECTION_ONLY
194 dfs->ath_dfs_isdfsregdomain = 0;
195#endif
196
197 /*
198 * If radar_info is NULL or dfsdomain is NULL, treat
199 * the rest of the radar configuration as suspect.
200 */
201 if (radar_info == NULL || radar_info->dfsdomain == 0) {
202 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
203 "%s[%d]: Unknown dfs domain %d ",
204 __func__, __LINE__, dfs->dfsdomain);
205 /* Disable radar detection since we don't have a radar domain */
206 dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
207 /* Returning success though we are not completing init. A failure
208 * will fail dfs_attach also.
209 */
210 return DFS_STATUS_SUCCESS;
211 }
212
213 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
214 "%s[%d]:dfsdomain=%d, numradars=%d, numb5radars=%d",
215 __func__, __LINE__, radar_info->dfsdomain,
216 radar_info->numradars, radar_info->numb5radars);
217 dfs->dfsdomain = radar_info->dfsdomain;
218 dfs_radars = radar_info->dfs_radars;
219 numradars = radar_info->numradars;
220 b5pulses = radar_info->b5pulses;
221 numb5radars = radar_info->numb5radars;
222
223 /* XXX this should be an explicit copy of some sort! */
224 dfs->dfs_defaultparams = radar_info->dfs_defaultparams;
225
226#ifndef ATH_DFS_RADAR_DETECTION_ONLY
227 dfs->ath_dfs_isdfsregdomain = 1;
228#endif
229
230 dfs->dfs_rinfo.rn_numradars = 0;
231 /* Clear filter type table */
232 for (n = 0; n < 256; n++) {
233 for (i = 0; i < DFS_MAX_RADAR_OVERLAP; i++)
234 (dfs->dfs_radartable[n])[i] = -1;
235 }
236 /* Now, initialize the radar filters */
237 for (p = 0; p < numradars; p++) {
238 ft = NULL;
239 for (n = 0; n < dfs->dfs_rinfo.rn_numradars; n++) {
240 if ((dfs_radars[p].rp_pulsedur ==
241 dfs->dfs_radarf[n]->ft_filterdur)
242 && (dfs_radars[p].rp_numpulses ==
243 dfs->dfs_radarf[n]->ft_numpulses)
244 && (dfs_radars[p].rp_mindur ==
245 dfs->dfs_radarf[n]->ft_mindur)
246 && (dfs_radars[p].rp_maxdur ==
247 dfs->dfs_radarf[n]->ft_maxdur)) {
248 ft = dfs->dfs_radarf[n];
249 break;
250 }
251 }
252 if (ft == NULL) {
253 /* No filter of the appropriate dur was found */
254 if ((dfs->dfs_rinfo.rn_numradars + 1) >
255 DFS_MAX_RADAR_TYPES) {
256 DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
257 "%s: Too many filter types",
258 __func__);
259 goto bad4;
260 }
261 ft = dfs->dfs_radarf[dfs->dfs_rinfo.rn_numradars];
262 ft->ft_numfilters = 0;
263 ft->ft_numpulses = dfs_radars[p].rp_numpulses;
264 ft->ft_patterntype = dfs_radars[p].rp_patterntype;
265 ft->ft_mindur = dfs_radars[p].rp_mindur;
266 ft->ft_maxdur = dfs_radars[p].rp_maxdur;
267 ft->ft_filterdur = dfs_radars[p].rp_pulsedur;
268 ft->ft_rssithresh = dfs_radars[p].rp_rssithresh;
269 ft->ft_rssimargin = dfs_radars[p].rp_rssimargin;
270 ft->ft_minpri = 1000000;
271
272 if (ft->ft_rssithresh < min_rssithresh)
273 min_rssithresh = ft->ft_rssithresh;
274 if (ft->ft_maxdur > max_pulsedur)
275 max_pulsedur = ft->ft_maxdur;
276 for (i = ft->ft_mindur; i <= ft->ft_maxdur; i++) {
277 uint32_t stop = 0, tableindex = 0;
278 while ((tableindex < DFS_MAX_RADAR_OVERLAP)
279 && (!stop)) {
280 if ((dfs->
281 dfs_radartable[i])[tableindex] ==
282 -1)
283 stop = 1;
284 else
285 tableindex++;
286 }
287 if (stop) {
288 (dfs->dfs_radartable[i])[tableindex] =
289 (int8_t) (dfs->dfs_rinfo.
290 rn_numradars);
291 } else {
292 DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
293 "%s: Too many overlapping radar filters",
294 __func__);
295 goto bad4;
296 }
297 }
298 dfs->dfs_rinfo.rn_numradars++;
299 }
300 rf = &(ft->ft_filters[ft->ft_numfilters++]);
301 dfs_reset_delayline(&rf->rf_dl);
302 numpulses = dfs_radars[p].rp_numpulses;
303
304 rf->rf_numpulses = numpulses;
305 rf->rf_patterntype = dfs_radars[p].rp_patterntype;
306 rf->rf_pulseid = dfs_radars[p].rp_pulseid;
307 rf->rf_mindur = dfs_radars[p].rp_mindur;
308 rf->rf_maxdur = dfs_radars[p].rp_maxdur;
309 rf->rf_numpulses = dfs_radars[p].rp_numpulses;
310 rf->rf_ignore_pri_window = dfs_radars[p].rp_ignore_pri_window;
311 T = (100000000 / dfs_radars[p].rp_max_pulsefreq) -
312 100 * (dfs_radars[p].rp_meanoffset);
313 rf->rf_minpri =
314 dfs_round((int32_t) T -
315 (100 * (dfs_radars[p].rp_pulsevar)));
316 Tmax =
317 (100000000 / dfs_radars[p].rp_pulsefreq) -
318 100 * (dfs_radars[p].rp_meanoffset);
319 rf->rf_maxpri =
320 dfs_round((int32_t) Tmax +
321 (100 * (dfs_radars[p].rp_pulsevar)));
322
323 if (rf->rf_minpri < ft->ft_minpri)
324 ft->ft_minpri = rf->rf_minpri;
325
326 rf->rf_fixed_pri_radar_pulse =
327 (dfs_radars[p].rp_max_pulsefreq ==
328 dfs_radars[p].rp_pulsefreq) ? 1 : 0;
329 rf->rf_threshold = dfs_radars[p].rp_threshold;
330 rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses;
331
332 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
333 "%s[%d]: minprf = %d maxprf = %d pulsevar = %d thresh=%d",
334 __func__, __LINE__, dfs_radars[p].rp_pulsefreq,
335 dfs_radars[p].rp_max_pulsefreq,
336 dfs_radars[p].rp_pulsevar, rf->rf_threshold);
337 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
338 "%s[%d]:minpri = %d maxpri = %d filterlen = %d filterID = %d",
339 __func__, __LINE__, rf->rf_minpri, rf->rf_maxpri,
340 rf->rf_filterlen, rf->rf_pulseid);
341
342 }
343
344#ifdef DFS_DEBUG
345 dfs_print_filters(ic);
346#endif
347 dfs->dfs_rinfo.rn_numbin5radars = numb5radars;
348 if (dfs->dfs_b5radars != NULL)
349 OS_FREE(dfs->dfs_b5radars);
350
351 dfs->dfs_b5radars = (struct dfs_bin5radars *)os_malloc(NULL,
352 numb5radars *
353 sizeof(struct
354 dfs_bin5radars),
355 GFP_KERNEL);
356 if (dfs->dfs_b5radars == NULL) {
357 DFS_DPRINTK(dfs, ATH_DEBUG_DFS,
358 "%s: cannot allocate memory for bin5 radars",
359 __func__);
360 goto bad4;
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 if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur)
370 max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur;
371 }
372 dfs_reset_alldelaylines(dfs);
373 dfs_reset_radarq(dfs);
374 dfs->dfs_curchan_radindex = -1;
375 dfs->dfs_extchan_radindex = -1;
376 dfs->dfs_rinfo.rn_minrssithresh = min_rssithresh;
377 /* Convert durations to TSF ticks */
378 dfs->dfs_rinfo.rn_maxpulsedur =
379 dfs_round((int32_t) ((max_pulsedur * 100 / 80) * 100));
380 /* relax the max pulse duration a little bit due to inaccuracy caused by chirping. */
381 dfs->dfs_rinfo.rn_maxpulsedur = dfs->dfs_rinfo.rn_maxpulsedur + 20;
382 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
383 "%s[%d]: DFS min filter rssiThresh = %d",
384 __func__, __LINE__, min_rssithresh);
385 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
386 "%s[%d]:DFS max pulse dur = %d ticks",
387 __func__, __LINE__, dfs->dfs_rinfo.rn_maxpulsedur);
388 return DFS_STATUS_SUCCESS;
389
390bad4:
391 return DFS_STATUS_FAIL;
392}
393
394void dfs_clear_stats(struct ieee80211com *ic)
395{
396 struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs;
397 if (dfs == NULL)
398 return;
399 OS_MEMZERO(&dfs->ath_dfs_stats, sizeof(struct dfs_stats));
400 dfs->ath_dfs_stats.last_reset_tstamp = ic->ic_get_TSF64(ic);
401}
402
403#endif /* ATH_SUPPORT_DFS */