1 /* 2 * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /** 28 * DOC: This file has the functions related to DFS CAC. 29 */ 30 31 #include "../dfs_channel.h" 32 #include "../dfs_zero_cac.h" 33 #include "../dfs_etsi_precac.h" 34 #include <wlan_objmgr_vdev_obj.h> 35 #include "wlan_dfs_utils_api.h" 36 #include "wlan_dfs_mlme_api.h" 37 #include "../dfs_internal.h" 38 #include "../dfs_process_radar_found_ind.h" 39 40 #define IS_CHANNEL_WEATHER_RADAR(freq) ((freq >= 5600) && (freq <= 5650)) 41 #define ADJACENT_WEATHER_RADAR_CHANNEL 5580 42 #define CH100_START_FREQ 5490 43 #define CH100 100 44 45 int dfs_override_cac_timeout(struct wlan_dfs *dfs, int cac_timeout) 46 { 47 if (!dfs) 48 return -EIO; 49 50 dfs->dfs_cac_timeout_override = cac_timeout; 51 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "CAC timeout is now %s %d", 52 (cac_timeout == -1) ? "default" : "overridden", 53 cac_timeout); 54 55 return 0; 56 } 57 58 int dfs_get_override_cac_timeout(struct wlan_dfs *dfs, int *cac_timeout) 59 { 60 if (!dfs) 61 return -EIO; 62 63 (*cac_timeout) = dfs->dfs_cac_timeout_override; 64 65 return 0; 66 } 67 68 void dfs_cac_valid_reset(struct wlan_dfs *dfs, 69 uint8_t prevchan_ieee, 70 uint32_t prevchan_flags) 71 { 72 if (dfs->dfs_cac_valid_time) { 73 if ((prevchan_ieee != dfs->dfs_curchan->dfs_ch_ieee) || 74 (prevchan_flags != dfs->dfs_curchan->dfs_ch_flags)) { 75 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 76 "Cancelling timer & clearing cac_valid" 77 ); 78 qdf_timer_stop(&dfs->dfs_cac_valid_timer); 79 dfs->dfs_cac_valid = 0; 80 } 81 } 82 } 83 84 /** 85 * dfs_cac_valid_timeout() - Timeout function for dfs_cac_valid_timer 86 * cac_valid bit will be reset in this function. 87 */ 88 static os_timer_func(dfs_cac_valid_timeout) 89 { 90 struct wlan_dfs *dfs = NULL; 91 92 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 93 dfs->dfs_cac_valid = 0; 94 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, ": Timed out!!"); 95 } 96 97 /** 98 * dfs_cac_timeout() - DFS cactimeout function. 99 * 100 * Sets dfs_cac_timer_running to 0 and dfs_cac_valid_timer. 101 */ 102 static os_timer_func(dfs_cac_timeout) 103 { 104 struct wlan_dfs *dfs = NULL; 105 106 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 107 dfs->dfs_cac_timer_running = 0; 108 109 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "cac expired, chan %d curr time %d", 110 dfs->dfs_curchan->dfs_ch_freq, 111 (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000)); 112 113 /* Once CAC is done, add channel to ETSI precacdone list*/ 114 if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) 115 dfs_add_to_etsi_precac_done_list(dfs); 116 117 /* 118 * When radar is detected during a CAC we are woken up prematurely to 119 * switch to a new channel. Check the channel to decide how to act. 120 */ 121 if (WLAN_IS_CHAN_RADAR(dfs->dfs_curchan)) { 122 dfs_mlme_mark_dfs(dfs->dfs_pdev_obj, 123 dfs->dfs_curchan->dfs_ch_ieee, 124 dfs->dfs_curchan->dfs_ch_freq, 125 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2, 126 dfs->dfs_curchan->dfs_ch_flags); 127 dfs_debug(dfs, WLAN_DEBUG_DFS, 128 "CAC timer on channel %u (%u MHz) stopped due to radar", 129 dfs->dfs_curchan->dfs_ch_ieee, 130 dfs->dfs_curchan->dfs_ch_freq); 131 } else { 132 dfs_debug(dfs, WLAN_DEBUG_DFS, 133 "CAC timer on channel %u (%u MHz) expired; no radar detected", 134 dfs->dfs_curchan->dfs_ch_ieee, 135 dfs->dfs_curchan->dfs_ch_freq); 136 137 /* On CAC completion, set the bit 'cac_valid'. 138 * CAC will not be re-done if this bit is reset. 139 * The flag will be reset when dfs_cac_valid_timer 140 * timesout. 141 */ 142 if (dfs->dfs_cac_valid_time) { 143 dfs->dfs_cac_valid = 1; 144 qdf_timer_mod(&dfs->dfs_cac_valid_timer, 145 dfs->dfs_cac_valid_time * 1000); 146 } 147 } 148 149 /* Iterate over the nodes, processing the CAC completion event. */ 150 dfs_mlme_proc_cac(dfs->dfs_pdev_obj, 0); 151 152 /* Send a CAC timeout, VAP up event to user space */ 153 dfs_mlme_deliver_event_up_after_cac(dfs->dfs_pdev_obj); 154 155 if (dfs->dfs_defer_precac_channel_change == 1) { 156 dfs_mlme_channel_change_by_precac(dfs->dfs_pdev_obj); 157 dfs->dfs_defer_precac_channel_change = 0; 158 } 159 } 160 161 void dfs_cac_timer_init(struct wlan_dfs *dfs) 162 { 163 qdf_timer_init(NULL, 164 &(dfs->dfs_cac_timer), 165 dfs_cac_timeout, 166 (void *)(dfs), 167 QDF_TIMER_TYPE_WAKE_APPS); 168 169 qdf_timer_init(NULL, 170 &(dfs->dfs_cac_valid_timer), 171 dfs_cac_valid_timeout, 172 (void *)(dfs), 173 QDF_TIMER_TYPE_WAKE_APPS); 174 } 175 176 void dfs_cac_attach(struct wlan_dfs *dfs) 177 { 178 dfs->dfs_cac_timeout_override = -1; 179 dfs->wlan_dfs_cac_time = WLAN_DFS_WAIT_MS; 180 dfs_cac_timer_init(dfs); 181 } 182 183 void dfs_cac_timer_reset(struct wlan_dfs *dfs) 184 { 185 qdf_timer_stop(&dfs->dfs_cac_timer); 186 dfs_get_override_cac_timeout(dfs, 187 &(dfs->dfs_cac_timeout_override)); 188 qdf_mem_zero(&dfs->dfs_cac_started_chan, 189 sizeof(dfs->dfs_cac_started_chan)); 190 191 } 192 193 void dfs_cac_timer_detach(struct wlan_dfs *dfs) 194 { 195 qdf_timer_free(&dfs->dfs_cac_timer); 196 197 qdf_timer_free(&dfs->dfs_cac_valid_timer); 198 dfs->dfs_cac_valid = 0; 199 } 200 201 int dfs_is_ap_cac_timer_running(struct wlan_dfs *dfs) 202 { 203 return dfs->dfs_cac_timer_running; 204 } 205 206 void dfs_start_cac_timer(struct wlan_dfs *dfs) 207 { 208 int cac_timeout = 0; 209 struct dfs_channel *chan = dfs->dfs_curchan; 210 211 cac_timeout = dfs_mlme_get_cac_timeout(dfs->dfs_pdev_obj, 212 chan->dfs_ch_freq, 213 chan->dfs_ch_vhtop_ch_freq_seg2, 214 chan->dfs_ch_flags); 215 216 dfs->dfs_cac_started_chan = *chan; 217 218 dfs_debug(dfs, WLAN_DEBUG_DFS, 219 "chan = %d cfreq2 = %d timeout = %d sec, curr_time = %d sec", 220 chan->dfs_ch_ieee, chan->dfs_ch_vhtop_ch_freq_seg2, 221 cac_timeout, 222 qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000); 223 224 qdf_timer_mod(&dfs->dfs_cac_timer, cac_timeout * 1000); 225 dfs->dfs_cac_aborted = 0; 226 } 227 228 void dfs_cancel_cac_timer(struct wlan_dfs *dfs) 229 { 230 qdf_timer_stop(&dfs->dfs_cac_timer); 231 } 232 233 void dfs_cac_stop(struct wlan_dfs *dfs) 234 { 235 uint32_t phyerr; 236 237 dfs_get_debug_info(dfs, (void *)&phyerr); 238 dfs_debug(dfs, WLAN_DEBUG_DFS, 239 "Stopping CAC Timer %d procphyerr 0x%08x", 240 dfs->dfs_curchan->dfs_ch_freq, phyerr); 241 qdf_timer_stop(&dfs->dfs_cac_timer); 242 if (dfs->dfs_cac_timer_running) 243 dfs->dfs_cac_aborted = 1; 244 dfs->dfs_cac_timer_running = 0; 245 } 246 247 void dfs_stacac_stop(struct wlan_dfs *dfs) 248 { 249 uint32_t phyerr; 250 251 dfs_get_debug_info(dfs, (void *)&phyerr); 252 dfs_debug(dfs, WLAN_DEBUG_DFS, 253 "Stopping STA CAC Timer %d procphyerr 0x%08x", 254 dfs->dfs_curchan->dfs_ch_freq, phyerr); 255 } 256 257 bool dfs_is_subset_channel(struct wlan_dfs *dfs, 258 struct dfs_channel *old_chan, 259 struct dfs_channel *new_chan) 260 { 261 uint8_t old_subchans[NUM_CHANNELS_160MHZ]; 262 uint8_t new_subchans[NUM_CHANNELS_160MHZ]; 263 uint8_t old_n_chans; 264 uint8_t new_n_chans; 265 int i = 0, j = 0; 266 bool is_found = false; 267 268 if (WLAN_IS_CHAN_11AC_VHT160(old_chan) || 269 WLAN_IS_CHAN_11AC_VHT80_80(old_chan)) { 270 /* If primary segment is NON-DFS */ 271 if (!WLAN_IS_CHAN_DFS(old_chan)) 272 old_n_chans = dfs_get_bonding_channels(dfs, 273 old_chan, 274 SEG_ID_SECONDARY, 275 old_subchans); 276 else 277 old_n_chans = dfs_get_bonding_channels_without_seg_info( 278 old_chan, old_subchans); 279 } else { 280 old_n_chans = dfs_get_bonding_channels_without_seg_info( 281 old_chan, old_subchans); 282 } 283 284 if (WLAN_IS_CHAN_11AC_VHT160(new_chan) || 285 WLAN_IS_CHAN_11AC_VHT80_80(new_chan)) { 286 /* If primary segment is NON-DFS */ 287 if (WLAN_IS_CHAN_DFS(new_chan)) 288 new_n_chans = dfs_get_bonding_channels( 289 dfs, new_chan, SEG_ID_SECONDARY, 290 new_subchans); 291 else 292 new_n_chans = dfs_get_bonding_channels_without_seg_info( 293 new_chan, new_subchans); 294 } else { 295 new_n_chans = dfs_get_bonding_channels_without_seg_info( 296 new_chan, new_subchans); 297 } 298 299 if (new_n_chans > old_n_chans) 300 return false; 301 302 for (i = 0; i < new_n_chans; i++) { 303 is_found = false; 304 for (j = 0; j < old_n_chans; j++) { 305 if (new_subchans[i] == old_subchans[j]) { 306 is_found = true; 307 break; 308 } 309 } 310 311 /* If new_subchans[i] is not found in old_subchans, then, 312 * new_chan is not subset of old_chan. 313 */ 314 if (!is_found) 315 break; 316 } 317 318 return is_found; 319 } 320 321 bool dfs_is_curchan_subset_of_cac_started_chan(struct wlan_dfs *dfs) 322 { 323 return dfs_is_subset_channel(dfs, &dfs->dfs_cac_started_chan, 324 dfs->dfs_curchan); 325 } 326 327 void dfs_clear_cac_started_chan(struct wlan_dfs *dfs) 328 { 329 qdf_mem_zero(&dfs->dfs_cac_started_chan, 330 sizeof(dfs->dfs_cac_started_chan)); 331 } 332 333 bool dfs_check_for_cac_start(struct wlan_dfs *dfs, 334 bool *continue_current_cac) 335 { 336 if (dfs->dfs_ignore_dfs || dfs->dfs_cac_valid || dfs->dfs_ignore_cac) { 337 dfs_debug(dfs, WLAN_DEBUG_DFS, 338 "Skip CAC, ignore_dfs = %d cac_valid = %d ignore_cac = %d", 339 dfs->dfs_ignore_dfs, dfs->dfs_cac_valid, 340 dfs->dfs_ignore_cac); 341 return false; 342 } 343 344 if (dfs_is_etsi_precac_done(dfs)) { 345 dfs_debug(dfs, WLAN_DEBUG_DFS, 346 "ETSI PRE-CAC alreay done on this channel %d", 347 dfs->dfs_curchan->dfs_ch_ieee); 348 return false; 349 } 350 351 /* If the channel has completed PRE-CAC then CAC can be skipped here. */ 352 if (dfs_is_precac_done(dfs, dfs->dfs_curchan)) { 353 dfs_debug(dfs, WLAN_DEBUG_DFS, 354 "PRE-CAC alreay done on this channel %d", 355 dfs->dfs_curchan->dfs_ch_ieee); 356 return false; 357 } 358 359 if (dfs_is_ap_cac_timer_running(dfs)) { 360 /* Check if we should continue the existing CAC or 361 * cancel the existing CAC. 362 * For example: - if an existing VAP(0) is already in 363 * DFS wait state (which means the radio(wifi) is 364 * running the CAC) and it is in channel A and another 365 * VAP(1) comes up in the same channel then instead of 366 * cancelling the CAC we can let the CAC continue. 367 */ 368 if (dfs_is_curchan_subset_of_cac_started_chan(dfs)) { 369 *continue_current_cac = true; 370 } else { 371 /* New CAC is needed, cancel the running CAC 372 * timer. 373 * 1) When AP is in DFS_WAIT state and it is in 374 * channel A and user restarts the AP vap in 375 * channel B, then cancel the running CAC in 376 * channel A and start new CAC in channel B. 377 * 378 * 2) When AP detects the RADAR during CAC in 379 * channel A, it cancels the running CAC and 380 * tries to find channel B with the reduced 381 * bandwidth with of channel A. 382 * In this case, since the CAC is aborted by 383 * the RADAR, AP should start the CAC again. 384 */ 385 dfs_cancel_cac_timer(dfs); 386 } 387 } else { /* CAC timer is not running. */ 388 if (dfs_is_curchan_subset_of_cac_started_chan(dfs)) { 389 /* AP bandwidth reduce case: 390 * When AP detects the RADAR in in-service monitoring 391 * mode in channel A, it cancels the running CAC and 392 * tries to find the channel B with the reduced 393 * bandwidth of channel A. 394 * If the new channel B is subset of the channel A 395 * then AP skips the CAC. 396 */ 397 if (!dfs->dfs_cac_aborted) { 398 dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC"); 399 return false; 400 } 401 } 402 } 403 404 return true; 405 } 406