1 /* 2 * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2002-2006, 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 the dfs_attach() and dfs_detach() functions as well 20 * as the dfs_control() function which is used to process ioctls related to DFS. 21 * For Linux/Mac, "radartool" is the command line tool that can be used to call 22 * various ioctls to set and get radar detection thresholds. 23 */ 24 25 #include "../dfs_zero_cac.h" 26 #include "wlan_dfs_lmac_api.h" 27 #include "wlan_dfs_mlme_api.h" 28 #include "wlan_dfs_tgt_api.h" 29 #include "../dfs_internal.h" 30 #include "../dfs_filter_init.h" 31 #include "../dfs_partial_offload_radar.h" 32 33 #ifndef WLAN_DFS_STATIC_MEM_ALLOC 34 /* 35 * dfs_alloc_dfs_events() - allocate dfs events buffer 36 * 37 * Return: events buffer, null on failure. 38 */ 39 static inline struct dfs_event *dfs_alloc_dfs_events(void) 40 { 41 return qdf_mem_malloc(sizeof(struct dfs_event) * DFS_MAX_EVENTS); 42 } 43 44 /* 45 * dfs_free_dfs_events() - Free events buffer 46 * @events: Events buffer pointer 47 * 48 * Return: None 49 */ 50 static inline void dfs_free_dfs_events(struct dfs_event *events) 51 { 52 qdf_mem_free(events); 53 } 54 55 /* 56 * dfs_alloc_dfs_pulseline() - allocate buffer for dfs pulses 57 * 58 * Return: events buffer, null on failure. 59 */ 60 static inline struct dfs_pulseline *dfs_alloc_dfs_pulseline(void) 61 { 62 return qdf_mem_malloc(sizeof(struct dfs_pulseline)); 63 } 64 65 /* 66 * dfs_free_dfs_pulseline() - Free pulse buffer 67 * @pulses: Pulses buffer pointer 68 * 69 * Return: None 70 */ 71 static inline void dfs_free_dfs_pulseline(struct dfs_pulseline *pulses) 72 { 73 qdf_mem_free(pulses); 74 } 75 #else 76 /* Static buffers for DFS objects */ 77 static struct dfs_event global_dfs_event[DFS_MAX_EVENTS]; 78 static struct dfs_pulseline global_dfs_pulseline; 79 80 static inline struct dfs_event *dfs_alloc_dfs_events(void) 81 { 82 return global_dfs_event; 83 } 84 85 static inline void dfs_free_dfs_events(struct dfs_event *events) 86 { 87 } 88 89 static inline struct dfs_pulseline *dfs_alloc_dfs_pulseline(void) 90 { 91 return &global_dfs_pulseline; 92 } 93 94 static inline void dfs_free_dfs_pulseline(struct dfs_pulseline *pulses) 95 { 96 } 97 #endif 98 99 /* 100 * Channel switch announcement (CSA) 101 * usenol=1 (default) make CSA and switch to a new channel on radar detect 102 * usenol=0, make CSA with next channel same as current on radar detect 103 * usenol=2, no CSA and stay on the same channel on radar detect 104 */ 105 106 /** 107 * dfs_task() - The timer function to process the radar pulses. 108 */ 109 static os_timer_func(dfs_task) 110 { 111 struct wlan_dfs *dfs = NULL; 112 113 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 114 115 if (!dfs) { 116 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 117 return; 118 } 119 120 dfs_process_radarevent(dfs, dfs->dfs_curchan); 121 122 dfs->wlan_radar_tasksched = 0; 123 } 124 125 /** 126 * dfs_main_task_timer_init() - Initialize dfs task timer. 127 * @dfs: Pointer to wlan_dfs structure. 128 */ 129 static void dfs_main_task_timer_init(struct wlan_dfs *dfs) 130 { 131 qdf_timer_init(NULL, 132 &(dfs->wlan_dfs_task_timer), 133 dfs_task, 134 (void *)(dfs), 135 QDF_TIMER_TYPE_WAKE_APPS); 136 } 137 138 /** 139 * dfs_free_filter() - free memory allocated for dfs ft_filters 140 * @radarf: pointer holding ft_filters. 141 * 142 * Return: None 143 */ 144 static void dfs_free_filter(struct dfs_filtertype *radarf) 145 { 146 uint8_t i; 147 148 for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) { 149 if (radarf->ft_filters[i]) { 150 qdf_mem_free(radarf->ft_filters[i]); 151 radarf->ft_filters[i] = NULL; 152 } 153 } 154 } 155 156 /** 157 * dfs_alloc_mem_filter() - allocate memory for dfs ft_filters 158 * @radarf: pointer holding ft_filters. 159 * 160 * Return: QDF_STATUS 161 */ 162 static QDF_STATUS dfs_alloc_mem_filter(struct dfs_filtertype *radarf) 163 { 164 uint8_t i; 165 166 for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) { 167 radarf->ft_filters[i] = qdf_mem_malloc(sizeof(struct 168 dfs_filter)); 169 if (!radarf->ft_filters[i]) { 170 /* Free all the filter if malloc failed */ 171 dfs_free_filter(radarf); 172 return QDF_STATUS_E_FAILURE; 173 } 174 } 175 176 return QDF_STATUS_SUCCESS; 177 } 178 179 int dfs_main_attach(struct wlan_dfs *dfs) 180 { 181 int i, n; 182 QDF_STATUS status; 183 struct wlan_dfs_radar_tab_info radar_info; 184 185 if (!dfs) { 186 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 187 return 0; 188 } 189 190 /* If ignore_dfs is set to 1 then Radar detection is disabled. */ 191 if (dfs->dfs_ignore_dfs) { 192 dfs_debug(dfs, WLAN_DEBUG_DFS1, "ignoring dfs"); 193 return 0; 194 } 195 196 /* 197 * Zero out radar_info. It's possible that the attach function 198 * won't fetch an initial regulatory configuration; you really 199 * do want to ensure that the contents indicates there aren't 200 * any filters. 201 */ 202 qdf_mem_zero(&radar_info, sizeof(radar_info)); 203 204 lmac_get_caps(dfs->dfs_pdev_obj, &(dfs->dfs_caps)); 205 206 dfs_clear_stats(dfs); 207 dfs->dfs_event_log_on = 1; 208 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "event log enabled by default"); 209 210 dfs->dfs_enable = 1; 211 212 /*Verify : Passing NULL to qdf_timer_init().*/ 213 dfs_main_task_timer_init(dfs); 214 215 dfs_host_wait_timer_init(dfs); 216 217 WLAN_DFSQ_LOCK_CREATE(dfs); 218 STAILQ_INIT(&dfs->dfs_radarq); 219 WLAN_ARQ_LOCK_CREATE(dfs); 220 STAILQ_INIT(&dfs->dfs_arq); 221 STAILQ_INIT(&(dfs->dfs_eventq)); 222 WLAN_DFSEVENTQ_LOCK_CREATE(dfs); 223 224 dfs->events = dfs_alloc_dfs_events(); 225 if (!(dfs->events)) { 226 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 227 "events allocation failed"); 228 return 1; 229 } 230 231 for (i = 0; i < DFS_MAX_EVENTS; i++) 232 STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i], 233 re_list); 234 235 dfs->pulses = dfs_alloc_dfs_pulseline(); 236 if (!(dfs->pulses)) { 237 dfs_free_dfs_events(dfs->events); 238 dfs->events = NULL; 239 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 240 "Pulse buffer allocation failed"); 241 return 1; 242 } 243 244 dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; 245 246 /* Allocate memory for radar filters. */ 247 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 248 dfs->dfs_radarf[n] = (struct dfs_filtertype *) 249 qdf_mem_malloc(sizeof(struct dfs_filtertype)); 250 if (!(dfs->dfs_radarf[n])) { 251 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 252 "cannot allocate memory for radar filter types"); 253 goto bad1; 254 } 255 qdf_mem_zero(dfs->dfs_radarf[n], 256 sizeof(struct dfs_filtertype)); 257 status = dfs_alloc_mem_filter(dfs->dfs_radarf[n]); 258 if (!QDF_IS_STATUS_SUCCESS(status)) { 259 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 260 "mem alloc for dfs_filter failed"); 261 goto bad1; 262 } 263 } 264 265 /* Allocate memory for radar table. */ 266 dfs->dfs_ftindextable = (int8_t **)qdf_mem_malloc( 267 DFS_NUM_FT_IDX_TBL_ROWS*sizeof(int8_t *)); 268 if (!(dfs->dfs_ftindextable)) { 269 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Cannot allocate memory for radar table"); 270 goto bad1; 271 } 272 for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) { 273 dfs->dfs_ftindextable[n] = qdf_mem_malloc( 274 DFS_MAX_RADAR_OVERLAP*sizeof(int8_t)); 275 if (!(dfs->dfs_ftindextable[n])) { 276 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 277 "cannot allocate memory for radar table entry"); 278 goto bad2; 279 } 280 } 281 282 dfs->dfs_use_nol = 1; 283 284 /* Init the cached extension channel busy for false alarm reduction */ 285 dfs->dfs_rinfo.ext_chan_busy_ts = lmac_get_tsf64(dfs->dfs_pdev_obj); 286 dfs->dfs_rinfo.dfs_ext_chan_busy = 0; 287 /* Init the Bin5 chirping related data */ 288 dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts; 289 dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR; 290 dfs->dfs_b5radars = NULL; 291 292 /* 293 * If dfs_init_radar_filters() fails, we can abort here and 294 * reconfigure when the first valid channel + radar config 295 * is available. 296 */ 297 if (dfs_init_radar_filters(dfs, &radar_info)) { 298 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "Radar Filter Intialization Failed"); 299 return 1; 300 } 301 302 dfs->wlan_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE; 303 dfs->wlan_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH; 304 dfs->dfs_phyerr_freq_min = 0x7fffffff; 305 dfs->dfs_phyerr_freq_max = 0; 306 dfs->dfs_phyerr_queued_count = 0; 307 dfs->dfs_phyerr_w53_counter = 0; 308 dfs->dfs_pri_multiplier = 2; 309 dfs_get_radars(dfs); 310 311 return 0; 312 313 bad2: 314 qdf_mem_free(dfs->dfs_ftindextable); 315 dfs->dfs_ftindextable = NULL; 316 bad1: 317 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 318 if (dfs->dfs_radarf[n] != NULL) { 319 dfs_free_filter(dfs->dfs_radarf[n]); 320 qdf_mem_free(dfs->dfs_radarf[n]); 321 dfs->dfs_radarf[n] = NULL; 322 } 323 } 324 if (dfs->pulses) { 325 dfs_free_dfs_pulseline(dfs->pulses); 326 dfs->pulses = NULL; 327 } 328 if (dfs->events) { 329 dfs_free_dfs_events(dfs->events); 330 dfs->events = NULL; 331 } 332 333 return 1; 334 } 335 336 void dfs_main_timer_reset(struct wlan_dfs *dfs) 337 { 338 if (dfs->wlan_radar_tasksched) { 339 qdf_timer_sync_cancel(&dfs->wlan_dfs_task_timer); 340 dfs->wlan_radar_tasksched = 0; 341 } 342 } 343 344 void dfs_main_timer_detach(struct wlan_dfs *dfs) 345 { 346 qdf_timer_free(&dfs->wlan_dfs_task_timer); 347 dfs->wlan_radar_tasksched = 0; 348 } 349 350 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) 351 void dfs_host_wait_timer_detach(struct wlan_dfs *dfs) 352 { 353 qdf_timer_free(&dfs->dfs_host_wait_timer); 354 } 355 #endif 356 357 void dfs_main_detach(struct wlan_dfs *dfs) 358 { 359 int n, empty; 360 361 if (!dfs->dfs_enable) { 362 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "Already detached"); 363 return; 364 } 365 366 dfs->dfs_enable = 0; 367 368 dfs_reset_radarq(dfs); 369 dfs_reset_alldelaylines(dfs); 370 371 if (dfs->pulses != NULL) { 372 dfs_free_dfs_pulseline(dfs->pulses); 373 dfs->pulses = NULL; 374 } 375 376 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 377 if (dfs->dfs_radarf[n] != NULL) { 378 dfs_free_filter(dfs->dfs_radarf[n]); 379 qdf_mem_free(dfs->dfs_radarf[n]); 380 dfs->dfs_radarf[n] = NULL; 381 } 382 } 383 384 if (dfs->dfs_ftindextable != NULL) { 385 for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) { 386 if (dfs->dfs_ftindextable[n] != NULL) { 387 qdf_mem_free(dfs->dfs_ftindextable[n]); 388 dfs->dfs_ftindextable[n] = NULL; 389 } 390 } 391 qdf_mem_free(dfs->dfs_ftindextable); 392 dfs->dfs_ftindextable = NULL; 393 dfs->wlan_dfs_isdfsregdomain = 0; 394 } 395 396 if (dfs->dfs_b5radars != NULL) { 397 qdf_mem_free(dfs->dfs_b5radars); 398 dfs->dfs_b5radars = NULL; 399 } 400 401 dfs_reset_ar(dfs); 402 403 WLAN_ARQ_LOCK(dfs); 404 empty = STAILQ_EMPTY(&(dfs->dfs_arq)); 405 WLAN_ARQ_UNLOCK(dfs); 406 if (!empty) 407 dfs_reset_arq(dfs); 408 409 if (dfs->events != NULL) { 410 dfs_free_dfs_events(dfs->events); 411 dfs->events = NULL; 412 } 413 414 WLAN_DFSQ_LOCK_DESTROY(dfs); 415 WLAN_ARQ_LOCK_DESTROY(dfs); 416 WLAN_DFSEVENTQ_LOCK_DESTROY(dfs); 417 } 418 419 int dfs_start_host_based_bangradar(struct wlan_dfs *dfs) 420 { 421 dfs->wlan_radar_tasksched = 1; 422 qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0); 423 424 return 0; 425 } 426