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 /* 34 * Channel switch announcement (CSA) 35 * usenol=1 (default) make CSA and switch to a new channel on radar detect 36 * usenol=0, make CSA with next channel same as current on radar detect 37 * usenol=2, no CSA and stay on the same channel on radar detect 38 */ 39 40 /** 41 * dfs_task() - The timer function to process the radar pulses. 42 */ 43 static os_timer_func(dfs_task) 44 { 45 struct wlan_dfs *dfs = NULL; 46 47 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 48 49 if (!dfs) { 50 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 51 return; 52 } 53 54 dfs_process_radarevent(dfs, dfs->dfs_curchan); 55 56 dfs->wlan_radar_tasksched = 0; 57 } 58 59 /** 60 * dfs_main_task_timer_init() - Initialize dfs task timer. 61 * @dfs: Pointer to wlan_dfs structure. 62 */ 63 static void dfs_main_task_timer_init(struct wlan_dfs *dfs) 64 { 65 qdf_timer_init(NULL, 66 &(dfs->wlan_dfs_task_timer), 67 dfs_task, 68 (void *)(dfs), 69 QDF_TIMER_TYPE_WAKE_APPS); 70 } 71 72 int dfs_main_attach(struct wlan_dfs *dfs) 73 { 74 int i, n; 75 struct wlan_dfs_radar_tab_info radar_info; 76 77 if (!dfs) { 78 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 79 return 0; 80 } 81 82 /* If ignore_dfs is set to 1 then Radar detection is disabled. */ 83 if (dfs->dfs_ignore_dfs) { 84 dfs_debug(dfs, WLAN_DEBUG_DFS1, "ignoring dfs"); 85 return 0; 86 } 87 88 /* 89 * Zero out radar_info. It's possible that the attach function 90 * won't fetch an initial regulatory configuration; you really 91 * do want to ensure that the contents indicates there aren't 92 * any filters. 93 */ 94 qdf_mem_zero(&radar_info, sizeof(radar_info)); 95 96 lmac_get_caps(dfs->dfs_pdev_obj, &(dfs->dfs_caps)); 97 98 dfs_clear_stats(dfs); 99 dfs->dfs_event_log_on = 1; 100 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "event log enabled by default"); 101 102 dfs->dfs_enable = 1; 103 104 /*Verify : Passing NULL to qdf_timer_init().*/ 105 dfs_main_task_timer_init(dfs); 106 107 dfs_host_wait_timer_init(dfs); 108 109 WLAN_DFSQ_LOCK_CREATE(dfs); 110 STAILQ_INIT(&dfs->dfs_radarq); 111 WLAN_ARQ_LOCK_CREATE(dfs); 112 STAILQ_INIT(&dfs->dfs_arq); 113 STAILQ_INIT(&(dfs->dfs_eventq)); 114 WLAN_DFSEVENTQ_LOCK_CREATE(dfs); 115 116 dfs->events = (struct dfs_event *)qdf_mem_malloc( 117 sizeof(struct dfs_event)*DFS_MAX_EVENTS); 118 if (!(dfs->events)) { 119 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "events allocation failed"); 120 return 1; 121 } 122 for (i = 0; i < DFS_MAX_EVENTS; i++) 123 STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i], 124 re_list); 125 126 dfs->pulses = (struct dfs_pulseline *)qdf_mem_malloc( 127 sizeof(struct dfs_pulseline)); 128 if (!(dfs->pulses)) { 129 qdf_mem_free(dfs->events); 130 dfs->events = NULL; 131 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Pulse buffer allocation failed"); 132 return 1; 133 } 134 135 dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; 136 137 /* Allocate memory for radar filters. */ 138 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 139 dfs->dfs_radarf[n] = (struct dfs_filtertype *) 140 qdf_mem_malloc(sizeof(struct dfs_filtertype)); 141 if (!(dfs->dfs_radarf[n])) { 142 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 143 "cannot allocate memory for radar filter types"); 144 goto bad1; 145 } 146 qdf_mem_zero(dfs->dfs_radarf[n], sizeof(struct dfs_filtertype)); 147 } 148 149 /* Allocate memory for radar table. */ 150 dfs->dfs_ftindextable = (int8_t **)qdf_mem_malloc( 151 DFS_NUM_FT_IDX_TBL_ROWS*sizeof(int8_t *)); 152 if (!(dfs->dfs_ftindextable)) { 153 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, "Cannot allocate memory for radar table"); 154 goto bad1; 155 } 156 for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) { 157 dfs->dfs_ftindextable[n] = qdf_mem_malloc( 158 DFS_MAX_RADAR_OVERLAP*sizeof(int8_t)); 159 if (!(dfs->dfs_ftindextable[n])) { 160 dfs_alert(dfs, WLAN_DEBUG_DFS_ALWAYS, 161 "cannot allocate memory for radar table entry"); 162 goto bad2; 163 } 164 } 165 166 dfs->dfs_use_nol = 1; 167 168 /* Init the cached extension channel busy for false alarm reduction */ 169 dfs->dfs_rinfo.ext_chan_busy_ts = lmac_get_tsf64(dfs->dfs_pdev_obj); 170 dfs->dfs_rinfo.dfs_ext_chan_busy = 0; 171 /* Init the Bin5 chirping related data */ 172 dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts; 173 dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR; 174 dfs->dfs_b5radars = NULL; 175 176 /* 177 * If dfs_init_radar_filters() fails, we can abort here and 178 * reconfigure when the first valid channel + radar config 179 * is available. 180 */ 181 if (dfs_init_radar_filters(dfs, &radar_info)) { 182 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "Radar Filter Intialization Failed"); 183 return 1; 184 } 185 186 dfs->wlan_dfs_false_rssi_thres = RSSI_POSSIBLY_FALSE; 187 dfs->wlan_dfs_peak_mag = SEARCH_FFT_REPORT_PEAK_MAG_THRSH; 188 dfs->dfs_phyerr_freq_min = 0x7fffffff; 189 dfs->dfs_phyerr_freq_max = 0; 190 dfs->dfs_phyerr_queued_count = 0; 191 dfs->dfs_phyerr_w53_counter = 0; 192 dfs->dfs_pri_multiplier = 2; 193 dfs_get_radars(dfs); 194 195 return 0; 196 197 bad2: 198 qdf_mem_free(dfs->dfs_ftindextable); 199 dfs->dfs_ftindextable = NULL; 200 bad1: 201 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 202 if (dfs->dfs_radarf[n] != NULL) { 203 qdf_mem_free(dfs->dfs_radarf[n]); 204 dfs->dfs_radarf[n] = NULL; 205 } 206 } 207 if (dfs->pulses) { 208 qdf_mem_free(dfs->pulses); 209 dfs->pulses = NULL; 210 } 211 if (dfs->events) { 212 qdf_mem_free(dfs->events); 213 dfs->events = NULL; 214 } 215 216 return 1; 217 } 218 219 void dfs_main_timer_reset(struct wlan_dfs *dfs) 220 { 221 if (dfs->wlan_radar_tasksched) { 222 qdf_timer_stop(&dfs->wlan_dfs_task_timer); 223 dfs->wlan_radar_tasksched = 0; 224 } 225 226 if (dfs->wlan_dfstest) { 227 qdf_timer_stop(&dfs->wlan_dfstesttimer); 228 dfs->wlan_dfstest = 0; 229 } 230 } 231 232 void dfs_main_detach(struct wlan_dfs *dfs) 233 { 234 int n, empty; 235 236 if (!dfs->dfs_enable) { 237 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "Already detached"); 238 return; 239 } 240 241 dfs->dfs_enable = 0; 242 243 if (dfs->dfs_curchan != NULL) { 244 qdf_mem_free(dfs->dfs_curchan); 245 dfs->dfs_curchan = NULL; 246 } 247 248 dfs_reset_radarq(dfs); 249 dfs_reset_alldelaylines(dfs); 250 251 if (dfs->pulses != NULL) { 252 qdf_mem_free(dfs->pulses); 253 dfs->pulses = NULL; 254 } 255 256 for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { 257 if (dfs->dfs_radarf[n] != NULL) { 258 qdf_mem_free(dfs->dfs_radarf[n]); 259 dfs->dfs_radarf[n] = NULL; 260 } 261 } 262 263 if (dfs->dfs_ftindextable != NULL) { 264 for (n = 0; n < DFS_NUM_FT_IDX_TBL_ROWS; n++) { 265 if (dfs->dfs_ftindextable[n] != NULL) { 266 qdf_mem_free(dfs->dfs_ftindextable[n]); 267 dfs->dfs_ftindextable[n] = NULL; 268 } 269 } 270 qdf_mem_free(dfs->dfs_ftindextable); 271 dfs->dfs_ftindextable = NULL; 272 dfs->wlan_dfs_isdfsregdomain = 0; 273 } 274 275 if (dfs->dfs_b5radars != NULL) { 276 qdf_mem_free(dfs->dfs_b5radars); 277 dfs->dfs_b5radars = NULL; 278 } 279 280 dfs_reset_ar(dfs); 281 282 WLAN_ARQ_LOCK(dfs); 283 empty = STAILQ_EMPTY(&(dfs->dfs_arq)); 284 WLAN_ARQ_UNLOCK(dfs); 285 if (!empty) 286 dfs_reset_arq(dfs); 287 288 if (dfs->events != NULL) { 289 qdf_mem_free(dfs->events); 290 dfs->events = NULL; 291 } 292 293 WLAN_DFSQ_LOCK_DESTROY(dfs); 294 WLAN_ARQ_LOCK_DESTROY(dfs); 295 WLAN_DFSEVENTQ_LOCK_DESTROY(dfs); 296 } 297 298 int dfs_start_host_based_bangradar(struct wlan_dfs *dfs) 299 { 300 dfs->wlan_radar_tasksched = 1; 301 qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0); 302 303 return 0; 304 } 305