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 #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 */ 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 != NULL) { 44 qdf_mem_zero(dl, sizeof(*dl)); 45 dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK; 46 } 47 } 48 } 49 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] != NULL) { 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 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 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 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 */ 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 */ 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 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 break; 289 } 290 } 291 292 if (!ft) { 293 retval = dfs_fill_filter_type(dfs, &ft, dfs_radars, 294 &min_rssithresh, &max_pulsedur, p); 295 if (retval == 1) 296 goto bad4; 297 } 298 299 rf = ft->ft_filters[ft->ft_numfilters++]; 300 dfs_reset_delayline(&rf->rf_dl); 301 numpulses = dfs_radars[p].rp_numpulses; 302 303 rf->rf_numpulses = numpulses; 304 rf->rf_patterntype = dfs_radars[p].rp_patterntype; 305 rf->rf_sidx_spread = dfs_radars[p].rp_sidx_spread; 306 rf->rf_check_delta_peak = dfs_radars[p].rp_check_delta_peak; 307 rf->rf_pulseid = dfs_radars[p].rp_pulseid; 308 rf->rf_mindur = dfs_radars[p].rp_mindur; 309 rf->rf_maxdur = dfs_radars[p].rp_maxdur; 310 rf->rf_numpulses = dfs_radars[p].rp_numpulses; 311 rf->rf_ignore_pri_window = dfs_radars[p].rp_ignore_pri_window; 312 T = (100000000 / dfs_radars[p].rp_max_pulsefreq) - 313 100 * (dfs_radars[p].rp_meanoffset); 314 rf->rf_minpri = dfs_round((int32_t)T - 315 (100 * (dfs_radars[p].rp_pulsevar))); 316 Tmax = (100000000 / dfs_radars[p].rp_pulsefreq) - 317 100 * (dfs_radars[p].rp_meanoffset); 318 rf->rf_maxpri = dfs_round((int32_t)Tmax + 319 (100 * (dfs_radars[p].rp_pulsevar))); 320 321 if (rf->rf_minpri < ft->ft_minpri) 322 ft->ft_minpri = rf->rf_minpri; 323 324 rf->rf_fixed_pri_radar_pulse = ( 325 dfs_radars[p].rp_max_pulsefreq == 326 dfs_radars[p].rp_pulsefreq) ? 1 : 0; 327 rf->rf_threshold = dfs_radars[p].rp_threshold; 328 rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses; 329 330 dfs_debug(dfs, WLAN_DEBUG_DFS2, 331 "minprf = %d maxprf = %d pulsevar = %d thresh=%d", 332 dfs_radars[p].rp_pulsefreq, 333 dfs_radars[p].rp_max_pulsefreq, 334 dfs_radars[p].rp_pulsevar, 335 rf->rf_threshold); 336 337 dfs_debug(dfs, WLAN_DEBUG_DFS2, 338 "minpri = %d maxpri = %d filterlen = %d filterID = %d", 339 rf->rf_minpri, rf->rf_maxpri, 340 rf->rf_filterlen, rf->rf_pulseid); 341 } 342 343 dfs_print_filters(dfs); 344 345 dfs->dfs_rinfo.rn_numbin5radars = numb5radars; 346 if (dfs->dfs_b5radars) { 347 qdf_mem_free(dfs->dfs_b5radars); 348 dfs->dfs_b5radars = NULL; 349 } 350 351 if (numb5radars) { 352 dfs->dfs_b5radars = (struct dfs_bin5radars *)qdf_mem_malloc( 353 numb5radars * sizeof(struct dfs_bin5radars)); 354 /* 355 * Malloc can return NULL if numb5radars is zero. But we still 356 * want to reset the delay lines. 357 */ 358 if (!(dfs->dfs_b5radars)) { 359 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 360 "cannot allocate memory for bin5 radars"); 361 goto bad4; 362 } 363 } 364 365 for (n = 0; n < numb5radars; n++) { 366 dfs->dfs_b5radars[n].br_pulse = b5pulses[n]; 367 dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= 1000000; 368 if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh < 369 min_rssithresh) 370 min_rssithresh = 371 dfs->dfs_b5radars[n].br_pulse.b5_rssithresh; 372 373 if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur) 374 max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur; 375 } 376 dfs_reset_alldelaylines(dfs); 377 dfs_reset_radarq(dfs); 378 dfs->dfs_curchan_radindex = -1; 379 dfs->dfs_extchan_radindex = -1; 380 dfs->dfs_rinfo.rn_minrssithresh = min_rssithresh; 381 382 /* Convert durations to TSF ticks. */ 383 dfs->dfs_rinfo.rn_maxpulsedur = 384 dfs_round((int32_t)((max_pulsedur * 100/80) * 100)); 385 /* 386 * Relax the max pulse duration a little bit due to inaccuracy 387 * caused by chirping. 388 */ 389 dfs->dfs_rinfo.rn_maxpulsedur = dfs->dfs_rinfo.rn_maxpulsedur + 20; 390 391 dfs_debug(dfs, WLAN_DEBUG_DFS, "DFS min filter rssiThresh = %d", 392 min_rssithresh); 393 394 dfs_debug(dfs, WLAN_DEBUG_DFS, "DFS max pulse dur = %d ticks", 395 dfs->dfs_rinfo.rn_maxpulsedur); 396 397 return 0; 398 399 bad4: 400 return 1; 401 } 402 403 void dfs_clear_stats(struct wlan_dfs *dfs) 404 { 405 if (!dfs) 406 return; 407 408 qdf_mem_zero(&dfs->wlan_dfs_stats, sizeof(struct dfs_stats)); 409 dfs->wlan_dfs_stats.last_reset_tstamp = 410 lmac_get_tsf64(dfs->dfs_pdev_obj); 411 } 412 413 bool dfs_check_intersect_excl(int low_freq, int high_freq, int center_freq) 414 { 415 return ((center_freq > low_freq) && (center_freq < high_freq)); 416 } 417 418 int dfs_check_etsi_overlap(int center_freq, int chan_width, 419 int en302_502_freq_low, int en302_502_freq_high) 420 { 421 int chan_freq_low; 422 int chan_freq_high; 423 424 /* Calculate low/high frequency ranges */ 425 chan_freq_low = center_freq - (chan_width / 2); 426 chan_freq_high = center_freq + (chan_width / 2); 427 428 return ((chan_freq_high == en302_502_freq_low) || 429 dfs_check_intersect_excl(en302_502_freq_low, 430 en302_502_freq_high, 431 chan_freq_low) || 432 dfs_check_intersect_excl(en302_502_freq_low, 433 en302_502_freq_high, 434 chan_freq_high)); 435 } 436 437 bool dfs_is_en302_502_applicable(struct wlan_dfs *dfs) 438 { 439 int chan_freq; 440 int chan_width; 441 int overlap = 0; 442 uint16_t regdmn; 443 struct wlan_objmgr_vdev *vdev = NULL; 444 struct wlan_channel *bss_chan = NULL; 445 446 /* Get centre frequency */ 447 chan_freq = dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1; 448 vdev = wlan_objmgr_pdev_get_first_vdev(dfs->dfs_pdev_obj, WLAN_DFS_ID); 449 if (!vdev) { 450 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "vdev is NULL"); 451 return false; 452 } 453 454 bss_chan = wlan_vdev_mlme_get_bss_chan(vdev); 455 wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID); 456 /* Grab width */ 457 chan_width = wlan_reg_get_bw_value(bss_chan->ch_width); 458 459 if (WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) { 460 /* HT80_80 mode has 2 segments and each segment must 461 * be checked for control channel first. 462 */ 463 overlap = dfs_check_etsi_overlap( 464 chan_freq, chan_width / 2, 465 ETSI_RADAR_EN302_502_FREQ_LOWER, 466 ETSI_RADAR_EN302_502_FREQ_UPPER); 467 468 /* check for extension channel */ 469 chan_freq = utils_dfs_chan_to_freq( 470 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2); 471 472 overlap += dfs_check_etsi_overlap( 473 chan_freq, chan_width / 2, 474 ETSI_RADAR_EN302_502_FREQ_LOWER, 475 ETSI_RADAR_EN302_502_FREQ_UPPER); 476 } else { 477 overlap = dfs_check_etsi_overlap( 478 chan_freq, chan_width, 479 ETSI_RADAR_EN302_502_FREQ_LOWER, 480 ETSI_RADAR_EN302_502_FREQ_UPPER); 481 } 482 483 regdmn = utils_dfs_get_cur_rd(dfs->dfs_pdev_obj); 484 485 return(((regdmn == ETSI11_WORLD_REGDMN_PAIR_ID) || 486 (regdmn == ETSI12_WORLD_REGDMN_PAIR_ID) || 487 (regdmn == ETSI13_WORLD_REGDMN_PAIR_ID) || 488 (regdmn == ETSI14_WORLD_REGDMN_PAIR_ID)) && 489 overlap); 490 } 491