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