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 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /** 29 * DOC: This file has the functions related to DFS CAC. 30 */ 31 32 #include "../dfs_channel.h" 33 #include "../dfs_zero_cac.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 /** 46 * dfs_cac_valid_timeout() - Timeout function for dfs_cac_valid_timer 47 * cac_valid bit will be reset in this function. 48 */ 49 static os_timer_func(dfs_cac_valid_timeout) 50 { 51 struct wlan_dfs *dfs = NULL; 52 53 OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); 54 dfs->dfs_cac_valid = 0; 55 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, ": Timed out!!"); 56 } 57 58 /** 59 * dfs_clear_cac_started_chan() - Clear dfs cac started channel. 60 * @dfs: Pointer to wlan_dfs structure. 61 */ 62 void dfs_clear_cac_started_chan(struct wlan_dfs *dfs) 63 { 64 qdf_mem_zero(&dfs->dfs_cac_started_chan, 65 sizeof(dfs->dfs_cac_started_chan)); 66 } 67 68 static void dfs_clear_nol_history_for_curchan(struct wlan_dfs *dfs) 69 { 70 struct dfs_channel *chan = dfs->dfs_curchan; 71 uint16_t sub_channels[MAX_20MHZ_SUBCHANS]; 72 uint8_t num_subchs; 73 74 num_subchs = dfs_get_bonding_channel_without_seg_info_for_freq( 75 chan, sub_channels); 76 77 if (dfs->dfs_is_stadfs_enabled) 78 if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj)) 79 utils_dfs_reg_update_nol_history_chan_for_freq( 80 dfs->dfs_pdev_obj, sub_channels, 81 num_subchs, DFS_NOL_HISTORY_RESET); 82 } 83 84 void dfs_process_cac_completion(void *context) 85 { 86 struct wlan_dfs *dfs = (struct wlan_dfs *)context; 87 enum phy_ch_width ch_width = CH_WIDTH_INVALID; 88 uint16_t primary_chan_freq = 0, sec_chan_freq = 0; 89 struct dfs_channel *dfs_curchan; 90 91 dfs->dfs_cac_timer_running = 0; 92 dfs_curchan = dfs->dfs_curchan; 93 94 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "cac expired, chan %d cur time %d", 95 dfs->dfs_curchan->dfs_ch_freq, 96 (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000)); 97 98 /* 99 * When radar is detected during a CAC we are woken up prematurely to 100 * switch to a new channel. Check the channel to decide how to act. 101 */ 102 if (WLAN_IS_CHAN_RADAR(dfs, dfs->dfs_curchan)) { 103 dfs_mlme_mark_dfs(dfs->dfs_pdev_obj, 104 dfs_curchan->dfs_ch_ieee, 105 dfs_curchan->dfs_ch_freq, 106 dfs_curchan->dfs_ch_mhz_freq_seg2, 107 dfs_curchan->dfs_ch_flags, 108 0); 109 dfs_debug(dfs, WLAN_DEBUG_DFS, 110 "CAC timer on chan %u (%u MHz) stopped due to radar", 111 dfs_curchan->dfs_ch_ieee, 112 dfs_curchan->dfs_ch_freq); 113 } else { 114 dfs_debug(dfs, WLAN_DEBUG_DFS, 115 "CAC timer on channel %u (%u MHz) expired;" 116 "no radar detected", 117 dfs_curchan->dfs_ch_ieee, 118 dfs_curchan->dfs_ch_freq); 119 120 /* On CAC completion, set the bit 'cac_valid'. 121 * CAC will not be re-done if this bit is reset. 122 * The flag will be reset when dfs_cac_valid_timer 123 * timesout. 124 */ 125 if (dfs->dfs_cac_valid_time) { 126 dfs->dfs_cac_valid = 1; 127 qdf_timer_mod(&dfs->dfs_cac_valid_timer, 128 dfs->dfs_cac_valid_time * 1000); 129 } 130 131 dfs_find_curchwidth_and_center_chan_for_freq(dfs, 132 &ch_width, 133 &primary_chan_freq, 134 &sec_chan_freq); 135 136 /* ETSI allows the driver to cache the CAC ( Once CAC done, 137 * it can be used in future). 138 * Therefore mark the current channel CAC done. 139 */ 140 if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) 141 dfs_mark_precac_done_for_freq(dfs, 142 primary_chan_freq, 143 sec_chan_freq, 144 ch_width); 145 } 146 147 dfs_clear_cac_started_chan(dfs); 148 149 /* Clear NOL history for current channel on successful CAC completion */ 150 dfs_clear_nol_history_for_curchan(dfs); 151 /* Iterate over the nodes, processing the CAC completion event. */ 152 dfs_mlme_proc_cac(dfs->dfs_pdev_obj, 0); 153 154 /* Send a CAC timeout, VAP up event to user space */ 155 dfs_mlme_deliver_event_up_after_cac(dfs->dfs_pdev_obj); 156 157 if (dfs->dfs_defer_precac_channel_change == 1) { 158 dfs_mlme_channel_change_by_precac(dfs->dfs_pdev_obj); 159 dfs->dfs_defer_precac_channel_change = 0; 160 } 161 } 162 163 /** 164 * dfs_cac_timeout() - DFS cactimeout function. 165 * 166 * Sets dfs_cac_timer_running to 0 and dfs_cac_valid_timer. 167 */ 168 #ifdef CONFIG_CHAN_FREQ_API 169 static enum qdf_hrtimer_restart_status 170 dfs_cac_timeout(qdf_hrtimer_data_t *arg) 171 { 172 struct wlan_dfs *dfs; 173 174 dfs = container_of(arg, struct wlan_dfs, dfs_cac_timer); 175 176 if (dfs_is_hw_mode_switch_in_progress(dfs)) 177 dfs->dfs_defer_params.is_cac_completed = true; 178 else 179 qdf_sched_work(NULL, &dfs->dfs_cac_completion_work); 180 181 return QDF_HRTIMER_NORESTART; 182 } 183 #endif 184 185 #ifdef QCA_SUPPORT_DFS_CAC 186 void dfs_cac_timer_attach(struct wlan_dfs *dfs) 187 { 188 dfs->dfs_cac_timeout_override = -1; 189 dfs->wlan_dfs_cac_time = WLAN_DFS_WAIT_MS; 190 qdf_hrtimer_init(&dfs->dfs_cac_timer, 191 dfs_cac_timeout, 192 QDF_CLOCK_MONOTONIC, 193 QDF_HRTIMER_MODE_REL, 194 QDF_CONTEXT_HARDWARE); 195 qdf_create_work(NULL, 196 &dfs->dfs_cac_completion_work, 197 dfs_process_cac_completion, 198 dfs); 199 qdf_timer_init(NULL, 200 &(dfs->dfs_cac_valid_timer), 201 dfs_cac_valid_timeout, 202 (void *)(dfs), 203 QDF_TIMER_TYPE_WAKE_APPS); 204 } 205 206 void dfs_cac_timer_reset(struct wlan_dfs *dfs) 207 { 208 qdf_hrtimer_cancel(&dfs->dfs_cac_timer); 209 qdf_flush_work(&dfs->dfs_cac_completion_work); 210 dfs_get_override_cac_timeout(dfs, 211 &(dfs->dfs_cac_timeout_override)); 212 dfs_clear_cac_started_chan(dfs); 213 } 214 215 void dfs_cac_timer_detach(struct wlan_dfs *dfs) 216 { 217 qdf_hrtimer_kill(&dfs->dfs_cac_timer); 218 qdf_flush_work(&dfs->dfs_cac_completion_work); 219 qdf_destroy_work(NULL, &dfs->dfs_cac_completion_work); 220 qdf_timer_free(&dfs->dfs_cac_valid_timer); 221 dfs->dfs_cac_valid = 0; 222 } 223 224 int dfs_is_ap_cac_timer_running(struct wlan_dfs *dfs) 225 { 226 return dfs->dfs_cac_timer_running; 227 } 228 229 #ifdef CONFIG_CHAN_FREQ_API 230 void dfs_start_cac_timer(struct wlan_dfs *dfs) 231 { 232 int cac_timeout = 0; 233 struct dfs_channel *chan = dfs->dfs_curchan; 234 235 cac_timeout = 236 dfs_mlme_get_cac_timeout_for_freq(dfs->dfs_pdev_obj, 237 chan->dfs_ch_freq, 238 chan->dfs_ch_mhz_freq_seg2, 239 chan->dfs_ch_flags); 240 241 dfs->dfs_cac_started_chan = *chan; 242 243 dfs_deliver_cac_state_events(dfs); 244 dfs_debug(dfs, WLAN_DEBUG_DFS, 245 "chan = %d cfreq2 = %d timeout = %d sec, curr_time = %d sec", 246 chan->dfs_ch_ieee, chan->dfs_ch_vhtop_ch_freq_seg2, 247 cac_timeout, 248 qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000); 249 250 qdf_hrtimer_start(&dfs->dfs_cac_timer, 251 qdf_time_ms_to_ktime(cac_timeout * 1000), 252 QDF_HRTIMER_MODE_REL); 253 dfs->dfs_cac_aborted = 0; 254 } 255 #endif 256 257 void dfs_cancel_cac_timer(struct wlan_dfs *dfs) 258 { 259 qdf_hrtimer_cancel(&dfs->dfs_cac_timer); 260 dfs_clear_cac_started_chan(dfs); 261 } 262 263 void dfs_send_dfs_events_for_chan(struct wlan_dfs *dfs, 264 struct dfs_channel *chan, 265 enum WLAN_DFS_EVENTS event) 266 { 267 uint8_t nchannels, i; 268 qdf_freq_t freq_list[MAX_20MHZ_SUBCHANS]; 269 270 nchannels = 271 dfs_get_bonding_channel_without_seg_info_for_freq(chan, 272 freq_list); 273 for (i = 0; i < nchannels; i++) 274 utils_dfs_deliver_event(dfs->dfs_pdev_obj, 275 freq_list[i], 276 event); 277 } 278 279 void dfs_cac_stop(struct wlan_dfs *dfs) 280 { 281 uint32_t phyerr; 282 struct dfs_channel *chan; 283 284 chan = &dfs->dfs_cac_started_chan; 285 dfs_get_debug_info(dfs, (void *)&phyerr); 286 dfs_debug(dfs, WLAN_DEBUG_DFS, 287 "Stopping CAC Timer %d procphyerr 0x%08x", 288 dfs->dfs_curchan->dfs_ch_freq, phyerr); 289 qdf_hrtimer_cancel(&dfs->dfs_cac_timer); 290 291 dfs_send_dfs_events_for_chan(dfs, chan, WLAN_EV_CAC_RESET); 292 293 if (dfs->dfs_cac_timer_running) 294 dfs->dfs_cac_aborted = 1; 295 dfs_clear_cac_started_chan(dfs); 296 dfs->dfs_cac_timer_running = 0; 297 } 298 299 void dfs_stacac_stop(struct wlan_dfs *dfs) 300 { 301 uint32_t phyerr; 302 303 dfs_get_debug_info(dfs, (void *)&phyerr); 304 dfs_debug(dfs, WLAN_DEBUG_DFS, 305 "Stopping STA CAC Timer %d procphyerr 0x%08x", 306 dfs->dfs_curchan->dfs_ch_freq, phyerr); 307 dfs_clear_cac_started_chan(dfs); 308 } 309 310 int dfs_override_cac_timeout(struct wlan_dfs *dfs, int cac_timeout) 311 { 312 if (!dfs) 313 return -EIO; 314 315 dfs->dfs_cac_timeout_override = cac_timeout; 316 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "CAC timeout is now %s %d", 317 (cac_timeout == -1) ? "default" : "overridden", 318 cac_timeout); 319 320 return 0; 321 } 322 323 int dfs_get_override_cac_timeout(struct wlan_dfs *dfs, int *cac_timeout) 324 { 325 if (!dfs) 326 return -EIO; 327 328 (*cac_timeout) = dfs->dfs_cac_timeout_override; 329 330 return 0; 331 } 332 333 #ifdef CONFIG_CHAN_FREQ_API 334 void dfs_cac_valid_reset_for_freq(struct wlan_dfs *dfs, 335 uint16_t prevchan_freq, 336 uint32_t prevchan_flags) 337 { 338 if (dfs->dfs_cac_valid_time) { 339 if ((prevchan_freq != dfs->dfs_curchan->dfs_ch_freq) || 340 (prevchan_flags != dfs->dfs_curchan->dfs_ch_flags)) { 341 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 342 "Cancelling timer & clearing cac_valid"); 343 qdf_timer_stop(&dfs->dfs_cac_valid_timer); 344 dfs->dfs_cac_valid = 0; 345 } 346 } 347 } 348 #endif 349 #endif 350 351 #ifdef CONFIG_CHAN_FREQ_API 352 bool 353 dfs_is_subset_channel_for_freq(uint16_t *old_subchans_freq, 354 uint8_t old_n_chans, 355 uint16_t *new_subchans_freq, 356 uint8_t new_n_chans) 357 { 358 bool is_found; 359 int i, j; 360 361 if (!new_n_chans) 362 return true; 363 364 if (new_n_chans > old_n_chans) 365 return false; 366 367 for (i = 0; i < new_n_chans; i++) { 368 is_found = false; 369 for (j = 0; j < old_n_chans; j++) { 370 if (new_subchans_freq[i] == old_subchans_freq[j]) { 371 is_found = true; 372 break; 373 } 374 } 375 376 /* If new_subchans[i] is not found in old_subchans, then, 377 * new_chan is not subset of old_chan. 378 */ 379 if (!is_found) 380 break; 381 } 382 383 return is_found; 384 } 385 #endif 386 387 #ifdef CONFIG_CHAN_FREQ_API 388 uint8_t 389 dfs_find_dfs_sub_channels_for_freq(struct wlan_dfs *dfs, 390 struct dfs_channel *chan, 391 uint16_t *subchan_arr) 392 { 393 if (WLAN_IS_CHAN_MODE_160(chan) || WLAN_IS_CHAN_MODE_80_80(chan)) { 394 if (WLAN_IS_CHAN_DFS(chan) && WLAN_IS_CHAN_DFS_CFREQ2(chan)) 395 return dfs_get_bonding_channel_without_seg_info_for_freq 396 (chan, subchan_arr); 397 if (WLAN_IS_CHAN_DFS(chan)) 398 return dfs_get_bonding_channels_for_freq(dfs, 399 chan, 400 SEG_ID_PRIMARY, 401 DETECTOR_ID_0, 402 subchan_arr); 403 if (WLAN_IS_CHAN_DFS_CFREQ2(chan)) 404 return dfs_get_bonding_channels_for_freq 405 (dfs, chan, SEG_ID_SECONDARY, 406 DETECTOR_ID_0, subchan_arr); 407 /* All channels in 160/80_80 BW are non DFS, return 0 408 * as number of subchannels 409 */ 410 return 0; 411 } else if (WLAN_IS_CHAN_DFS(chan)) { 412 return dfs_get_bonding_channel_without_seg_info_for_freq 413 (chan, subchan_arr); 414 } 415 /* All channels are non DFS, return 0 as number of subchannels*/ 416 return 0; 417 } 418 #endif 419 420 #ifdef CONFIG_CHAN_FREQ_API 421 bool 422 dfs_is_new_chan_subset_of_old_chan(struct wlan_dfs *dfs, 423 struct dfs_channel *new_chan, 424 struct dfs_channel *old_chan) 425 { 426 uint16_t new_subchans[MAX_20MHZ_SUBCHANS]; 427 uint16_t old_subchans[MAX_20MHZ_SUBCHANS]; 428 uint8_t n_new_subchans = 0; 429 uint8_t n_old_subchans = 0; 430 431 /* Given channel is the old channel. i.e. The channel which 432 * should have the new channel as subset. 433 */ 434 n_old_subchans = dfs_find_dfs_sub_channels_for_freq(dfs, old_chan, 435 old_subchans); 436 /* cur_chan is the new channel to be check if subset of old channel */ 437 n_new_subchans = dfs_find_dfs_sub_channels_for_freq(dfs, new_chan, 438 new_subchans); 439 440 return dfs_is_subset_channel_for_freq(old_subchans, 441 n_old_subchans, 442 new_subchans, 443 n_new_subchans); 444 } 445 #endif 446 447 #ifdef QCA_SUPPORT_DFS_CAC 448 bool dfs_is_cac_required(struct wlan_dfs *dfs, 449 struct dfs_channel *cur_chan, 450 struct dfs_channel *prev_chan, 451 bool *continue_current_cac, 452 bool is_vap_restart) 453 { 454 struct dfs_channel *cac_started_chan = &dfs->dfs_cac_started_chan; 455 456 if (!WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(cur_chan)) { 457 dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC on non-DFS channel"); 458 return false; 459 } 460 461 if (dfs->dfs_ignore_dfs || dfs->dfs_cac_valid || dfs->dfs_ignore_cac) { 462 dfs_debug(dfs, WLAN_DEBUG_DFS, 463 "Skip CAC, ignore_dfs = %d cac_valid = %d ignore_cac = %d", 464 dfs->dfs_ignore_dfs, dfs->dfs_cac_valid, 465 dfs->dfs_ignore_cac); 466 return false; 467 } 468 469 /* In case of RCAC, check if CAC is completed only on the RCAC channel 470 * and do not check the CAC info on current operating channel. 471 */ 472 if (dfs_is_agile_rcac_enabled(dfs) && 473 dfs_is_rcac_cac_done(dfs, cur_chan, prev_chan)) 474 return false; 475 476 /* If the channel has completed PRE-CAC then CAC can be skipped here. */ 477 if (dfs_is_precac_done(dfs, cur_chan)) { 478 dfs_debug(dfs, WLAN_DEBUG_DFS, 479 "PRE-CAC alreay done on this channel %d", 480 cur_chan->dfs_ch_ieee); 481 return false; 482 } 483 484 if (dfs_is_ap_cac_timer_running(dfs)) { 485 /* Check if we should continue the existing CAC or 486 * cancel the existing CAC. 487 * For example: - if an existing VAP(0) is already in 488 * DFS wait state (which means the radio(wifi) is 489 * running the CAC) and it is in channel A and another 490 * VAP(1) comes up in the same channel then instead of 491 * cancelling the CAC we can let the CAC continue. 492 */ 493 if (dfs_is_new_chan_subset_of_old_chan(dfs, 494 cur_chan, 495 cac_started_chan)) { 496 if (continue_current_cac) 497 *continue_current_cac = true; 498 } else { 499 /* New CAC is needed, cancel the running CAC 500 * timer. 501 * 1) When AP is in DFS_WAIT state and it is in 502 * channel A and user restarts the AP vap in 503 * channel B, then cancel the running CAC in 504 * channel A and start new CAC in channel B. 505 * 506 * 2) When AP detects the RADAR during CAC in 507 * channel A, it cancels the running CAC and 508 * tries to find channel B with the reduced 509 * bandwidth with of channel A. 510 * In this case, since the CAC is aborted by 511 * the RADAR, AP should start the CAC again. 512 */ 513 dfs_cancel_cac_timer(dfs); 514 } 515 } else { /* CAC timer is not running. */ 516 /* If channel change happens via VAP DOWN/UP on subset channels, 517 * (eg: from 52 HT80 to 64 HT80) CAC done information 518 * (of 52 HT80) based on subset logic 519 * (as 52 and 64 HT80 are subsets of each other) 520 * is not expected to be preserved as VAP has come up 521 * from DOWN state. Hence do not skip CAC on 64 HT80. 522 * is_vap_restart flag is used as an identifer to indicate if 523 * vap has come up from a DOWN state or UP state (vap restart). 524 */ 525 if (!is_vap_restart) { 526 dfs_debug(dfs, WLAN_DEBUG_DFS, "CAC is needed"); 527 return true; 528 } 529 if (dfs_is_new_chan_subset_of_old_chan(dfs, 530 cur_chan, 531 prev_chan)) { 532 /* AP bandwidth reduce case: 533 * When AP detects the RADAR in in-service monitoring 534 * mode in channel A, it cancels the running CAC and 535 * tries to find the channel B with the reduced 536 * bandwidth of channel A. 537 * If the new channel B is subset of the channel A 538 * then AP skips the CAC. 539 */ 540 if (!dfs->dfs_cac_aborted) { 541 dfs_debug(dfs, WLAN_DEBUG_DFS, "Skip CAC"); 542 return false; 543 } 544 } 545 } 546 547 return true; 548 } 549 #endif 550