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