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 */ 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 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 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 /* 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 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 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 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 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