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