1 /* 2 * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: API for processing radar found indication. 21 * 22 */ 23 24 #include "../dfs.h" 25 #include "../dfs_zero_cac.h" 26 #include "../dfs_process_radar_found_ind.h" 27 #include <wlan_reg_services_api.h> 28 #include <wlan_objmgr_vdev_obj.h> 29 #include <wlan_dfs_utils_api.h> 30 #include <wlan_dfs_tgt_api.h> 31 #include "wlan_dfs_mlme_api.h" 32 #include "../dfs_internal.h" 33 /** 34 * TODO: The code is not according to the following description needs 35 * modification and correction. Code always adds left and right channels to 36 * NOL even if it is not a chirp radar. 37 * 38 * A) If chirp radar starts at boundary and ends at boundary then three channels 39 * will be affected. 40 * freq_offset.freq[0] = fn (Center frequency) 41 * freq_offset.freq[1] = fn-1 (Left of center) 42 * freq_offset.freq[2] = fn+1 (Right of center) 43 * 44 * Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL. 45 * 46 * Chirp start freq Chirp end freq 47 * | | 48 * | | 49 * V V 50 * _______________________________________________________________________ 51 * | center freq | center freq | center freq | 52 * | ch(n-1) | ch(n) | ch(n+1) | 53 * | | | | | | | 54 * | | | | | | | 55 * | | | | | | | 56 * fn-1 fn boundary fn+1 57 * <-------- 20 Mhz ------> 58 * 59 * B) If chirp radar starts at one channel and continues up to another channel 60 * then two channels will be affected. 61 * freq_offset.freq[0] = fn 62 * freq_offset.freq[1] = 0 63 * freq_offset.freq[2] = fn+1 64 * 65 * Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL. 66 * 67 * Chirp start freq Chirp end freq 68 * | | 69 * | | 70 * V V 71 * _______________________________________________________________________ 72 * | center freq | center freq | center freq | 73 * | ch(n-1) | ch(n) | ch(n+1) | 74 * | | | | | | | 75 * | | | | | | | 76 * | | | | | | | 77 * fn-1 fn boundary fn+1 78 * <-------- 20 Mhz ------> 79 * 80 * C) Radar found at boundary, two channels will be affected. 81 * freq_offset.freq[0] = fn 82 * freq_offset.freq[1] = 0 83 * freq_offset.freq[2] = fn+1 84 * 85 * Two channels, ch(n) and ch(n+1) will be added to NOL. 86 * 87 * dfs_freq_offset (radar found freq) 88 * | 89 * | 90 * V 91 * _______________________________________________________________________ 92 * | center freq | center freq | center freq | 93 * | ch(n-1) | ch(n) | ch(n+1) | 94 * | | | | | | | 95 * | | | | | | | 96 * | | | | | | | 97 * fn-1 fn boundary fn+1 98 * <-------- 20 Mhz ------> 99 * 100 * 101 * D) Else only one channel will be affected. 102 * freq_offset.freq[0] = fn 103 * freq_offset.freq[1] = 0 104 * freq_offset.freq[2] = 0 105 * 106 * One channel ch(n) will be added to NOL. 107 * 108 * 109 * dfs_freq_offset (radar found freq) 110 * | 111 * | 112 * V 113 * _______________________________________________________________________ 114 * | center freq | center freq | center freq | 115 * | ch(n-1) | ch(n) | ch(n+1) | 116 * | | | | | | | 117 * | | | | | | | 118 * | | | | | | | 119 * fn-1 fn boundary fn+1 120 * <-------- 20 Mhz ------> 121 */ 122 123 int dfs_set_nol_subchannel_marking(struct wlan_dfs *dfs, 124 bool nol_subchannel_marking) 125 { 126 QDF_STATUS status = QDF_STATUS_SUCCESS; 127 128 if (!dfs) 129 return -EIO; 130 131 dfs->dfs_use_nol_subchannel_marking = nol_subchannel_marking; 132 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "NOL subchannel marking is %s ", 133 (nol_subchannel_marking) ? "set" : "disabled"); 134 if (dfs->dfs_is_offload_enabled) 135 status = tgt_dfs_send_subchan_marking(dfs->dfs_pdev_obj, 136 nol_subchannel_marking); 137 138 return qdf_status_to_os_return(status); 139 } 140 141 int dfs_get_nol_subchannel_marking(struct wlan_dfs *dfs, 142 bool *nol_subchannel_marking) 143 { 144 if (!dfs) 145 return -EIO; 146 147 (*nol_subchannel_marking) = dfs->dfs_use_nol_subchannel_marking; 148 149 return 0; 150 } 151 152 /** 153 * dfs_radar_add_channel_list_to_nol_for_freq()- Add given channels to nol 154 * @dfs: Pointer to wlan_dfs structure. 155 * @freq_list: Pointer to list of frequency. 156 * @num_channels: Number of channels in the list. 157 * 158 * Add list of channels to nol, only if the channel is dfs. 159 * 160 * Return: QDF_STATUS 161 */ 162 #ifdef CONFIG_CHAN_FREQ_API 163 static QDF_STATUS 164 dfs_radar_add_channel_list_to_nol_for_freq(struct wlan_dfs *dfs, 165 uint16_t *freq_list, 166 uint8_t num_channels) 167 { 168 int i; 169 uint16_t last_chan_freq = 0; 170 uint16_t nol_freq_list[NUM_CHANNELS_160MHZ]; 171 uint8_t num_ch = 0; 172 173 if (num_channels > NUM_CHANNELS_160MHZ) { 174 dfs_err(dfs, WLAN_DEBUG_DFS, 175 "Invalid num channels: %d", num_channels); 176 return QDF_STATUS_E_FAILURE; 177 } 178 179 for (i = 0; i < num_channels; i++) { 180 if (freq_list[i] == 0 || 181 freq_list[i] == last_chan_freq) 182 continue; 183 if (!utils_is_dfs_chan_for_freq(dfs->dfs_pdev_obj, 184 freq_list[i])) { 185 dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip", 186 freq_list[i]); 187 continue; 188 } 189 last_chan_freq = freq_list[i]; 190 DFS_NOL_ADD_CHAN_LOCKED(dfs, 191 freq_list[i], 192 dfs->wlan_dfs_nol_timeout); 193 nol_freq_list[num_ch++] = last_chan_freq; 194 utils_dfs_deliver_event(dfs->dfs_pdev_obj, 195 freq_list[i], 196 WLAN_EV_NOL_STARTED); 197 dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL", 198 last_chan_freq); 199 } 200 201 if (!num_ch) { 202 dfs_err(dfs, WLAN_DEBUG_DFS, 203 "dfs channels not found in channel list"); 204 return QDF_STATUS_E_FAILURE; 205 } 206 207 utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj, 208 nol_freq_list, num_ch, 209 DFS_NOL_SET); 210 211 if (dfs->dfs_is_stadfs_enabled) 212 if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj)) 213 utils_dfs_reg_update_nol_history_chan_for_freq( 214 dfs->dfs_pdev_obj, nol_freq_list, 215 num_ch, DFS_NOL_HISTORY_SET); 216 217 dfs_nol_update(dfs); 218 utils_dfs_save_nol(dfs->dfs_pdev_obj); 219 220 return QDF_STATUS_SUCCESS; 221 } 222 #endif 223 /** 224 * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz 225 * @freq_offset: freq offset 226 * @center_freq: center frequency 227 * 228 * Find frequency offsets for 80MHz 229 * 230 * Return: None 231 */ 232 static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset, 233 uint32_t center_freq) 234 { 235 int i; 236 237 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 238 if (freq_offset->offset[i] < DFS_OFFSET_SECOND_LOWER) 239 freq_offset->freq[i] = 240 DFS_THIRD_LOWER_CHANNEL(center_freq); 241 else if ((freq_offset->offset[i] > DFS_OFFSET_SECOND_LOWER) && 242 (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER)) 243 freq_offset->freq[i] = 244 DFS_SECOND_LOWER_CHANNEL(center_freq); 245 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) && 246 (freq_offset->offset[i] < 0)) 247 freq_offset->freq[i] = 248 DFS_FIRST_LOWER_CHANNEL(center_freq); 249 else if ((freq_offset->offset[i] > 0) && 250 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER)) 251 freq_offset->freq[i] = 252 DFS_FIRST_UPPER_CHANNEL(center_freq); 253 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) && 254 (freq_offset->offset[i] < DFS_OFFSET_SECOND_UPPER)) 255 freq_offset->freq[i] = 256 DFS_SECOND_UPPER_CHANNEL(center_freq); 257 else if (freq_offset->offset[i] > DFS_OFFSET_SECOND_UPPER) 258 freq_offset->freq[i] = 259 DFS_THIRD_UPPER_CHANNEL(center_freq); 260 } 261 } 262 263 /** 264 * dfs_radar_chan_for_40()- Find frequency offsets for 40MHz 265 * @freq_offset: freq offset 266 * @center_freq: center frequency 267 * 268 * Find frequency offsets for 40MHz 269 * 270 * Return: None 271 */ 272 static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset, 273 uint32_t center_freq) 274 { 275 int i; 276 277 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 278 if (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER) 279 freq_offset->freq[i] = 280 DFS_SECOND_LOWER_CHANNEL(center_freq); 281 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) && 282 (freq_offset->offset[i] < 0)) 283 freq_offset->freq[i] = 284 DFS_FIRST_LOWER_CHANNEL(center_freq); 285 else if ((freq_offset->offset[i] > 0) && 286 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER)) 287 freq_offset->freq[i] = 288 DFS_FIRST_UPPER_CHANNEL(center_freq); 289 else if (freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) 290 freq_offset->freq[i] = 291 DFS_SECOND_UPPER_CHANNEL(center_freq); 292 } 293 } 294 295 /** 296 * dfs_radar_chan_for_20()- Find frequency offsets for 20MHz 297 * @freq_offset: freq offset 298 * @center_freq: center frequency 299 * 300 * Find frequency offsets for 20MHz 301 * 302 * Return: None 303 */ 304 static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset, 305 uint32_t center_freq) 306 { 307 int i; 308 309 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 310 if (freq_offset->offset[i] <= DFS_20MZ_OFFSET_LOWER) 311 freq_offset->freq[i] = 312 DFS_20MHZ_LOWER_CHANNEL(center_freq); 313 else if ((freq_offset->offset[i] > DFS_20MZ_OFFSET_LOWER) && 314 (freq_offset->offset[i] < DFS_20MZ_OFFSET_UPPER)) 315 freq_offset->freq[i] = center_freq; 316 else if (freq_offset->offset[i] >= DFS_20MZ_OFFSET_UPPER) 317 freq_offset->freq[i] = 318 DFS_20MHZ_UPPER_CHANNEL(center_freq); 319 } 320 } 321 322 /* dfs_compute_radar_found_cfreq(): Computes the centre frequency of the 323 * radar hit channel. 324 * @dfs: Pointer to wlan_dfs structure. 325 * @radar_found: Pointer to radar_found_info. 326 * @freq_center: Pointer to retrieve the value of radar found cfreq. 327 */ 328 #ifdef CONFIG_CHAN_FREQ_API 329 static void 330 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, 331 struct radar_found_info *radar_found, 332 uint32_t *freq_center) 333 { 334 struct dfs_channel *curchan = dfs->dfs_curchan; 335 336 /* Radar found on agile detector ID. 337 * Applicable to chips that have a separate agile radar detector 338 * engine. 339 */ 340 if (radar_found->detector_id == AGILE_DETECTOR_ID) { 341 *freq_center = dfs->dfs_agile_precac_freq_mhz; 342 } else if (!radar_found->segment_id) { 343 *freq_center = curchan->dfs_ch_mhz_freq_seg1; 344 } else { 345 /* Radar found on secondary segment by the HW when 346 * preCAC was running. It (dfs_precac_enable) is specific to 347 * legacy chips. 348 */ 349 if (dfs_is_precac_timer_running(dfs) && 350 dfs_is_legacy_precac_enabled(dfs)) { 351 *freq_center = dfs->dfs_precac_secondary_freq_mhz; 352 } else { 353 /* Radar found on secondary segment by the HW, when preCAC 354 * was not running in legacy chips or preCAC was running 355 * in Lithium chips. 356 */ 357 *freq_center = curchan->dfs_ch_mhz_freq_seg2; 358 if (WLAN_IS_CHAN_MODE_160(curchan)) { 359 /* If center frequency of entire 160 band 360 * is less than center frequency of primary 361 * segment, then the center frequency of 362 * secondary segment is -40 of center 363 * frequency of entire 160 segment. 364 */ 365 if (curchan->dfs_ch_mhz_freq_seg2 < 366 curchan->dfs_ch_mhz_freq_seg1) 367 *freq_center -= 368 DFS_160MHZ_SECOND_SEG_OFFSET; 369 else 370 *freq_center += 371 DFS_160MHZ_SECOND_SEG_OFFSET; 372 } 373 } 374 } 375 } 376 #else 377 #ifdef CONFIG_CHAN_NUM_API 378 static void 379 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, 380 struct radar_found_info 381 *radar_found, 382 uint32_t *freq_center) 383 { 384 struct dfs_channel *curchan = dfs->dfs_curchan; 385 /* Radar found on agile detector ID. 386 * Applicable to chips that have a separate agile radar detector 387 * engine. 388 */ 389 if (radar_found->detector_id == AGILE_DETECTOR_ID) { 390 *freq_center = utils_dfs_chan_to_freq( 391 dfs->dfs_agile_precac_freq); 392 /* Radar found on primary segment by the HW. */ 393 } else if (radar_found->segment_id == PRIMARY_SEG) { 394 *freq_center = utils_dfs_chan_to_freq( 395 curchan->dfs_ch_vhtop_ch_freq_seg1); 396 } else { 397 /* Radar found on secondary segment by the HW when 398 * preCAC was running. It (dfs_precac_enable) is specific to 399 * legacy chips. 400 */ 401 if (dfs_is_precac_timer_running(dfs) && 402 dfs_is_legacy_precac_enabled(dfs)) { 403 *freq_center = utils_dfs_chan_to_freq( 404 dfs->dfs_precac_secondary_freq); 405 } else { 406 /* Radar found on secondary segment by the HW, when preCAC 407 * was not running in legacy chips or preCAC was running 408 * in Lithium chips. 409 */ 410 *freq_center = utils_dfs_chan_to_freq( 411 curchan->dfs_ch_vhtop_ch_freq_seg2); 412 if (WLAN_IS_CHAN_MODE_160(curchan)) { 413 /* If center frequency of entire 160 band 414 * is less than center frequency of primary 415 * segment, then the center frequency of 416 * secondary segment is -40 of center 417 * frequency of entire 160 segment. 418 */ 419 if (curchan->dfs_ch_vhtop_ch_freq_seg2 < 420 curchan->dfs_ch_vhtop_ch_freq_seg1) 421 *freq_center -= 422 DFS_160MHZ_SECOND_SEG_OFFSET; 423 else 424 *freq_center += 425 DFS_160MHZ_SECOND_SEG_OFFSET; 426 } 427 } 428 } 429 } 430 #endif 431 #endif 432 433 /** 434 * dfs_find_radar_affected_subchans_for_freq() - Find radar affected sub chans. 435 * @dfs: Pointer to wlan_dfs structure. 436 * @radar_found: Pointer to radar_found structure. 437 * @freq_list: Pointer to save radar affected channels. 438 * @freq_center: Freq_center of the radar affected chan. 439 * 440 * Return: Number of channels. 441 */ 442 #ifdef CONFIG_CHAN_FREQ_API 443 static uint8_t 444 dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs *dfs, 445 struct radar_found_info *radar_found, 446 uint16_t *freq_list, 447 uint32_t freq_center) 448 { 449 int i, j; 450 uint8_t num_radar_subchans; 451 uint32_t flag; 452 int32_t sidx; 453 uint16_t candidate_subchan_freq; 454 uint16_t cur_subchans[NUM_CHANNELS_160MHZ]; 455 uint8_t n_cur_subchans; 456 struct dfs_channel *curchan = dfs->dfs_curchan; 457 struct freqs_offsets freq_offset; 458 459 qdf_mem_zero(&freq_offset, sizeof(freq_offset)); 460 flag = curchan->dfs_ch_flags; 461 462 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) 463 freq_offset.offset[i] = radar_found->freq_offset; 464 465 sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset); 466 467 dfs_info(dfs, WLAN_DEBUG_DFS, 468 "seg=%d, det=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d", 469 radar_found->segment_id, radar_found->detector_id, sidx, 470 radar_found->freq_offset, radar_found->is_chirp, 471 flag, freq_center); 472 473 if ((WLAN_IS_CHAN_A(curchan)) || 474 WLAN_IS_CHAN_MODE_20(curchan)) { 475 if (radar_found->is_chirp || 476 (sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) { 477 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 478 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 479 } 480 dfs_radar_chan_for_20(&freq_offset, freq_center); 481 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 482 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 483 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 484 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 485 } 486 dfs_radar_chan_for_40(&freq_offset, freq_center); 487 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 488 WLAN_IS_CHAN_MODE_160(curchan) || 489 WLAN_IS_CHAN_MODE_80_80(curchan)) { 490 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 491 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 492 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 493 } 494 dfs_radar_chan_for_80(&freq_offset, freq_center); 495 } else { 496 dfs_err(dfs, WLAN_DEBUG_DFS, 497 "channel flag=%d is invalid", flag); 498 return 0; 499 } 500 501 n_cur_subchans = 502 dfs_get_bonding_channels_for_freq(dfs, curchan, 503 radar_found->segment_id, 504 radar_found->detector_id, 505 cur_subchans); 506 507 for (i = 0, num_radar_subchans = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 508 candidate_subchan_freq = freq_offset.freq[i]; 509 for (j = 0; j < n_cur_subchans; j++) { 510 if (cur_subchans[j] == candidate_subchan_freq) { 511 freq_list[num_radar_subchans++] = 512 candidate_subchan_freq; 513 dfs_info(dfs, WLAN_DEBUG_DFS, 514 "offset=%d, channel=%d", 515 num_radar_subchans, 516 freq_list[num_radar_subchans - 1]); 517 break; 518 } 519 } 520 } 521 return num_radar_subchans; 522 } 523 #endif 524 525 #ifdef CONFIG_CHAN_NUM_API 526 uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, 527 uint8_t *channels) 528 { 529 uint8_t center_chan; 530 uint8_t nchannels = 0; 531 532 center_chan = chan->dfs_ch_vhtop_ch_freq_seg1; 533 534 if (WLAN_IS_CHAN_MODE_20(chan)) { 535 nchannels = 1; 536 channels[0] = center_chan; 537 } else if (WLAN_IS_CHAN_MODE_40(chan)) { 538 nchannels = 2; 539 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 540 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 541 } else if (WLAN_IS_CHAN_MODE_80(chan)) { 542 nchannels = 4; 543 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 544 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 545 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 546 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 547 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { 548 nchannels = 8; 549 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 550 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 551 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 552 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 553 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 554 channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 555 channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 556 channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 557 channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 558 } else if (WLAN_IS_CHAN_MODE_160(chan)) { 559 nchannels = 8; 560 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 561 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 562 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 563 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 564 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 565 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 566 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 567 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 568 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 569 } 570 571 return nchannels; 572 } 573 #endif 574 575 /* 576 * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding frequency 577 * list. 578 * @chan: Pointer to dfs_channel. 579 * @freq_list: Pointer to frequency list. 580 */ 581 #ifdef CONFIG_CHAN_FREQ_API 582 uint8_t 583 dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan, 584 uint16_t *freq_list) 585 { 586 uint16_t center_freq; 587 uint8_t nchannels = 0; 588 589 center_freq = chan->dfs_ch_mhz_freq_seg1; 590 591 if (WLAN_IS_CHAN_MODE_20(chan)) { 592 nchannels = 1; 593 freq_list[0] = center_freq; 594 } else if (WLAN_IS_CHAN_MODE_40(chan)) { 595 nchannels = 2; 596 freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 597 freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 598 } else if (WLAN_IS_CHAN_MODE_80(chan)) { 599 nchannels = 4; 600 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 601 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 602 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 603 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 604 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { 605 nchannels = 8; 606 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 607 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 608 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 609 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 610 center_freq = chan->dfs_ch_mhz_freq_seg2; 611 freq_list[4] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 612 freq_list[5] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 613 freq_list[6] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 614 freq_list[7] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 615 } else if (WLAN_IS_CHAN_MODE_160(chan)) { 616 nchannels = 8; 617 center_freq = chan->dfs_ch_mhz_freq_seg2; 618 freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 619 freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 620 freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 621 freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 622 freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 623 freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 624 freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 625 freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 626 } 627 628 return nchannels; 629 } 630 #endif 631 632 /* 633 * dfs_get_bonding_channels_for_freq() - Get bonding channel frequency. 634 * @dfs: Pointer to wlan_dfs. 635 * @curchan: Pointer to dfs_channel. 636 * @segment_id: Segment ID. 637 * @detector_id: Detector ID. 638 * @freq_list: Pointer to frequency list. 639 */ 640 #ifdef CONFIG_CHAN_FREQ_API 641 uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs, 642 struct dfs_channel *curchan, 643 uint32_t segment_id, 644 uint8_t detector_id, 645 uint16_t *freq_list) 646 { 647 uint16_t center_freq; 648 uint8_t nchannels = 0; 649 650 if (detector_id == AGILE_DETECTOR_ID) 651 center_freq = dfs->dfs_agile_precac_freq_mhz; 652 else if (!segment_id) 653 center_freq = curchan->dfs_ch_mhz_freq_seg1; 654 else { 655 /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is 656 * zero and "dfs_precac_secondary_freq" holds the secondary 657 * frequency. 658 */ 659 if (dfs_is_precac_timer_running(dfs)) 660 center_freq = dfs->dfs_precac_secondary_freq_mhz; 661 else 662 center_freq = curchan->dfs_ch_mhz_freq_seg2; 663 } 664 665 if (WLAN_IS_CHAN_MODE_20(curchan)) { 666 nchannels = 1; 667 freq_list[0] = center_freq; 668 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 669 nchannels = 2; 670 freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 671 freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 672 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 673 WLAN_IS_CHAN_MODE_80_80(curchan) || 674 detector_id == AGILE_DETECTOR_ID) { 675 /* If the current channel's bandwidth is 80/80+80/160Mhz, 676 * the corresponding agile Detector's bandwidth will be 80Mhz. 677 * Therefore, if radar is found on the agile detector find 678 * subchannels for 80Mhz bandwidth. 679 */ 680 nchannels = 4; 681 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 682 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 683 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 684 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 685 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 686 nchannels = 8; 687 center_freq = curchan->dfs_ch_mhz_freq_seg2; 688 freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 689 freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 690 freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 691 freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 692 freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 693 freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 694 freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 695 freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 696 } 697 698 return nchannels; 699 } 700 #endif 701 702 #ifdef CONFIG_CHAN_NUM_API 703 uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, 704 struct dfs_channel *curchan, 705 uint32_t segment_id, 706 uint8_t detector_id, 707 uint8_t *channels) 708 { 709 uint8_t center_chan; 710 uint8_t nchannels = 0; 711 712 if (detector_id == AGILE_DETECTOR_ID) 713 center_chan = dfs->dfs_agile_precac_freq; 714 else if (!segment_id) 715 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1; 716 else { 717 /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is 718 * zero and "dfs_precac_secondary_freq" holds the secondary 719 * frequency in case of legacy chips. 720 * For chips that support a separate agile detector engine, 721 * "dfs_agile_precac_freq" holds the frequency that agile 722 * engine operates on. 723 * 724 * In case of radar detected by the HW in the secondary 80 725 * channel,"dfs_ch_vhtop_ch_freq_seg2" holds the secondary 726 * segment center frequency in the below cases: 727 * 1. preCAC timer is running in chips that support separate 728 * agile engines. 729 * 2. preCAC timer is not running. 730 */ 731 if (dfs_is_precac_timer_running(dfs) && 732 dfs_is_legacy_precac_enabled(dfs)) 733 center_chan = dfs->dfs_precac_secondary_freq; 734 else 735 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 736 } 737 738 if (WLAN_IS_CHAN_MODE_20(curchan)) { 739 nchannels = 1; 740 channels[0] = center_chan; 741 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 742 nchannels = 2; 743 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 744 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 745 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 746 WLAN_IS_CHAN_MODE_80_80(curchan) || 747 detector_id == AGILE_DETECTOR_ID) { 748 /* If the current channel's bandwidth is 80/80+80/160Mhz, 749 * the corresponding agile Detector's bandwidth will be 80Mhz. 750 * Therefore, if radar is found on the agile detector find 751 * subchannels for 80Mhz bandwidth. 752 */ 753 nchannels = 4; 754 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 755 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 756 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 757 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 758 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 759 nchannels = 8; 760 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 761 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 762 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 763 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 764 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 765 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 766 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 767 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 768 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 769 } 770 771 return nchannels; 772 } 773 #endif 774 775 static inline void dfs_reset_bangradar(struct wlan_dfs *dfs) 776 { 777 dfs->dfs_bangradar_type = DFS_NO_BANGRADAR; 778 } 779 780 int dfs_radarevent_basic_sanity(struct wlan_dfs *dfs, 781 struct dfs_channel *chan) 782 { 783 if (!(dfs->dfs_seg_id == SEG_ID_SECONDARY && 784 dfs_is_precac_timer_running(dfs))) 785 if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) { 786 dfs_debug(dfs, WLAN_DEBUG_DFS2, 787 "radar event on non-DFS chan"); 788 if (!(dfs->dfs_is_offload_enabled)) { 789 dfs_reset_radarq(dfs); 790 dfs_reset_alldelaylines(dfs); 791 dfs_reset_bangradar(dfs); 792 } 793 return 0; 794 } 795 796 return 1; 797 } 798 799 /** 800 * dfs_send_csa_to_current_chan() - Send CSA to current channel 801 * @dfs: Pointer to wlan_dfs structure. 802 * 803 * For the test mode(usenol = 0), don't do a CSA; but setup the test timer so 804 * we get a CSA _back_ to the current operating channel. 805 */ 806 static inline void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs) 807 { 808 qdf_timer_stop(&dfs->wlan_dfstesttimer); 809 dfs->wlan_dfstest = 1; 810 dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee; 811 dfs->wlan_dfstesttime = 1; /* 1ms */ 812 qdf_timer_mod(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime); 813 } 814 815 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs) 816 { 817 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 818 819 return 0; 820 } 821 822 /* dfs_prepare_nol_ie_bitmap: Create a Bitmap from the radar found subchannels 823 * to be sent along with RCSA. 824 * @dfs: Pointer to wlan_dfs. 825 * @radar_found: Pointer to radar_found_info. 826 * @in_sub_channels: Pointer to Sub-channels. 827 * @n_in_sub_channels: Number of sub-channels. 828 */ 829 #ifdef CONFIG_CHAN_FREQ_API 830 static void 831 dfs_prepare_nol_ie_bitmap_for_freq(struct wlan_dfs *dfs, 832 struct radar_found_info *radar_found, 833 uint16_t *in_sub_channels, 834 uint8_t n_in_sub_channels) 835 { 836 uint16_t cur_subchans[NUM_CHANNELS_160MHZ]; 837 uint8_t n_cur_subchans; 838 uint8_t i; 839 uint8_t j; 840 uint8_t bits = 0x01; 841 842 n_cur_subchans = 843 dfs_get_bonding_channels_for_freq(dfs, dfs->dfs_curchan, 844 radar_found->segment_id, 845 radar_found->detector_id, 846 cur_subchans); 847 dfs->dfs_nol_ie_bandwidth = MIN_DFS_SUBCHAN_BW; 848 dfs->dfs_nol_ie_startfreq = cur_subchans[0]; 849 850 /* Search through the array list of radar affected subchannels 851 * to find if the subchannel in our current channel has radar hit. 852 * Break if found to reduce loop count. 853 */ 854 for (i = 0; i < n_cur_subchans; i++) { 855 for (j = 0; j < n_in_sub_channels; j++) { 856 if (cur_subchans[i] == in_sub_channels[j]) { 857 dfs->dfs_nol_ie_bitmap |= bits; 858 break; 859 } 860 } 861 bits <<= 1; 862 } 863 } 864 #endif 865 866 void dfs_fetch_nol_ie_info(struct wlan_dfs *dfs, 867 uint8_t *nol_ie_bandwidth, 868 uint16_t *nol_ie_startfreq, 869 uint8_t *nol_ie_bitmap) 870 { 871 if (nol_ie_bandwidth) 872 *nol_ie_bandwidth = dfs->dfs_nol_ie_bandwidth; 873 if (nol_ie_startfreq) 874 *nol_ie_startfreq = dfs->dfs_nol_ie_startfreq; 875 if (nol_ie_bitmap) 876 *nol_ie_bitmap = dfs->dfs_nol_ie_bitmap; 877 } 878 879 void dfs_get_rcsa_flags(struct wlan_dfs *dfs, bool *is_rcsa_ie_sent, 880 bool *is_nol_ie_sent) 881 { 882 if (is_rcsa_ie_sent) 883 *is_rcsa_ie_sent = dfs->dfs_is_rcsa_ie_sent; 884 if (is_nol_ie_sent) 885 *is_nol_ie_sent = dfs->dfs_is_nol_ie_sent; 886 } 887 888 void dfs_set_rcsa_flags(struct wlan_dfs *dfs, bool is_rcsa_ie_sent, 889 bool is_nol_ie_sent) 890 { 891 dfs->dfs_is_rcsa_ie_sent = is_rcsa_ie_sent; 892 dfs->dfs_is_nol_ie_sent = is_nol_ie_sent; 893 } 894 895 static void dfs_reset_nol_ie_bitmap(struct wlan_dfs *dfs) 896 { 897 dfs->dfs_nol_ie_bitmap = 0; 898 } 899 900 #ifdef CONFIG_CHAN_FREQ_API 901 bool dfs_process_nol_ie_bitmap(struct wlan_dfs *dfs, uint8_t nol_ie_bandwidth, 902 uint16_t nol_ie_startfreq, uint8_t nol_ie_bitmap) 903 { 904 uint8_t num_subchans; 905 uint8_t bits = 0x01; 906 uint16_t radar_subchans[NUM_CHANNELS_160MHZ]; 907 bool should_nol_ie_be_sent = true; 908 909 qdf_mem_zero(radar_subchans, sizeof(radar_subchans)); 910 if (!dfs->dfs_use_nol_subchannel_marking) { 911 /* Since subchannel marking is disabled, disregard 912 * NOL IE and set NOL IE flag as false, so it 913 * can't be sent to uplink. 914 */ 915 num_subchans = 916 dfs_get_bonding_channels_for_freq(dfs, 917 dfs->dfs_curchan, 918 SEG_ID_PRIMARY, 919 DETECTOR_ID_0, 920 radar_subchans); 921 should_nol_ie_be_sent = false; 922 } else { 923 /* Add the NOL IE information in DFS structure so that RCSA 924 * and NOL IE can be sent to uplink if uplink exists. 925 */ 926 uint32_t frequency = (uint32_t)nol_ie_startfreq; 927 928 dfs->dfs_nol_ie_bandwidth = nol_ie_bandwidth; 929 dfs->dfs_nol_ie_startfreq = nol_ie_startfreq; 930 dfs->dfs_nol_ie_bitmap = nol_ie_bitmap; 931 for (num_subchans = 0; num_subchans < NUM_CHANNELS_160MHZ; 932 num_subchans++) { 933 if (nol_ie_bitmap & bits) { 934 radar_subchans[num_subchans] = frequency; 935 } 936 bits <<= 1; 937 frequency += nol_ie_bandwidth; 938 } 939 } 940 941 dfs_radar_add_channel_list_to_nol_for_freq(dfs, radar_subchans, 942 num_subchans); 943 return should_nol_ie_be_sent; 944 } 945 #endif 946 947 #ifdef CONFIG_CHAN_FREQ_API 948 QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, 949 struct radar_found_info *radar_found) 950 { 951 bool wait_for_csa = false; 952 uint16_t freq_list[NUM_CHANNELS_160MHZ]; 953 uint8_t num_channels; 954 QDF_STATUS status = QDF_STATUS_E_FAILURE; 955 uint32_t freq_center; 956 uint32_t radarfound_freq; 957 struct dfs_channel *dfs_curchan; 958 959 /* Acquire a lock to avoid initiating mode switch till radar 960 * processing is completed. 961 */ 962 DFS_RADAR_MODE_SWITCH_LOCK(dfs); 963 964 /* Before processing radar, check if HW mode switch is in progress. 965 * If in progress, defer the processing of radar event received till 966 * the mode switch is completed. 967 */ 968 if (dfs_is_hw_mode_switch_in_progress(dfs)) { 969 struct radar_found_info *radar_params = NULL; 970 971 radar_params = qdf_mem_malloc(sizeof(*radar_params)); 972 if (!radar_params) 973 goto exit; 974 975 /* If CAC timer is running, cancel it here rather than 976 * after processing to avoid handling unnecessary CAC timeouts. 977 */ 978 if (dfs->dfs_cac_timer_running) 979 dfs_cac_stop(dfs); 980 981 /* If CAC timer is to be handled after mode switch and then 982 * we receive radar, no point in handling CAC completion. 983 */ 984 if (dfs->dfs_defer_params.is_cac_completed) 985 dfs->dfs_defer_params.is_cac_completed = false; 986 qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params)); 987 dfs->dfs_defer_params.radar_params = radar_params; 988 dfs->dfs_defer_params.is_radar_detected = true; 989 status = QDF_STATUS_SUCCESS; 990 goto exit; 991 } 992 993 dfs_curchan = dfs->dfs_curchan; 994 995 if (!dfs_curchan) { 996 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs->dfs_curchan is NULL"); 997 goto exit; 998 } 999 1000 /* Check if the current channel is a non DFS channel 1001 * If the current channel is non-DFS and the radar is from Agile 1002 * Detector we need to process it since Agile Detector has a 1003 * different channel. 1004 */ 1005 if (!dfs_radarevent_basic_sanity(dfs, dfs_curchan) && 1006 !(radar_found->detector_id == AGILE_DETECTOR_ID)) { 1007 dfs_err(dfs, WLAN_DEBUG_DFS, 1008 "radar event on a non-DFS channel"); 1009 goto exit; 1010 } 1011 1012 /* Sanity checks for radar on Agile detector */ 1013 if (radar_found->detector_id == AGILE_DETECTOR_ID && 1014 (!dfs_is_agile_precac_enabled(dfs) || !dfs->dfs_agile_precac_freq_mhz)) 1015 { 1016 dfs_err(dfs, WLAN_DEBUG_DFS, 1017 "radar on Agile detector when ADFS is not running"); 1018 goto exit; 1019 } 1020 1021 /* For Full Offload, FW sends segment id,freq_offset and chirp 1022 * information and gets assigned when there is radar detect. In 1023 * case of radartool bangradar enhanced command and real radar 1024 * for DA and PO, we assign these information here. 1025 */ 1026 if (!(dfs->dfs_is_offload_enabled && dfs->dfs_radar_found_for_fo)) { 1027 radar_found->segment_id = dfs->dfs_seg_id; 1028 radar_found->freq_offset = dfs->dfs_freq_offset; 1029 radar_found->is_chirp = dfs->dfs_is_chirp; 1030 } 1031 1032 dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center); 1033 radarfound_freq = freq_center + radar_found->freq_offset; 1034 1035 if (radar_found->detector_id == AGILE_DETECTOR_ID) 1036 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 1037 "Radar found on Agile detector freq=%d radar freq=%d", 1038 freq_center, radarfound_freq); 1039 else if (radar_found->segment_id == SEG_ID_SECONDARY) 1040 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 1041 "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.", 1042 radarfound_freq, freq_center); 1043 else 1044 dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, 1045 "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.", 1046 utils_dfs_freq_to_chan(radarfound_freq), 1047 radarfound_freq, dfs_curchan->dfs_ch_ieee, 1048 dfs_curchan->dfs_ch_freq); 1049 1050 utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq, 1051 WLAN_EV_RADAR_DETECTED); 1052 1053 if (!dfs->dfs_use_nol) { 1054 dfs_reset_bangradar(dfs); 1055 dfs_send_csa_to_current_chan(dfs); 1056 status = QDF_STATUS_SUCCESS; 1057 goto exit; 1058 } 1059 1060 if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS) 1061 num_channels = 1062 dfs_get_bonding_channel_without_seg_info_for_freq 1063 (dfs_curchan, freq_list); 1064 /* BW reduction is dependent on subchannel marking */ 1065 else if ((dfs->dfs_use_nol_subchannel_marking) && 1066 (!(dfs->dfs_bangradar_type) || 1067 (dfs->dfs_bangradar_type == 1068 DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS))) 1069 num_channels = 1070 dfs_find_radar_affected_subchans_for_freq(dfs, 1071 radar_found, 1072 freq_list, 1073 freq_center); 1074 else 1075 num_channels = dfs_get_bonding_channels_for_freq 1076 (dfs, dfs_curchan, radar_found->segment_id, 1077 radar_found->detector_id, freq_list); 1078 1079 dfs_reset_bangradar(dfs); 1080 1081 status = dfs_radar_add_channel_list_to_nol_for_freq(dfs, 1082 freq_list, 1083 num_channels); 1084 if (QDF_IS_STATUS_ERROR(status)) { 1085 dfs_err(dfs, WLAN_DEBUG_DFS, 1086 "radar event received on invalid channel"); 1087 goto exit; 1088 } 1089 1090 dfs->dfs_is_nol_ie_sent = false; 1091 (dfs->is_radar_during_precac || 1092 radar_found->detector_id == AGILE_DETECTOR_ID) ? 1093 (dfs->dfs_is_rcsa_ie_sent = false) : 1094 (dfs->dfs_is_rcsa_ie_sent = true); 1095 if (dfs->dfs_use_nol_subchannel_marking) { 1096 dfs_reset_nol_ie_bitmap(dfs); 1097 dfs_prepare_nol_ie_bitmap_for_freq(dfs, radar_found, freq_list, 1098 num_channels); 1099 dfs->dfs_is_nol_ie_sent = true; 1100 } 1101 1102 /* 1103 * If precac is running and the radar found in secondary 1104 * VHT80 mark the channel as radar and add to NOL list. 1105 * Otherwise random channel selection can choose this 1106 * channel. 1107 */ 1108 dfs_debug(dfs, WLAN_DEBUG_DFS, 1109 "found_on_second=%d is_pre=%d", 1110 dfs->is_radar_found_on_secondary_seg, 1111 dfs_is_precac_timer_running(dfs)); 1112 /* 1113 * Even if radar found on primary, we need to mark the channel as NOL 1114 * in preCAC list. The preCAC list also maintains the current CAC 1115 * channels as part of pre-cleared DFS. Hence call the API 1116 * to mark channels as NOL irrespective of preCAC being enabled or not. 1117 */ 1118 1119 dfs_debug(dfs, WLAN_DEBUG_DFS, 1120 "%s: %d Radar found on dfs detector:%d", 1121 __func__, __LINE__, radar_found->detector_id); 1122 dfs_mark_precac_nol_for_freq(dfs, 1123 dfs->is_radar_found_on_secondary_seg, 1124 radar_found->detector_id, 1125 freq_list, 1126 num_channels); 1127 /* 1128 * This calls into the umac DFS code, which sets the umac 1129 * related radar flags and begins the channel change 1130 * machinery. 1131 1132 * Even during precac, this API is called, but with a flag 1133 * saying not to send RCSA, but only the radar affected subchannel 1134 * information. 1135 */ 1136 1137 dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa); 1138 1139 /* If radar is found on preCAC or Agile CAC, return here since 1140 * channel change is not required. 1141 */ 1142 if (radar_found->detector_id == AGILE_DETECTOR_ID) 1143 goto exit; 1144 if (!dfs->dfs_is_offload_enabled && 1145 dfs->is_radar_found_on_secondary_seg) { 1146 dfs_second_segment_radar_disable(dfs); 1147 dfs->is_radar_found_on_secondary_seg = 0; 1148 1149 if (dfs->is_radar_during_precac) { 1150 dfs->is_radar_during_precac = 0; 1151 goto exit; 1152 } 1153 } 1154 1155 /* 1156 * XXX TODO: the umac NOL code isn't used, but 1157 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac 1158 * NOL code isn't used, that flag is never cleared. This 1159 * needs to be fixed. See EV 105776. 1160 */ 1161 if (wait_for_csa) 1162 goto exit; 1163 1164 /* 1165 * EV 129487 : We have detected radar in the channel, 1166 * stop processing PHY error data as this can cause 1167 * false detect in the new channel while channel 1168 * change is in progress. 1169 */ 1170 1171 if (!dfs->dfs_is_offload_enabled) { 1172 dfs_radar_disable(dfs); 1173 dfs_second_segment_radar_disable(dfs); 1174 } 1175 1176 dfs_mlme_mark_dfs_for_freq(dfs->dfs_pdev_obj, 1177 dfs->dfs_curchan->dfs_ch_ieee, 1178 dfs->dfs_curchan->dfs_ch_freq, 1179 dfs->dfs_curchan->dfs_ch_mhz_freq_seg2, 1180 dfs->dfs_curchan->dfs_ch_flags); 1181 1182 exit: 1183 DFS_RADAR_MODE_SWITCH_UNLOCK(dfs); 1184 return status; 1185 } 1186 #endif 1187