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 /* Need to take a lock here since dfs filtering data structures are 121 * freed and re-allocated in dfs_init_radar_filters() during channel 122 * change which may happen in the middle of dfs pulse processing. 123 */ 124 WLAN_DFS_DATA_STRUCT_LOCK(dfs); 125 dfs_process_radarevent(dfs, dfs->dfs_curchan); 126 WLAN_DFS_DATA_STRUCT_UNLOCK(dfs); 127 128 dfs->wlan_radar_tasksched = 0; 129 } 130 131 /** 132 * dfs_main_task_timer_init() - Initialize dfs task timer. 133 * @dfs: Pointer to wlan_dfs structure. 134 */ 135 static void dfs_main_task_timer_init(struct wlan_dfs *dfs) 136 { 137 qdf_timer_init(NULL, 138 &(dfs->wlan_dfs_task_timer), 139 dfs_task, 140 (void *)(dfs), 141 QDF_TIMER_TYPE_WAKE_APPS); 142 } 143 144 /** 145 * dfs_free_filter() - free memory allocated for dfs ft_filters 146 * @radarf: pointer holding ft_filters. 147 * 148 * Return: None 149 */ 150 static void dfs_free_filter(struct dfs_filtertype *radarf) 151 { 152 uint8_t i; 153 154 for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) { 155 if (radarf->ft_filters[i]) { 156 qdf_mem_free(radarf->ft_filters[i]); 157 radarf->ft_filters[i] = NULL; 158 } 159 } 160 } 161 162 /** 163 * dfs_alloc_mem_filter() - allocate memory for dfs ft_filters 164 * @radarf: pointer holding ft_filters. 165 * 166 * Return: QDF_STATUS 167 */ 168 static QDF_STATUS dfs_alloc_mem_filter(struct dfs_filtertype *radarf) 169 { 170 uint8_t i; 171 172 for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) { 173 radarf->ft_filters[i] = qdf_mem_malloc(sizeof(struct 174 dfs_filter)); 175 if (!radarf->ft_filters[i]) { 176 /* Free all the filter if malloc failed */ 177 dfs_free_filter(radarf); 178 return QDF_STATUS_E_FAILURE; 179 } 180 } 181 182 return QDF_STATUS_SUCCESS; 183 } 184 185 int dfs_main_attach(struct wlan_dfs *dfs) 186 { 187 int i, n; 188 QDF_STATUS status; 189 struct wlan_dfs_radar_tab_info radar_info; 190 191 if (!dfs) { 192 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 193 return 0; 194 } 195 196 /* If ignore_dfs is set to 1 then Radar detection is disabled. */ 197 if (dfs->dfs_ignore_dfs) { 198 dfs_debug(dfs, WLAN_DEBUG_DFS1, "ignoring dfs"); 199 return 0; 200 } 201 202 /* 203 * Zero out radar_info. It's possible that the attach function 204 * won't fetch an initial regulatory configuration; you really 205 * do want to ensure that the contents indicates there aren't 206 * any filters. 207 */ 208 qdf_mem_zero(&radar_info, sizeof(radar_info)); 209 210 lmac_get_caps(dfs->dfs_pdev_obj, &(dfs->dfs_caps)); 211 212 dfs_clear_stats(dfs); 213 dfs->dfs_event_log_on = 1; 214 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "event log enabled by default"); 215 216 dfs->dfs_enable = 1; 217 218 /*Verify : Passing NULL to qdf_timer_init().*/ 219 dfs_main_task_timer_init(dfs); 220 221 dfs_host_wait_timer_init(dfs); 222 223 WLAN_DFSQ_LOCK_CREATE(dfs); 224 STAILQ_INIT(&dfs->dfs_radarq); 225 WLAN_ARQ_LOCK_CREATE(dfs); 226 STAILQ_INIT(&dfs->dfs_arq); 227 STAILQ_INIT(&(dfs->dfs_eventq)); 228 WLAN_DFSEVENTQ_LOCK_CREATE(dfs); 229 WLAN_DFS_DATA_STRUCT_LOCK_CREATE(dfs); 230 231 dfs->events = dfs_alloc_dfs_events(); 232 if (!(dfs->events)) { 233 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 234 "events allocation failed"); 235 return 1; 236 } 237 238 for (i = 0; i < DFS_MAX_EVENTS; i++) 239 STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i], 240 re_list); 241 242 dfs->pulses = dfs_alloc_dfs_pulseline(); 243 if (!(dfs->pulses)) { 244 dfs_free_dfs_events(dfs->events); 245 dfs->events = NULL; 246 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 247 "Pulse buffer allocation failed"); 248 return 1; 249 } 250 251 dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; 252 253 /* Allocate memory for radar filters. */ 254 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 255 dfs->dfs_radarf[n] = (struct dfs_filtertype *) 256 qdf_mem_malloc(sizeof(struct dfs_filtertype)); 257 if (!(dfs->dfs_radarf[n])) { 258 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 259 "cannot allocate memory for radar filter types"); 260 goto bad1; 261 } 262 qdf_mem_zero(dfs->dfs_radarf[n], 263 sizeof(struct dfs_filtertype)); 264 status = dfs_alloc_mem_filter(dfs->dfs_radarf[n]); 265 if (!QDF_IS_STATUS_SUCCESS(status)) { 266 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 267 "mem alloc for dfs_filter failed"); 268 goto bad1; 269 } 270 } 271 272 /* Allocate memory for radar table. */ 273 dfs->dfs_ftindextable = (int8_t **)qdf_mem_malloc( 274 DFS_NUM_FT_IDX_TBL_ROWS*sizeof(int8_t *)); 275 if (!(dfs->dfs_ftindextable)) { 276 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Cannot allocate memory for radar table"); 277 goto bad1; 278 } 279 for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) { 280 dfs->dfs_ftindextable[n] = qdf_mem_malloc( 281 DFS_MAX_RADAR_OVERLAP*sizeof(int8_t)); 282 if (!(dfs->dfs_ftindextable[n])) { 283 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 284 "cannot allocate memory for radar table entry"); 285 goto bad2; 286 } 287 } 288 289 dfs->dfs_use_nol = 1; 290 291 /* Init the cached extension channel busy for false alarm reduction */ 292 dfs->dfs_rinfo.ext_chan_busy_ts = lmac_get_tsf64(dfs->dfs_pdev_obj); 293 dfs->dfs_rinfo.dfs_ext_chan_busy = 0; 294 /* Init the Bin5 chirping related data */ 295 dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts; 296 dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR; 297 dfs->dfs_b5radars = NULL; 298 299 /* 300 * If dfs_init_radar_filters() fails, we can abort here and 301 * reconfigure when the first valid channel + radar config 302 * is available. 303 */ 304 if (dfs_init_radar_filters(dfs, &radar_info)) { 305 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "Radar Filter Intialization Failed"); 306 return 1; 307 } 308 309 dfs->wlan_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE; 310 dfs->wlan_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH; 311 dfs->dfs_phyerr_freq_min = 0x7fffffff; 312 dfs->dfs_phyerr_freq_max = 0; 313 dfs->dfs_phyerr_queued_count = 0; 314 dfs->dfs_phyerr_w53_counter = 0; 315 dfs->dfs_pri_multiplier = 2; 316 dfs_get_radars(dfs); 317 318 return 0; 319 320 bad2: 321 qdf_mem_free(dfs->dfs_ftindextable); 322 dfs->dfs_ftindextable = NULL; 323 bad1: 324 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 325 if (dfs->dfs_radarf[n] != NULL) { 326 dfs_free_filter(dfs->dfs_radarf[n]); 327 qdf_mem_free(dfs->dfs_radarf[n]); 328 dfs->dfs_radarf[n] = NULL; 329 } 330 } 331 if (dfs->pulses) { 332 dfs_free_dfs_pulseline(dfs->pulses); 333 dfs->pulses = NULL; 334 } 335 if (dfs->events) { 336 dfs_free_dfs_events(dfs->events); 337 dfs->events = NULL; 338 } 339 340 return 1; 341 } 342 343 void dfs_main_timer_reset(struct wlan_dfs *dfs) 344 { 345 if (dfs->wlan_radar_tasksched) { 346 qdf_timer_sync_cancel(&dfs->wlan_dfs_task_timer); 347 dfs->wlan_radar_tasksched = 0; 348 } 349 } 350 351 void dfs_main_timer_detach(struct wlan_dfs *dfs) 352 { 353 qdf_timer_free(&dfs->wlan_dfs_task_timer); 354 dfs->wlan_radar_tasksched = 0; 355 } 356 357 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) 358 void dfs_host_wait_timer_detach(struct wlan_dfs *dfs) 359 { 360 qdf_timer_free(&dfs->dfs_host_wait_timer); 361 } 362 #endif 363 364 void dfs_main_detach(struct wlan_dfs *dfs) 365 { 366 int n, empty; 367 368 if (!dfs->dfs_enable) { 369 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "Already detached"); 370 return; 371 } 372 373 dfs->dfs_enable = 0; 374 375 dfs_reset_radarq(dfs); 376 dfs_reset_alldelaylines(dfs); 377 378 if (dfs->pulses != NULL) { 379 dfs_free_dfs_pulseline(dfs->pulses); 380 dfs->pulses = NULL; 381 } 382 383 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 384 if (dfs->dfs_radarf[n] != NULL) { 385 dfs_free_filter(dfs->dfs_radarf[n]); 386 qdf_mem_free(dfs->dfs_radarf[n]); 387 dfs->dfs_radarf[n] = NULL; 388 } 389 } 390 391 if (dfs->dfs_ftindextable != NULL) { 392 for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) { 393 if (dfs->dfs_ftindextable[n] != NULL) { 394 qdf_mem_free(dfs->dfs_ftindextable[n]); 395 dfs->dfs_ftindextable[n] = NULL; 396 } 397 } 398 qdf_mem_free(dfs->dfs_ftindextable); 399 dfs->dfs_ftindextable = NULL; 400 dfs->wlan_dfs_isdfsregdomain = 0; 401 } 402 403 if (dfs->dfs_b5radars != NULL) { 404 qdf_mem_free(dfs->dfs_b5radars); 405 dfs->dfs_b5radars = NULL; 406 } 407 408 dfs_reset_ar(dfs); 409 410 WLAN_ARQ_LOCK(dfs); 411 empty = STAILQ_EMPTY(&(dfs->dfs_arq)); 412 WLAN_ARQ_UNLOCK(dfs); 413 if (!empty) 414 dfs_reset_arq(dfs); 415 416 if (dfs->events != NULL) { 417 dfs_free_dfs_events(dfs->events); 418 dfs->events = NULL; 419 } 420 421 WLAN_DFS_DATA_STRUCT_LOCK_DESTROY(dfs); 422 WLAN_DFSQ_LOCK_DESTROY(dfs); 423 WLAN_ARQ_LOCK_DESTROY(dfs); 424 WLAN_DFSEVENTQ_LOCK_DESTROY(dfs); 425 } 426 427 int dfs_start_host_based_bangradar(struct wlan_dfs *dfs) 428 { 429 dfs->wlan_radar_tasksched = 1; 430 qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0); 431 432 return 0; 433 } 434