1 /* 2 * Copyright (c) 2013, 2016-2017 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 void dfs_reset_alldelaylines(struct wlan_dfs *dfs) 27 { 28 struct dfs_filtertype *ft = NULL; 29 struct dfs_filter *rf; 30 struct dfs_delayline *dl; 31 struct dfs_pulseline *pl; 32 int i, j; 33 34 if (dfs == NULL) { 35 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 36 "%s: sc_dfs is NULL\n", __func__); 37 return; 38 } 39 pl = dfs->pulses; 40 41 if (pl == NULL) { 42 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "%s: pl==NULL, dfs=%p\n", 43 __func__, dfs); 44 return; 45 } 46 47 if (dfs->dfs_b5radars == NULL) { 48 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "%s: pl==NULL, b5radars=%p\n", 49 __func__, dfs->dfs_b5radars); 50 return; 51 } 52 53 /* Reset the pulse log. */ 54 pl->pl_firstelem = pl->pl_numelems = 0; 55 pl->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; 56 57 for (i = 0; i < DFS_MAX_RADAR_TYPES; i++) { 58 if (dfs->dfs_radarf[i] != NULL) { 59 ft = dfs->dfs_radarf[i]; 60 for (j = 0; j < ft->ft_numfilters; j++) { 61 rf = &(ft->ft_filters[j]); 62 dl = &(rf->rf_dl); 63 if (dl != NULL) { 64 qdf_mem_zero(dl, 65 sizeof(struct dfs_delayline)); 66 dl->dl_lastelem = 67 (0xFFFFFFFF) & DFS_MAX_DL_MASK; 68 } 69 } 70 } 71 } 72 73 for (i = 0; i < dfs->dfs_rinfo.rn_numbin5radars; i++) { 74 qdf_mem_zero(&(dfs->dfs_b5radars[i].br_elems[0]), 75 sizeof(struct dfs_bin5elem) * DFS_MAX_B5_SIZE); 76 dfs->dfs_b5radars[i].br_firstelem = 0; 77 dfs->dfs_b5radars[i].br_numelems = 0; 78 dfs->dfs_b5radars[i].br_lastelem = 79 (0xFFFFFFFF) & DFS_MAX_B5_MASK; 80 } 81 } 82 83 void dfs_reset_delayline(struct dfs_delayline *dl) 84 { 85 qdf_mem_zero(&(dl->dl_elems[0]), sizeof(dl->dl_elems)); 86 dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK; 87 } 88 89 void dfs_reset_filter_delaylines(struct dfs_filtertype *dft) 90 { 91 struct dfs_filter *df; 92 int i; 93 94 for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) { 95 df = &dft->ft_filters[i]; 96 dfs_reset_delayline(&(df->rf_dl)); 97 } 98 } 99 100 void dfs_reset_radarq(struct wlan_dfs *dfs) 101 { 102 struct dfs_event *event; 103 104 if (dfs == NULL) { 105 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "%s: sc_dfs is NULL\n", 106 __func__); 107 return; 108 } 109 110 WLAN_DFSQ_LOCK(dfs); 111 WLAN_DFSEVENTQ_LOCK(dfs); 112 while (!STAILQ_EMPTY(&(dfs->dfs_radarq))) { 113 event = STAILQ_FIRST(&(dfs->dfs_radarq)); 114 STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); 115 qdf_mem_zero(event, sizeof(struct dfs_event)); 116 STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); 117 } 118 WLAN_DFSEVENTQ_UNLOCK(dfs); 119 WLAN_DFSQ_UNLOCK(dfs); 120 } 121 122 int dfs_init_radar_filters(struct wlan_dfs *dfs, 123 struct wlan_dfs_radar_tab_info *radar_info) 124 { 125 struct dfs_filtertype *ft = NULL; 126 struct dfs_filter *rf = NULL; 127 struct dfs_pulse *dfs_radars; 128 struct dfs_bin5pulse *b5pulses = NULL; 129 uint32_t T, Tmax; 130 int32_t min_rssithresh = DFS_MAX_RSSI_VALUE; 131 uint32_t max_pulsedur = 0; 132 int numpulses, p, n, i; 133 int numradars = 0, numb5radars = 0; 134 135 if (dfs == NULL) { 136 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "dfs is NULL %s", __func__); 137 return 1; 138 } 139 140 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 141 "%s: dfsdomain=%d, numradars=%d, numb5radars=%d\n", 142 __func__, radar_info->dfsdomain, 143 radar_info->numradars, radar_info->numb5radars); 144 145 /* Clear up the dfs domain flag first. */ 146 dfs->wlan_dfs_isdfsregdomain = 0; 147 148 /* 149 * If radar_info is NULL or dfsdomain is NULL, treat the 150 * rest of the radar configuration as suspect. 151 */ 152 if (radar_info == NULL || radar_info->dfsdomain == 0) { 153 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "%s: Unknown dfs domain %d\n", 154 __func__, dfs->dfsdomain); 155 /* Disable radar detection since we don't have a radar domain.*/ 156 dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; 157 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 158 return 0; 159 } 160 161 dfs->dfsdomain = radar_info->dfsdomain; 162 dfs_radars = radar_info->dfs_radars; 163 numradars = radar_info->numradars; 164 b5pulses = radar_info->b5pulses; 165 numb5radars = radar_info->numb5radars; 166 167 dfs->dfs_defaultparams = radar_info->dfs_defaultparams; 168 169 dfs->wlan_dfs_isdfsregdomain = 1; 170 dfs->dfs_rinfo.rn_numradars = 0; 171 /* Clear filter type table. */ 172 for (n = 0; n < 256; n++) { 173 for (i = 0; i < DFS_MAX_RADAR_OVERLAP; i++) 174 (dfs->dfs_radartable[n])[i] = -1; 175 } 176 177 /* Now, initialize the radar filters. */ 178 for (p = 0; p < numradars; p++) { 179 ft = NULL; 180 for (n = 0; n < dfs->dfs_rinfo.rn_numradars; n++) { 181 if ((dfs_radars[p].rp_pulsedur == 182 dfs->dfs_radarf[n]->ft_filterdur) && 183 (dfs_radars[p].rp_numpulses == 184 dfs->dfs_radarf[n]->ft_numpulses) && 185 (dfs_radars[p].rp_mindur == 186 dfs->dfs_radarf[n]->ft_mindur) && 187 (dfs_radars[p].rp_maxdur == 188 dfs->dfs_radarf[n]->ft_maxdur)) { 189 ft = dfs->dfs_radarf[n]; 190 break; 191 } 192 } 193 if (ft == NULL) { 194 /* No filter of the appropriate dur was found. */ 195 if ((dfs->dfs_rinfo.rn_numradars + 1) > 196 DFS_MAX_RADAR_TYPES) { 197 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 198 "%s: Too many filter types\n", 199 __func__); 200 goto bad4; 201 } 202 ft = dfs->dfs_radarf[dfs->dfs_rinfo.rn_numradars]; 203 ft->ft_numfilters = 0; 204 ft->ft_numpulses = dfs_radars[p].rp_numpulses; 205 ft->ft_patterntype = dfs_radars[p].rp_patterntype; 206 ft->ft_mindur = dfs_radars[p].rp_mindur; 207 ft->ft_maxdur = dfs_radars[p].rp_maxdur; 208 ft->ft_filterdur = dfs_radars[p].rp_pulsedur; 209 ft->ft_rssithresh = dfs_radars[p].rp_rssithresh; 210 ft->ft_rssimargin = dfs_radars[p].rp_rssimargin; 211 ft->ft_minpri = 1000000; 212 213 if (ft->ft_rssithresh < min_rssithresh) 214 min_rssithresh = ft->ft_rssithresh; 215 216 if (ft->ft_maxdur > max_pulsedur) 217 max_pulsedur = ft->ft_maxdur; 218 219 for (i = ft->ft_mindur; i <= ft->ft_maxdur; i++) { 220 uint32_t stop = 0, tableindex = 0; 221 222 while ((tableindex < DFS_MAX_RADAR_OVERLAP) && 223 (!stop)) { 224 if ((dfs->dfs_radartable[i])[tableindex] 225 == -1) 226 stop = 1; 227 else 228 tableindex++; 229 } 230 231 if (stop) { 232 (dfs->dfs_radartable[i])[tableindex] = 233 (int8_t) 234 (dfs->dfs_rinfo.rn_numradars); 235 } else { 236 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 237 "%s: Too many overlapping radar filters\n", 238 __func__); 239 goto bad4; 240 } 241 } 242 dfs->dfs_rinfo.rn_numradars++; 243 } 244 rf = &(ft->ft_filters[ft->ft_numfilters++]); 245 dfs_reset_delayline(&rf->rf_dl); 246 numpulses = dfs_radars[p].rp_numpulses; 247 248 rf->rf_numpulses = numpulses; 249 rf->rf_patterntype = dfs_radars[p].rp_patterntype; 250 rf->rf_pulseid = dfs_radars[p].rp_pulseid; 251 rf->rf_mindur = dfs_radars[p].rp_mindur; 252 rf->rf_maxdur = dfs_radars[p].rp_maxdur; 253 rf->rf_numpulses = dfs_radars[p].rp_numpulses; 254 rf->rf_ignore_pri_window = dfs_radars[p].rp_ignore_pri_window; 255 T = (100000000 / dfs_radars[p].rp_max_pulsefreq) - 256 100 * (dfs_radars[p].rp_meanoffset); 257 rf->rf_minpri = 258 dfs_round((int32_t)T - 259 (100 * (dfs_radars[p].rp_pulsevar))); 260 Tmax = (100000000 / dfs_radars[p].rp_pulsefreq) - 261 100 * (dfs_radars[p].rp_meanoffset); 262 rf->rf_maxpri = 263 dfs_round((int32_t)Tmax + 264 (100 * (dfs_radars[p].rp_pulsevar))); 265 266 if (rf->rf_minpri < ft->ft_minpri) 267 ft->ft_minpri = rf->rf_minpri; 268 269 rf->rf_fixed_pri_radar_pulse = 270 (dfs_radars[p].rp_max_pulsefreq == 271 dfs_radars[p].rp_pulsefreq) ? 1 : 0; 272 rf->rf_threshold = dfs_radars[p].rp_threshold; 273 rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses; 274 275 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, 276 "minprf = %d maxprf = %d pulsevar = %d thresh=%d\n", 277 dfs_radars[p].rp_pulsefreq, 278 dfs_radars[p].rp_max_pulsefreq, 279 dfs_radars[p].rp_pulsevar, 280 rf->rf_threshold); 281 282 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, 283 "minpri = %d maxpri = %d filterlen = %d filterID = %d\n", 284 rf->rf_minpri, rf->rf_maxpri, 285 rf->rf_filterlen, rf->rf_pulseid); 286 } 287 288 dfs_print_filters(dfs); 289 290 dfs->dfs_rinfo.rn_numbin5radars = numb5radars; 291 if (dfs->dfs_b5radars != NULL) 292 qdf_mem_free(dfs->dfs_b5radars); 293 294 dfs->dfs_b5radars = (struct dfs_bin5radars *)qdf_mem_malloc( 295 numb5radars * sizeof(struct dfs_bin5radars)); 296 if (dfs->dfs_b5radars == NULL) { 297 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 298 "%s: cannot allocate memory for bin5 radars\n", 299 __func__); 300 goto bad4; 301 } 302 for (n = 0; n < numb5radars; n++) { 303 dfs->dfs_b5radars[n].br_pulse = b5pulses[n]; 304 dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= 1000000; 305 if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh < 306 min_rssithresh) 307 min_rssithresh = 308 dfs->dfs_b5radars[n].br_pulse.b5_rssithresh; 309 310 if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur 311 > max_pulsedur) 312 max_pulsedur = 313 dfs->dfs_b5radars[n].br_pulse.b5_maxdur; 314 } 315 dfs_reset_alldelaylines(dfs); 316 dfs_reset_radarq(dfs); 317 dfs->dfs_curchan_radindex = -1; 318 dfs->dfs_extchan_radindex = -1; 319 dfs->dfs_rinfo.rn_minrssithresh = min_rssithresh; 320 321 /* Convert durations to TSF ticks. */ 322 dfs->dfs_rinfo.rn_maxpulsedur = 323 dfs_round((int32_t)((max_pulsedur * 100/80) * 100)); 324 /* 325 * Relax the max pulse duration a little bit due to inaccuracy 326 * caused by chirping. 327 */ 328 dfs->dfs_rinfo.rn_maxpulsedur = 329 dfs->dfs_rinfo.rn_maxpulsedur + 20; 330 331 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 332 "DFS min filter rssiThresh = %d\n", 333 min_rssithresh); 334 335 DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, 336 "DFS max pulse dur = %d ticks\n", 337 dfs->dfs_rinfo.rn_maxpulsedur); 338 339 return 0; 340 341 bad4: 342 return 1; 343 } 344 345 void dfs_clear_stats(struct wlan_dfs *dfs) 346 { 347 if (dfs == NULL) 348 return; 349 350 qdf_mem_zero(&dfs->wlan_dfs_stats, sizeof(struct dfs_stats)); 351 dfs->wlan_dfs_stats.last_reset_tstamp = 352 lmac_get_tsf64(dfs->dfs_pdev_obj); 353 } 354