1 /* 2 * Copyright (c) 2016-2021 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 <wlan_objmgr_vdev_obj.h> 34 #include "wlan_dfs_utils_api.h" 35 #include "wlan_dfs_mlme_api.h" 36 #include "../dfs_internal.h" 37 #include "../dfs_process_radar_found_ind.h" 38 39 #define IS_CHANNEL_WEATHER_RADAR(freq) ((freq >= 5600) && (freq <= 5650)) 40 #define ADJACENT_WEATHER_RADAR_CHANNEL 5580 41 #define CH100_START_FREQ 5490 42 #define CH100 100 43 44 /** 45 * dfs_cac_valid_timeout() - Timeout function for dfs_cac_valid_timer 46 * cac_valid bit will be reset in this function. 47 */ 48 static os_timer_func(dfs_cac_valid_timeout) 49 { 50 struct wlan_dfs *dfs = NULL; 51 52 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 53 dfs->dfs_cac_valid = 0; 54 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, ": Timed out!!"); 55 } 56 57 /** 58 * dfs_clear_cac_started_chan() - Clear dfs cac started channel. 59 * @dfs: Pointer to wlan_dfs structure. 60 */ 61 void dfs_clear_cac_started_chan(struct wlan_dfs *dfs) 62 { 63 qdf_mem_zero(&dfs->dfs_cac_started_chan, 64 sizeof(dfs->dfs_cac_started_chan)); 65 } 66 67 void dfs_process_cac_completion(struct wlan_dfs *dfs) 68 { 69 enum phy_ch_width ch_width = CH_WIDTH_INVALID; 70 uint16_t primary_chan_freq = 0, sec_chan_freq = 0; 71 struct dfs_channel *dfs_curchan; 72 73 dfs->dfs_cac_timer_running = 0; 74 dfs_curchan = dfs->dfs_curchan; 75 76 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "cac expired, chan %d cur time %d", 77 dfs->dfs_curchan->dfs_ch_freq, 78 (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000)); 79 80 /* 81 * When radar is detected during a CAC we are woken up prematurely to 82 * switch to a new channel. Check the channel to decide how to act. 83 */ 84 if (WLAN_IS_CHAN_RADAR(dfs, dfs->dfs_curchan)) { 85 dfs_mlme_mark_dfs(dfs->dfs_pdev_obj, 86 dfs_curchan->dfs_ch_ieee, 87 dfs_curchan->dfs_ch_freq, 88 dfs_curchan->dfs_ch_mhz_freq_seg2, 89 dfs_curchan->dfs_ch_flags); 90 dfs_debug(dfs, WLAN_DEBUG_DFS, 91 "CAC timer on chan %u (%u MHz) stopped due to radar", 92 dfs_curchan->dfs_ch_ieee, 93 dfs_curchan->dfs_ch_freq); 94 } else { 95 dfs_debug(dfs, WLAN_DEBUG_DFS, 96 "CAC timer on channel %u (%u MHz) expired;" 97 "no radar detected", 98 dfs_curchan->dfs_ch_ieee, 99 dfs_curchan->dfs_ch_freq); 100 101 /* On CAC completion, set the bit 'cac_valid'. 102 * CAC will not be re-done if this bit is reset. 103 * The flag will be reset when dfs_cac_valid_timer 104 * timesout. 105 */ 106 if (dfs->dfs_cac_valid_time) { 107 dfs->dfs_cac_valid = 1; 108 qdf_timer_mod(&dfs->dfs_cac_valid_timer, 109 dfs->dfs_cac_valid_time * 1000); 110 } 111 112 dfs_find_curchwidth_and_center_chan_for_freq(dfs, 113 &ch_width, 114 &primary_chan_freq, 115 &sec_chan_freq); 116 117 /* ETSI allows the driver to cache the CAC ( Once CAC done, 118 * it can be used in future). 119 * Therefore mark the current channel CAC done. 120 */ 121 if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) 122 dfs_mark_precac_done_for_freq(dfs, 123 primary_chan_freq, 124 sec_chan_freq, 125 ch_width); 126 } 127 128 dfs_clear_cac_started_chan(dfs); 129 /* Iterate over the nodes, processing the CAC completion event. */ 130 dfs_mlme_proc_cac(dfs->dfs_pdev_obj, 0); 131 132 /* Send a CAC timeout, VAP up event to user space */ 133 dfs_mlme_deliver_event_up_after_cac(dfs->dfs_pdev_obj); 134 135 if (dfs->dfs_defer_precac_channel_change == 1) { 136 dfs_mlme_channel_change_by_precac(dfs->dfs_pdev_obj); 137 dfs->dfs_defer_precac_channel_change = 0; 138 } 139 } 140 141 /** 142 * dfs_cac_timeout() - DFS cactimeout function. 143 * 144 * Sets dfs_cac_timer_running to 0 and dfs_cac_valid_timer. 145 */ 146 #ifdef CONFIG_CHAN_FREQ_API 147 static os_timer_func(dfs_cac_timeout) 148 { 149 struct wlan_dfs *dfs = NULL; 150 151 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 152 153 if (dfs_is_hw_mode_switch_in_progress(dfs)) 154 dfs->dfs_defer_params.is_cac_completed = true; 155 else 156 dfs_process_cac_completion(dfs); 157 } 158 #endif 159 160 #ifdef QCA_SUPPORT_DFS_CAC 161 void dfs_cac_timer_attach(struct wlan_dfs *dfs) 162 { 163 dfs->dfs_cac_timeout_override = -1; 164 dfs->wlan_dfs_cac_time = WLAN_DFS_WAIT_MS; 165 qdf_timer_init(NULL, 166 &(dfs->dfs_cac_timer), 167 dfs_cac_timeout, 168 (void *)(dfs), 169 QDF_TIMER_TYPE_WAKE_APPS); 170 171 qdf_timer_init(NULL, 172 &(dfs->dfs_cac_valid_timer), 173 dfs_cac_valid_timeout, 174 (void *)(dfs), 175 QDF_TIMER_TYPE_WAKE_APPS); 176 } 177 178 void dfs_cac_timer_reset(struct wlan_dfs *dfs) 179 { 180 qdf_timer_stop(&dfs->dfs_cac_timer); 181 dfs_get_override_cac_timeout(dfs, 182 &(dfs->dfs_cac_timeout_override)); 183 dfs_clear_cac_started_chan(dfs); 184 } 185 186 void dfs_cac_timer_detach(struct wlan_dfs *dfs) 187 { 188 qdf_timer_free(&dfs->dfs_cac_timer); 189 190 qdf_timer_free(&dfs->dfs_cac_valid_timer); 191 dfs->dfs_cac_valid = 0; 192 } 193 194 int dfs_is_ap_cac_timer_running(struct wlan_dfs *dfs) 195 { 196 return dfs->dfs_cac_timer_running; 197 } 198 199 #ifdef CONFIG_CHAN_FREQ_API 200 void dfs_start_cac_timer(struct wlan_dfs *dfs) 201 { 202 int cac_timeout = 0; 203 struct dfs_channel *chan = dfs->dfs_curchan; 204 205 cac_timeout = 206 dfs_mlme_get_cac_timeout_for_freq(dfs->dfs_pdev_obj, 207 chan->dfs_ch_freq, 208 chan->dfs_ch_mhz_freq_seg2, 209 chan->dfs_ch_flags); 210 211 dfs->dfs_cac_started_chan = *chan; 212 213 dfs_debug(dfs, WLAN_DEBUG_DFS, 214 "chan = %d cfreq2 = %d timeout = %d sec, curr_time = %d sec", 215 chan->dfs_ch_ieee, chan->dfs_ch_vhtop_ch_freq_seg2, 216 cac_timeout, 217 qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000); 218 219 qdf_timer_mod(&dfs->dfs_cac_timer, cac_timeout * 1000); 220 dfs->dfs_cac_aborted = 0; 221 } 222 #endif 223 224 void dfs_cancel_cac_timer(struct wlan_dfs *dfs) 225 { 226 qdf_timer_stop(&dfs->dfs_cac_timer); 227 dfs_clear_cac_started_chan(dfs); 228 } 229 230 void dfs_cac_stop(struct wlan_dfs *dfs) 231 { 232 uint32_t phyerr; 233 234 dfs_get_debug_info(dfs, (void *)&phyerr); 235 dfs_debug(dfs, WLAN_DEBUG_DFS, 236 "Stopping CAC Timer %d procphyerr 0x%08x", 237 dfs->dfs_curchan->dfs_ch_freq, phyerr); 238 qdf_timer_stop(&dfs->dfs_cac_timer); 239 if (dfs->dfs_cac_timer_running) 240 dfs->dfs_cac_aborted = 1; 241 dfs_clear_cac_started_chan(dfs); 242 dfs->dfs_cac_timer_running = 0; 243 } 244 245 void dfs_stacac_stop(struct wlan_dfs *dfs) 246 { 247 uint32_t phyerr; 248 249 dfs_get_debug_info(dfs, (void *)&phyerr); 250 dfs_debug(dfs, WLAN_DEBUG_DFS, 251 "Stopping STA CAC Timer %d procphyerr 0x%08x", 252 dfs->dfs_curchan->dfs_ch_freq, phyerr); 253 dfs_clear_cac_started_chan(dfs); 254 } 255 256 int dfs_override_cac_timeout(struct wlan_dfs *dfs, int cac_timeout) 257 { 258 if (!dfs) 259 return -EIO; 260 261 dfs->dfs_cac_timeout_override = cac_timeout; 262 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "CAC timeout is now %s %d", 263 (cac_timeout == -1) ? "default" : "overridden", 264 cac_timeout); 265 266 return 0; 267 } 268 269 int dfs_get_override_cac_timeout(struct wlan_dfs *dfs, int *cac_timeout) 270 { 271 if (!dfs) 272 return -EIO; 273 274 (*cac_timeout) = dfs->dfs_cac_timeout_override; 275 276 return 0; 277 } 278 279 #ifdef CONFIG_CHAN_FREQ_API 280 void dfs_cac_valid_reset_for_freq(struct wlan_dfs *dfs, 281 uint16_t prevchan_freq, 282 uint32_t prevchan_flags) 283 { 284 if (dfs->dfs_cac_valid_time) { 285 if ((prevchan_freq != dfs->dfs_curchan->dfs_ch_freq) || 286 (prevchan_flags != dfs->dfs_curchan->dfs_ch_flags)) { 287 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 288 "Cancelling timer & clearing cac_valid"); 289 qdf_timer_stop(&dfs->dfs_cac_valid_timer); 290 dfs->dfs_cac_valid = 0; 291 } 292 } 293 } 294 #endif 295 #endif 296 297 /* 298 * dfs_is_subset_channel_for_freq() - Find out if prev channel and current 299 * channel are subsets of each other. 300 * @old_subchans_freq: Pointer to previous sub-channels freq. 301 * @old_n_chans: Number of previous sub-channels. 302 * @new_subchans_freq: Pointer to new sub-channels freq. 303 * @new_n_chans: Number of new sub-channels 304 */ 305 #ifdef CONFIG_CHAN_FREQ_API 306 static bool 307 dfs_is_subset_channel_for_freq(uint16_t *old_subchans_freq, 308 uint8_t old_n_chans, 309 uint16_t *new_subchans_freq, 310 uint8_t new_n_chans) 311 { 312 bool is_found; 313 int i, j; 314 315 if (!new_n_chans) 316 return true; 317 318 if (new_n_chans > old_n_chans) 319 return false; 320 321 for (i = 0; i < new_n_chans; i++) { 322 is_found = false; 323 for (j = 0; j < old_n_chans; j++) { 324 if (new_subchans_freq[i] == old_subchans_freq[j]) { 325 is_found = true; 326 break; 327 } 328 } 329 330 /* If new_subchans[i] is not found in old_subchans, then, 331 * new_chan is not subset of old_chan. 332 */ 333 if (!is_found) 334 break; 335 } 336 337 return is_found; 338 } 339 #endif 340 341 #ifdef CONFIG_CHAN_FREQ_API 342 uint8_t 343 dfs_find_dfs_sub_channels_for_freq(struct wlan_dfs *dfs, 344 struct dfs_channel *chan, 345 uint16_t *subchan_arr) 346 { 347 if (WLAN_IS_CHAN_MODE_160(chan) || WLAN_IS_CHAN_MODE_80_80(chan)) { 348 if (WLAN_IS_CHAN_DFS(chan) && WLAN_IS_CHAN_DFS_CFREQ2(chan)) 349 return dfs_get_bonding_channel_without_seg_info_for_freq 350 (chan, subchan_arr); 351 if (WLAN_IS_CHAN_DFS(chan)) 352 return dfs_get_bonding_channels_for_freq(dfs, 353 chan, 354 SEG_ID_PRIMARY, 355 DETECTOR_ID_0, 356 subchan_arr); 357 if (WLAN_IS_CHAN_DFS_CFREQ2(chan)) 358 return dfs_get_bonding_channels_for_freq 359 (dfs, chan, SEG_ID_SECONDARY, 360 DETECTOR_ID_0, subchan_arr); 361 /* All channels in 160/80_80 BW are non DFS, return 0 362 * as number of subchannels 363 */ 364 return 0; 365 } else if (WLAN_IS_CHAN_DFS(chan)) { 366 return dfs_get_bonding_channel_without_seg_info_for_freq 367 (chan, subchan_arr); 368 } 369 /* All channels are non DFS, return 0 as number of subchannels*/ 370 return 0; 371 } 372 #endif 373 374 #ifdef CONFIG_CHAN_FREQ_API 375 bool 376 dfs_is_new_chan_subset_of_old_chan(struct wlan_dfs *dfs, 377 struct dfs_channel *new_chan, 378 struct dfs_channel *old_chan) 379 { 380 uint16_t new_subchans[NUM_CHANNELS_160MHZ]; 381 uint16_t old_subchans[NUM_CHANNELS_160MHZ]; 382 uint8_t n_new_subchans = 0; 383 uint8_t n_old_subchans = 0; 384 385 /* Given channel is the old channel. i.e. The channel which 386 * should have the new channel as subset. 387 */ 388 n_old_subchans = dfs_find_dfs_sub_channels_for_freq(dfs, old_chan, 389 old_subchans); 390 /* cur_chan is the new channel to be check if subset of old channel */ 391 n_new_subchans = dfs_find_dfs_sub_channels_for_freq(dfs, new_chan, 392 new_subchans); 393 394 return dfs_is_subset_channel_for_freq(old_subchans, 395 n_old_subchans, 396 new_subchans, 397 n_new_subchans); 398 } 399 #endif 400 401 #ifdef QCA_SUPPORT_DFS_CAC 402 bool dfs_is_cac_required(struct wlan_dfs *dfs, 403 struct dfs_channel *cur_chan, 404 struct dfs_channel *prev_chan, 405 bool *continue_current_cac, 406 bool is_vap_restart) 407 { 408 struct dfs_channel *cac_started_chan = &dfs->dfs_cac_started_chan; 409 410 if (!WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(cur_chan)) { 411 dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC on non-DFS channel"); 412 return false; 413 } 414 415 if (dfs->dfs_ignore_dfs || dfs->dfs_cac_valid || dfs->dfs_ignore_cac) { 416 dfs_debug(dfs, WLAN_DEBUG_DFS, 417 "Skip CAC, ignore_dfs = %d cac_valid = %d ignore_cac = %d", 418 dfs->dfs_ignore_dfs, dfs->dfs_cac_valid, 419 dfs->dfs_ignore_cac); 420 return false; 421 } 422 423 /* If the channel has completed PRE-CAC then CAC can be skipped here. */ 424 if (dfs_is_precac_done(dfs, cur_chan)) { 425 dfs_debug(dfs, WLAN_DEBUG_DFS, 426 "PRE-CAC alreay done on this channel %d", 427 cur_chan->dfs_ch_ieee); 428 return false; 429 } 430 431 if (dfs_is_ap_cac_timer_running(dfs)) { 432 /* Check if we should continue the existing CAC or 433 * cancel the existing CAC. 434 * For example: - if an existing VAP(0) is already in 435 * DFS wait state (which means the radio(wifi) is 436 * running the CAC) and it is in channel A and another 437 * VAP(1) comes up in the same channel then instead of 438 * cancelling the CAC we can let the CAC continue. 439 */ 440 if (dfs_is_new_chan_subset_of_old_chan(dfs, 441 cur_chan, 442 cac_started_chan)) { 443 *continue_current_cac = true; 444 } else { 445 /* New CAC is needed, cancel the running CAC 446 * timer. 447 * 1) When AP is in DFS_WAIT state and it is in 448 * channel A and user restarts the AP vap in 449 * channel B, then cancel the running CAC in 450 * channel A and start new CAC in channel B. 451 * 452 * 2) When AP detects the RADAR during CAC in 453 * channel A, it cancels the running CAC and 454 * tries to find channel B with the reduced 455 * bandwidth with of channel A. 456 * In this case, since the CAC is aborted by 457 * the RADAR, AP should start the CAC again. 458 */ 459 dfs_cancel_cac_timer(dfs); 460 } 461 } else { /* CAC timer is not running. */ 462 /* If channel change happens via VAP DOWN/UP on subset channels, 463 * (eg: from 52 HT80 to 64 HT80) CAC done information 464 * (of 52 HT80) based on subset logic 465 * (as 52 and 64 HT80 are subsets of each other) 466 * is not expected to be preserved as VAP has come up 467 * from DOWN state. Hence do not skip CAC on 64 HT80. 468 * is_vap_restart flag is used as an identifer to indicate if 469 * vap has come up from a DOWN state or UP state (vap restart). 470 */ 471 if (!is_vap_restart) { 472 dfs_debug(dfs, WLAN_DEBUG_DFS, "CAC is needed"); 473 return true; 474 } 475 if (dfs_is_new_chan_subset_of_old_chan(dfs, 476 cur_chan, 477 prev_chan)) { 478 /* AP bandwidth reduce case: 479 * When AP detects the RADAR in in-service monitoring 480 * mode in channel A, it cancels the running CAC and 481 * tries to find the channel B with the reduced 482 * bandwidth of channel A. 483 * If the new channel B is subset of the channel A 484 * then AP skips the CAC. 485 */ 486 if (!dfs->dfs_cac_aborted) { 487 dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC"); 488 return false; 489 } 490 } 491 } 492 493 return true; 494 } 495 #endif 496