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 int dfs_main_attach(struct wlan_dfs *dfs) 139 { 140 int i, n; 141 struct wlan_dfs_radar_tab_info radar_info; 142 143 if (!dfs) { 144 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 145 return 0; 146 } 147 148 /* If ignore_dfs is set to 1 then Radar detection is disabled. */ 149 if (dfs->dfs_ignore_dfs) { 150 dfs_debug(dfs, WLAN_DEBUG_DFS1, "ignoring dfs"); 151 return 0; 152 } 153 154 /* 155 * Zero out radar_info. It's possible that the attach function 156 * won't fetch an initial regulatory configuration; you really 157 * do want to ensure that the contents indicates there aren't 158 * any filters. 159 */ 160 qdf_mem_zero(&radar_info, sizeof(radar_info)); 161 162 lmac_get_caps(dfs->dfs_pdev_obj, &(dfs->dfs_caps)); 163 164 dfs_clear_stats(dfs); 165 dfs->dfs_event_log_on = 1; 166 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "event log enabled by default"); 167 168 dfs->dfs_enable = 1; 169 170 /*Verify : Passing NULL to qdf_timer_init().*/ 171 dfs_main_task_timer_init(dfs); 172 173 dfs_host_wait_timer_init(dfs); 174 175 WLAN_DFSQ_LOCK_CREATE(dfs); 176 STAILQ_INIT(&dfs->dfs_radarq); 177 WLAN_ARQ_LOCK_CREATE(dfs); 178 STAILQ_INIT(&dfs->dfs_arq); 179 STAILQ_INIT(&(dfs->dfs_eventq)); 180 WLAN_DFSEVENTQ_LOCK_CREATE(dfs); 181 182 dfs->events = dfs_alloc_dfs_events(); 183 if (!(dfs->events)) { 184 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 185 "events allocation failed"); 186 return 1; 187 } 188 189 for (i = 0; i < DFS_MAX_EVENTS; i++) 190 STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i], 191 re_list); 192 193 dfs->pulses = dfs_alloc_dfs_pulseline(); 194 if (!(dfs->pulses)) { 195 dfs_free_dfs_events(dfs->events); 196 dfs->events = NULL; 197 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 198 "Pulse buffer allocation failed"); 199 return 1; 200 } 201 202 dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; 203 204 /* Allocate memory for radar filters. */ 205 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 206 dfs->dfs_radarf[n] = (struct dfs_filtertype *) 207 qdf_mem_malloc(sizeof(struct dfs_filtertype)); 208 if (!(dfs->dfs_radarf[n])) { 209 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 210 "cannot allocate memory for radar filter types"); 211 goto bad1; 212 } 213 qdf_mem_zero(dfs->dfs_radarf[n], sizeof(struct dfs_filtertype)); 214 } 215 216 /* Allocate memory for radar table. */ 217 dfs->dfs_ftindextable = (int8_t **)qdf_mem_malloc( 218 DFS_NUM_FT_IDX_TBL_ROWS*sizeof(int8_t *)); 219 if (!(dfs->dfs_ftindextable)) { 220 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Cannot allocate memory for radar table"); 221 goto bad1; 222 } 223 for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) { 224 dfs->dfs_ftindextable[n] = qdf_mem_malloc( 225 DFS_MAX_RADAR_OVERLAP*sizeof(int8_t)); 226 if (!(dfs->dfs_ftindextable[n])) { 227 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 228 "cannot allocate memory for radar table entry"); 229 goto bad2; 230 } 231 } 232 233 dfs->dfs_use_nol = 1; 234 235 /* Init the cached extension channel busy for false alarm reduction */ 236 dfs->dfs_rinfo.ext_chan_busy_ts = lmac_get_tsf64(dfs->dfs_pdev_obj); 237 dfs->dfs_rinfo.dfs_ext_chan_busy = 0; 238 /* Init the Bin5 chirping related data */ 239 dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts; 240 dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR; 241 dfs->dfs_b5radars = NULL; 242 243 /* 244 * If dfs_init_radar_filters() fails, we can abort here and 245 * reconfigure when the first valid channel + radar config 246 * is available. 247 */ 248 if (dfs_init_radar_filters(dfs, &radar_info)) { 249 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "Radar Filter Intialization Failed"); 250 return 1; 251 } 252 253 dfs->wlan_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE; 254 dfs->wlan_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH; 255 dfs->dfs_phyerr_freq_min = 0x7fffffff; 256 dfs->dfs_phyerr_freq_max = 0; 257 dfs->dfs_phyerr_queued_count = 0; 258 dfs->dfs_phyerr_w53_counter = 0; 259 dfs->dfs_pri_multiplier = 2; 260 dfs_get_radars(dfs); 261 262 return 0; 263 264 bad2: 265 qdf_mem_free(dfs->dfs_ftindextable); 266 dfs->dfs_ftindextable = NULL; 267 bad1: 268 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 269 if (dfs->dfs_radarf[n] != NULL) { 270 qdf_mem_free(dfs->dfs_radarf[n]); 271 dfs->dfs_radarf[n] = NULL; 272 } 273 } 274 if (dfs->pulses) { 275 dfs_free_dfs_pulseline(dfs->pulses); 276 dfs->pulses = NULL; 277 } 278 if (dfs->events) { 279 dfs_free_dfs_events(dfs->events); 280 dfs->events = NULL; 281 } 282 283 return 1; 284 } 285 286 void dfs_main_timer_reset(struct wlan_dfs *dfs) 287 { 288 if (dfs->wlan_radar_tasksched) { 289 qdf_timer_sync_cancel(&dfs->wlan_dfs_task_timer); 290 dfs->wlan_radar_tasksched = 0; 291 } 292 } 293 294 void dfs_main_timer_detach(struct wlan_dfs *dfs) 295 { 296 qdf_timer_free(&dfs->wlan_dfs_task_timer); 297 dfs->wlan_radar_tasksched = 0; 298 } 299 300 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) 301 void dfs_host_wait_timer_detach(struct wlan_dfs *dfs) 302 { 303 qdf_timer_free(&dfs->dfs_host_wait_timer); 304 } 305 #endif 306 307 void dfs_main_detach(struct wlan_dfs *dfs) 308 { 309 int n, empty; 310 311 if (!dfs->dfs_enable) { 312 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "Already detached"); 313 return; 314 } 315 316 dfs->dfs_enable = 0; 317 318 dfs_reset_radarq(dfs); 319 dfs_reset_alldelaylines(dfs); 320 321 if (dfs->pulses != NULL) { 322 dfs_free_dfs_pulseline(dfs->pulses); 323 dfs->pulses = NULL; 324 } 325 326 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 327 if (dfs->dfs_radarf[n] != NULL) { 328 qdf_mem_free(dfs->dfs_radarf[n]); 329 dfs->dfs_radarf[n] = NULL; 330 } 331 } 332 333 if (dfs->dfs_ftindextable != NULL) { 334 for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) { 335 if (dfs->dfs_ftindextable[n] != NULL) { 336 qdf_mem_free(dfs->dfs_ftindextable[n]); 337 dfs->dfs_ftindextable[n] = NULL; 338 } 339 } 340 qdf_mem_free(dfs->dfs_ftindextable); 341 dfs->dfs_ftindextable = NULL; 342 dfs->wlan_dfs_isdfsregdomain = 0; 343 } 344 345 if (dfs->dfs_b5radars != NULL) { 346 qdf_mem_free(dfs->dfs_b5radars); 347 dfs->dfs_b5radars = NULL; 348 } 349 350 dfs_reset_ar(dfs); 351 352 WLAN_ARQ_LOCK(dfs); 353 empty = STAILQ_EMPTY(&(dfs->dfs_arq)); 354 WLAN_ARQ_UNLOCK(dfs); 355 if (!empty) 356 dfs_reset_arq(dfs); 357 358 if (dfs->events != NULL) { 359 dfs_free_dfs_events(dfs->events); 360 dfs->events = NULL; 361 } 362 363 WLAN_DFSQ_LOCK_DESTROY(dfs); 364 WLAN_ARQ_LOCK_DESTROY(dfs); 365 WLAN_DFSEVENTQ_LOCK_DESTROY(dfs); 366 } 367 368 int dfs_start_host_based_bangradar(struct wlan_dfs *dfs) 369 { 370 dfs->wlan_radar_tasksched = 1; 371 qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0); 372 373 return 0; 374 } 375