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