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 #ifdef CONFIG_CHAN_FREQ_API 153 QDF_STATUS 154 dfs_radar_add_channel_list_to_nol_for_freq(struct wlan_dfs *dfs, 155 uint16_t *freq_list, 156 uint16_t *nol_freq_list, 157 uint8_t *num_channels) 158 { 159 int i; 160 uint16_t last_chan_freq = 0; 161 uint8_t num_ch = 0; 162 163 if (*num_channels > NUM_CHANNELS_160MHZ) { 164 dfs_err(dfs, WLAN_DEBUG_DFS, 165 "Invalid num channels: %d", *num_channels); 166 return QDF_STATUS_E_FAILURE; 167 } 168 169 for (i = 0; i < *num_channels; i++) { 170 if (freq_list[i] == 0 || 171 freq_list[i] == last_chan_freq) 172 continue; 173 if (!utils_is_dfs_chan_for_freq(dfs->dfs_pdev_obj, 174 freq_list[i])) { 175 dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip", 176 freq_list[i]); 177 continue; 178 } 179 last_chan_freq = freq_list[i]; 180 DFS_NOL_ADD_CHAN_LOCKED(dfs, 181 freq_list[i], 182 dfs->wlan_dfs_nol_timeout); 183 nol_freq_list[num_ch++] = last_chan_freq; 184 utils_dfs_deliver_event(dfs->dfs_pdev_obj, 185 freq_list[i], 186 WLAN_EV_NOL_STARTED); 187 dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL", 188 last_chan_freq); 189 } 190 191 if (!num_ch) { 192 dfs_err(dfs, WLAN_DEBUG_DFS, 193 "dfs channels not found in channel list"); 194 return QDF_STATUS_E_FAILURE; 195 } 196 *num_channels = num_ch; 197 198 utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj, 199 nol_freq_list, num_ch, 200 DFS_NOL_SET); 201 202 if (dfs->dfs_is_stadfs_enabled) 203 if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj)) 204 utils_dfs_reg_update_nol_history_chan_for_freq( 205 dfs->dfs_pdev_obj, nol_freq_list, 206 num_ch, DFS_NOL_HISTORY_SET); 207 208 dfs_nol_update(dfs); 209 utils_dfs_save_nol(dfs->dfs_pdev_obj); 210 211 return QDF_STATUS_SUCCESS; 212 } 213 #endif 214 /** 215 * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz 216 * @freq_offset: freq offset 217 * @center_freq: center frequency 218 * 219 * Find frequency offsets for 80MHz 220 * 221 * Return: None 222 */ 223 static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset, 224 uint32_t center_freq) 225 { 226 int i; 227 228 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 229 if (freq_offset->offset[i] < DFS_OFFSET_SECOND_LOWER) 230 freq_offset->freq[i] = 231 DFS_THIRD_LOWER_CHANNEL(center_freq); 232 else if ((freq_offset->offset[i] > DFS_OFFSET_SECOND_LOWER) && 233 (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER)) 234 freq_offset->freq[i] = 235 DFS_SECOND_LOWER_CHANNEL(center_freq); 236 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) && 237 (freq_offset->offset[i] < 0)) 238 freq_offset->freq[i] = 239 DFS_FIRST_LOWER_CHANNEL(center_freq); 240 else if ((freq_offset->offset[i] > 0) && 241 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER)) 242 freq_offset->freq[i] = 243 DFS_FIRST_UPPER_CHANNEL(center_freq); 244 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) && 245 (freq_offset->offset[i] < DFS_OFFSET_SECOND_UPPER)) 246 freq_offset->freq[i] = 247 DFS_SECOND_UPPER_CHANNEL(center_freq); 248 else if (freq_offset->offset[i] > DFS_OFFSET_SECOND_UPPER) 249 freq_offset->freq[i] = 250 DFS_THIRD_UPPER_CHANNEL(center_freq); 251 } 252 } 253 254 /** 255 * dfs_radar_chan_for_40()- Find frequency offsets for 40MHz 256 * @freq_offset: freq offset 257 * @center_freq: center frequency 258 * 259 * Find frequency offsets for 40MHz 260 * 261 * Return: None 262 */ 263 static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset, 264 uint32_t center_freq) 265 { 266 int i; 267 268 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 269 if (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER) 270 freq_offset->freq[i] = 271 DFS_SECOND_LOWER_CHANNEL(center_freq); 272 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) && 273 (freq_offset->offset[i] < 0)) 274 freq_offset->freq[i] = 275 DFS_FIRST_LOWER_CHANNEL(center_freq); 276 else if ((freq_offset->offset[i] > 0) && 277 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER)) 278 freq_offset->freq[i] = 279 DFS_FIRST_UPPER_CHANNEL(center_freq); 280 else if (freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) 281 freq_offset->freq[i] = 282 DFS_SECOND_UPPER_CHANNEL(center_freq); 283 } 284 } 285 286 /** 287 * dfs_radar_chan_for_20()- Find frequency offsets for 20MHz 288 * @freq_offset: freq offset 289 * @center_freq: center frequency 290 * 291 * Find frequency offsets for 20MHz 292 * 293 * Return: None 294 */ 295 static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset, 296 uint32_t center_freq) 297 { 298 int i; 299 300 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 301 if (freq_offset->offset[i] <= DFS_20MZ_OFFSET_LOWER) 302 freq_offset->freq[i] = 303 DFS_20MHZ_LOWER_CHANNEL(center_freq); 304 else if ((freq_offset->offset[i] > DFS_20MZ_OFFSET_LOWER) && 305 (freq_offset->offset[i] < DFS_20MZ_OFFSET_UPPER)) 306 freq_offset->freq[i] = center_freq; 307 else if (freq_offset->offset[i] >= DFS_20MZ_OFFSET_UPPER) 308 freq_offset->freq[i] = 309 DFS_20MHZ_UPPER_CHANNEL(center_freq); 310 } 311 } 312 313 #ifdef CONFIG_CHAN_FREQ_API 314 void 315 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, 316 struct radar_found_info *radar_found, 317 uint32_t *freq_center) 318 { 319 struct dfs_channel *curchan = dfs->dfs_curchan; 320 321 /* Radar found on agile detector ID. 322 * Applicable to chips that have a separate agile radar detector 323 * engine. 324 */ 325 if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) { 326 *freq_center = dfs->dfs_agile_precac_freq_mhz; 327 if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) { 328 if (radar_found->segment_id == PRIMARY_SEG) 329 *freq_center -= DFS_160MHZ_SECOND_SEG_OFFSET; 330 else 331 *freq_center += DFS_160MHZ_SECOND_SEG_OFFSET; 332 } else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ && 333 dfs->dfs_agile_precac_freq_mhz == 334 RESTRICTED_80P80_CHAN_CENTER_FREQ) { 335 /* 336 * The reason why left and right offsets 337 * are different. 338 * Center of 165 is 5730MHz. 339 * Center of left 80 is 5690MHz. 340 * Center of right 80 is 5775MHz. 341 */ 342 if (radar_found->segment_id == PRIMARY_SEG) 343 *freq_center -= 344 DFS_165MHZ_SECOND_SEG_OFFSET_LEFT; 345 else 346 *freq_center += 347 DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT; 348 } 349 } else if (!radar_found->segment_id) { 350 *freq_center = curchan->dfs_ch_mhz_freq_seg1; 351 } else { 352 /* Radar found on secondary segment by the HW when 353 * preCAC was running. It (dfs_precac_enable) is specific to 354 * legacy chips. 355 */ 356 if (dfs_is_precac_timer_running(dfs) && 357 dfs_is_legacy_precac_enabled(dfs)) { 358 *freq_center = dfs->dfs_precac_secondary_freq_mhz; 359 } else { 360 /* Radar found on secondary segment by the HW, when preCAC 361 * was not running in legacy chips or preCAC was running 362 * in Lithium chips. 363 */ 364 *freq_center = curchan->dfs_ch_mhz_freq_seg2; 365 if (WLAN_IS_CHAN_MODE_160(curchan)) { 366 /* If center frequency of entire 160 band 367 * is less than center frequency of primary 368 * segment, then the center frequency of 369 * secondary segment is -40 of center 370 * frequency of entire 160 segment. 371 */ 372 if (curchan->dfs_ch_mhz_freq_seg2 < 373 curchan->dfs_ch_mhz_freq_seg1) 374 *freq_center -= 375 DFS_160MHZ_SECOND_SEG_OFFSET; 376 else 377 *freq_center += 378 DFS_160MHZ_SECOND_SEG_OFFSET; 379 } 380 } 381 } 382 } 383 #else 384 #ifdef CONFIG_CHAN_NUM_API 385 static void 386 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, 387 struct radar_found_info 388 *radar_found, 389 uint32_t *freq_center) 390 { 391 struct dfs_channel *curchan = dfs->dfs_curchan; 392 /* Radar found on agile detector ID. 393 * Applicable to chips that have a separate agile radar detector 394 * engine. 395 */ 396 if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) { 397 *freq_center = utils_dfs_chan_to_freq( 398 dfs->dfs_agile_precac_freq); 399 if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ || 400 dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ) { 401 if (radar_found->segment_id == PRIMARY_SEG) 402 *freq_center -= DFS_160MHZ_SECOND_SEG_OFFSET; 403 else 404 *freq_center += DFS_160MHZ_SECOND_SEG_OFFSET; 405 } 406 /* Radar found on primary segment by the HW. */ 407 } else if (radar_found->segment_id == PRIMARY_SEG) { 408 *freq_center = utils_dfs_chan_to_freq( 409 curchan->dfs_ch_vhtop_ch_freq_seg1); 410 } else { 411 /* Radar found on secondary segment by the HW when 412 * preCAC was running. It (dfs_precac_enable) is specific to 413 * legacy chips. 414 */ 415 if (dfs_is_precac_timer_running(dfs) && 416 dfs_is_legacy_precac_enabled(dfs)) { 417 *freq_center = utils_dfs_chan_to_freq( 418 dfs->dfs_precac_secondary_freq); 419 } else { 420 /* Radar found on secondary segment by the HW, when preCAC 421 * was not running in legacy chips or preCAC was running 422 * in Lithium chips. 423 */ 424 *freq_center = utils_dfs_chan_to_freq( 425 curchan->dfs_ch_vhtop_ch_freq_seg2); 426 if (WLAN_IS_CHAN_MODE_160(curchan)) { 427 /* If center frequency of entire 160 band 428 * is less than center frequency of primary 429 * segment, then the center frequency of 430 * secondary segment is -40 of center 431 * frequency of entire 160 segment. 432 */ 433 if (curchan->dfs_ch_vhtop_ch_freq_seg2 < 434 curchan->dfs_ch_vhtop_ch_freq_seg1) 435 *freq_center -= 436 DFS_160MHZ_SECOND_SEG_OFFSET; 437 else 438 *freq_center += 439 DFS_160MHZ_SECOND_SEG_OFFSET; 440 } 441 } 442 } 443 } 444 #endif 445 #endif 446 447 /** 448 * dfs_find_radar_affected_subchans_for_freq() - Find radar affected sub chans. 449 * @dfs: Pointer to wlan_dfs structure. 450 * @radar_found: Pointer to radar_found structure. 451 * @freq_list: Pointer to save radar affected channels. 452 * @freq_center: Freq_center of the radar affected chan. 453 * 454 * Return: Number of channels. 455 */ 456 #ifdef CONFIG_CHAN_FREQ_API 457 static uint8_t 458 dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs *dfs, 459 struct radar_found_info *radar_found, 460 uint16_t *freq_list, 461 uint32_t freq_center) 462 { 463 int i, j; 464 uint8_t num_radar_subchans; 465 uint32_t flag; 466 int32_t sidx; 467 uint16_t candidate_subchan_freq; 468 uint16_t cur_subchans[NUM_CHANNELS_160MHZ]; 469 uint8_t n_cur_subchans; 470 struct dfs_channel *curchan = dfs->dfs_curchan; 471 struct freqs_offsets freq_offset; 472 473 qdf_mem_zero(&freq_offset, sizeof(freq_offset)); 474 flag = curchan->dfs_ch_flags; 475 476 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) 477 freq_offset.offset[i] = radar_found->freq_offset; 478 479 sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset); 480 481 dfs_info(dfs, WLAN_DEBUG_DFS, 482 "seg=%d, det=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d", 483 radar_found->segment_id, radar_found->detector_id, sidx, 484 radar_found->freq_offset, radar_found->is_chirp, 485 flag, freq_center); 486 487 if ((WLAN_IS_CHAN_A(curchan)) || 488 WLAN_IS_CHAN_MODE_20(curchan)) { 489 if (radar_found->is_chirp || 490 (sidx && !(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_20(&freq_offset, freq_center); 495 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 496 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 497 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 498 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 499 } 500 dfs_radar_chan_for_40(&freq_offset, freq_center); 501 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 502 WLAN_IS_CHAN_MODE_160(curchan) || 503 WLAN_IS_CHAN_MODE_80_80(curchan)) { 504 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 505 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 506 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 507 } 508 dfs_radar_chan_for_80(&freq_offset, freq_center); 509 } else { 510 dfs_err(dfs, WLAN_DEBUG_DFS, 511 "channel flag=%d is invalid", flag); 512 return 0; 513 } 514 515 n_cur_subchans = 516 dfs_get_bonding_channels_for_freq(dfs, curchan, 517 radar_found->segment_id, 518 radar_found->detector_id, 519 cur_subchans); 520 521 for (i = 0, num_radar_subchans = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 522 candidate_subchan_freq = freq_offset.freq[i]; 523 for (j = 0; j < n_cur_subchans; j++) { 524 if (cur_subchans[j] == candidate_subchan_freq) { 525 freq_list[num_radar_subchans++] = 526 candidate_subchan_freq; 527 dfs_info(dfs, WLAN_DEBUG_DFS, 528 "offset=%d, channel=%d", 529 num_radar_subchans, 530 freq_list[num_radar_subchans - 1]); 531 break; 532 } 533 } 534 } 535 return num_radar_subchans; 536 } 537 #endif 538 539 #ifdef CONFIG_CHAN_NUM_API 540 uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, 541 uint8_t *channels) 542 { 543 uint8_t center_chan; 544 uint8_t nchannels = 0; 545 546 center_chan = chan->dfs_ch_vhtop_ch_freq_seg1; 547 548 if (WLAN_IS_CHAN_MODE_20(chan)) { 549 nchannels = 1; 550 channels[0] = center_chan; 551 } else if (WLAN_IS_CHAN_MODE_40(chan)) { 552 nchannels = 2; 553 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 554 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 555 } else if (WLAN_IS_CHAN_MODE_80(chan)) { 556 nchannels = 4; 557 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 558 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 559 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 560 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 561 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { 562 nchannels = 8; 563 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 564 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 565 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 566 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 567 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 568 channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 569 channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 570 channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 571 channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 572 } else if (WLAN_IS_CHAN_MODE_160(chan)) { 573 nchannels = 8; 574 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 575 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 576 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 577 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 578 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 579 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 580 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 581 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 582 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 583 } 584 585 return nchannels; 586 } 587 #endif 588 589 /* 590 * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding frequency 591 * list. 592 * @chan: Pointer to dfs_channel. 593 * @freq_list: Pointer to frequency list. 594 */ 595 #ifdef CONFIG_CHAN_FREQ_API 596 uint8_t 597 dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan, 598 uint16_t *freq_list) 599 { 600 uint16_t center_freq; 601 uint8_t nchannels = 0; 602 603 center_freq = chan->dfs_ch_mhz_freq_seg1; 604 605 if (WLAN_IS_CHAN_MODE_20(chan)) { 606 nchannels = 1; 607 freq_list[0] = center_freq; 608 } else if (WLAN_IS_CHAN_MODE_40(chan)) { 609 nchannels = 2; 610 freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 611 freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 612 } else if (WLAN_IS_CHAN_MODE_80(chan)) { 613 nchannels = 4; 614 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 615 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 616 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 617 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 618 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { 619 nchannels = 8; 620 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 621 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 622 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 623 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 624 center_freq = chan->dfs_ch_mhz_freq_seg2; 625 freq_list[4] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 626 freq_list[5] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 627 freq_list[6] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 628 freq_list[7] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 629 } else if (WLAN_IS_CHAN_MODE_160(chan)) { 630 nchannels = 8; 631 center_freq = chan->dfs_ch_mhz_freq_seg2; 632 freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 633 freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 634 freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 635 freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 636 freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 637 freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 638 freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 639 freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 640 } 641 642 return nchannels; 643 } 644 #endif 645 646 #ifdef CONFIG_CHAN_FREQ_API 647 /* 648 * dfs_get_80mhz_bonding_channels() - Get bonding frequency list of 80MHz 649 * channel. 650 * @center_freq: Center frequency of the 80MHz channel. 651 * @freq_list: Pointer to frequency list. 652 */ 653 static 654 void dfs_get_80mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list) 655 { 656 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 657 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 658 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 659 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 660 } 661 662 /* 663 * dfs_get_160mhz_bonding_channels() - Get bonding frequency list of 160MHz 664 * channel. 665 * @center_freq: Center frequency of the 160MHz channel. 666 * @freq_list: Pointer to frequency list. 667 */ 668 static 669 void dfs_get_160mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list) 670 { 671 freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 672 freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 673 freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 674 freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 675 freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 676 freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 677 freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 678 freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 679 } 680 681 /* 682 * dfs_get_agile_subchans_for_curchan_160() - Get bonding frequency list of 683 * agile channels when current operating channel is 160MHz. 684 * 685 * @dfs: Pointer to DFS structure. 686 * @center_freq: Center frequency of the channel. 687 * @segment_id: Segment ID of interest. 0 for primary segment and 1 for 688 * secondary segment. 689 * @freq_list: Pointer to frequency list. 690 * @nchannels: Number of subchannel. 691 */ 692 static void 693 dfs_get_agile_subchans_for_curchan_160(struct wlan_dfs *dfs, 694 uint16_t center_freq, 695 uint32_t segment_id, 696 uint16_t *freq_list, 697 uint8_t *nchannels) 698 { 699 if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) { 700 /* 701 * The current operating channel is 160MHz and 702 * the agile channel is 80MHz. This can happen 703 * in HK only. 704 */ 705 *nchannels = 4; 706 dfs_get_80mhz_bonding_channels(center_freq, 707 freq_list); 708 } else if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) 709 /* 710 * The current operating channel is 160MHz and 711 * the agile channel is 160MHz. 712 * Pine ADFS specific. 713 */ 714 dfs_get_160mhz_bonding_channels(center_freq, 715 freq_list); 716 else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ) { 717 /* 718 * The current operating channel is 160MHz and the agile channel 719 * is 165MHz(restricted 80P80MHZ). Pine ADFS specific. 720 * If the segment id is primary segment 0, shift the center 721 * frequency 5730MHz to the center of left 80MHz segment 5690MHz 722 * and add the subchannels of the left 80MHz segment. 723 * If the segment id is secondary segment 1, shift the center 724 * frequency 5730MHz to the center of right 80MHz segment 725 * 5775MHz and add the subchannels of the right 80MHz segment. 726 */ 727 *nchannels = 4; 728 center_freq = (segment_id) ? 729 (center_freq + DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT) : 730 (center_freq - DFS_165MHZ_SECOND_SEG_OFFSET_LEFT); 731 dfs_get_80mhz_bonding_channels(center_freq, 732 freq_list); 733 } 734 } 735 736 /* 737 * dfs_get_bonding_channels_for_freq() - Get bonding channel frequency. 738 * @dfs: Pointer to wlan_dfs. 739 * @curchan: Pointer to dfs_channel. 740 * @segment_id: Segment ID. 741 * @detector_id: Detector ID. 742 * @freq_list: Pointer to frequency list. 743 */ 744 uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs, 745 struct dfs_channel *curchan, 746 uint32_t segment_id, 747 uint8_t detector_id, 748 uint16_t *freq_list) 749 { 750 uint16_t center_freq; 751 uint8_t nchannels = 0; 752 753 if (detector_id == dfs_get_agile_detector_id(dfs)) 754 center_freq = dfs->dfs_agile_precac_freq_mhz; 755 else if (!segment_id) 756 center_freq = curchan->dfs_ch_mhz_freq_seg1; 757 else { 758 /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is 759 * zero and "dfs_precac_secondary_freq" holds the secondary 760 * frequency. 761 */ 762 if (dfs_is_legacy_precac_enabled(dfs) && 763 dfs_is_precac_timer_running(dfs)) 764 center_freq = dfs->dfs_precac_secondary_freq_mhz; 765 else 766 center_freq = curchan->dfs_ch_mhz_freq_seg2; 767 } 768 769 if (WLAN_IS_CHAN_MODE_20(curchan)) { 770 nchannels = 1; 771 freq_list[0] = center_freq; 772 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 773 nchannels = 2; 774 freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 775 freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 776 } else if (WLAN_IS_CHAN_MODE_80(curchan)) { 777 nchannels = 4; 778 dfs_get_80mhz_bonding_channels(center_freq, freq_list); 779 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 780 nchannels = 8; 781 if (detector_id == dfs_get_agile_detector_id(dfs)) 782 dfs_get_agile_subchans_for_curchan_160(dfs, 783 center_freq, 784 segment_id, 785 freq_list, 786 &nchannels); 787 else 788 dfs_get_160mhz_bonding_channels(center_freq, freq_list); 789 } else if (WLAN_IS_CHAN_MODE_80_80(curchan)) { 790 /* 791 * If the current channel's bandwidth is 80P80MHz, 792 * the corresponding agile Detector's bandwidth will be 160MHz 793 * in case of Pine ADFS. 794 */ 795 if (detector_id == dfs_get_agile_detector_id(dfs)) { 796 if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) { 797 nchannels = 8; 798 dfs_get_160mhz_bonding_channels(center_freq, 799 freq_list); 800 } else if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) { 801 nchannels = 4; 802 dfs_get_80mhz_bonding_channels(center_freq, 803 freq_list); 804 } else { 805 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 806 "Incorrect precac width %u", 807 dfs->dfs_precac_chwidth); 808 } 809 } else { 810 /* 811 * If the radar is getting detected in 80P80MHz home 812 * channel, only the 80MHz segment that is infected with 813 * radar is of interest. The other 80MHz segment is 814 * ignored. The center frequency of the radar infected 815 * segment is dfs_ch_mhz_freq_seg1 if primary and 816 * dfs_ch_mhz_freq_seg2 in case of secondary. 817 */ 818 nchannels = 4; 819 dfs_get_80mhz_bonding_channels(center_freq, freq_list); 820 } 821 } 822 823 return nchannels; 824 } 825 #endif 826 827 #ifdef CONFIG_CHAN_NUM_API 828 uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, 829 struct dfs_channel *curchan, 830 uint32_t segment_id, 831 uint8_t detector_id, 832 uint8_t *channels) 833 { 834 uint8_t center_chan; 835 uint8_t nchannels = 0; 836 837 if (detector_id == dfs_get_agile_detector_id(dfs)) 838 center_chan = dfs->dfs_agile_precac_freq; 839 else if (!segment_id) 840 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1; 841 else { 842 /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is 843 * zero and "dfs_precac_secondary_freq" holds the secondary 844 * frequency in case of legacy chips. 845 * For chips that support a separate agile detector engine, 846 * "dfs_agile_precac_freq" holds the frequency that agile 847 * engine operates on. 848 * 849 * In case of radar detected by the HW in the secondary 80 850 * channel,"dfs_ch_vhtop_ch_freq_seg2" holds the secondary 851 * segment center frequency in the below cases: 852 * 1. preCAC timer is running in chips that support separate 853 * agile engines. 854 * 2. preCAC timer is not running. 855 */ 856 if (dfs_is_precac_timer_running(dfs) && 857 dfs_is_legacy_precac_enabled(dfs)) 858 center_chan = dfs->dfs_precac_secondary_freq; 859 else 860 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 861 } 862 863 if (WLAN_IS_CHAN_MODE_20(curchan)) { 864 nchannels = 1; 865 channels[0] = center_chan; 866 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 867 nchannels = 2; 868 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 869 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 870 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 871 WLAN_IS_CHAN_MODE_80_80(curchan) || 872 detector_id == dfs_get_agile_detector_id(dfs)) { 873 /* If the current channel's bandwidth is 80/80+80/160Mhz, 874 * the corresponding agile Detector's bandwidth will be 80Mhz. 875 * Therefore, if radar is found on the agile detector find 876 * subchannels for 80Mhz bandwidth. 877 */ 878 nchannels = 4; 879 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 880 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 881 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 882 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 883 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 884 nchannels = 8; 885 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 886 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 887 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 888 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 889 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 890 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 891 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 892 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 893 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 894 } 895 896 return nchannels; 897 } 898 #endif 899 900 void dfs_reset_bangradar(struct wlan_dfs *dfs) 901 { 902 dfs->dfs_bangradar_type = DFS_NO_BANGRADAR; 903 } 904 905 /** 906 * dfs_radar_found_event_basic_sanity() - Check if radar event is received on a 907 * DFS channel. 908 * @dfs: Pointer to wlan_dfs structure. 909 * @chan: Current channel. 910 * 911 * Return: If a radar event found on NON-DFS channel return false. Otherwise, 912 * return true. 913 */ 914 static 915 bool dfs_radar_found_event_basic_sanity(struct wlan_dfs *dfs, 916 struct dfs_channel *chan) 917 { 918 if (!chan) { 919 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 920 "dfs->dfs_curchan is NULL"); 921 return false; 922 } 923 924 if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) { 925 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, 926 "radar event on non-DFS chan"); 927 return false; 928 } 929 930 return true; 931 } 932 933 void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs) 934 { 935 qdf_timer_stop(&dfs->wlan_dfstesttimer); 936 dfs->wlan_dfstest = 1; 937 dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee; 938 dfs->wlan_dfstesttime = 1; /* 1ms */ 939 qdf_timer_mod(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime); 940 } 941 942 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs) 943 { 944 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 945 946 return 0; 947 } 948 949 #if defined(WLAN_DFS_TRUE_160MHZ_SUPPORT) && defined(WLAN_DFS_FULL_OFFLOAD) 950 void dfs_translate_radar_params(struct wlan_dfs *dfs, 951 struct radar_found_info *radar_found) 952 { 953 struct dfs_channel *curchan = dfs->dfs_curchan; 954 bool is_primary_ch_right_of_center = false; 955 956 if (!dfs_is_true_160mhz_supported(dfs)) 957 return; 958 959 if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) { 960 dfs_translate_radar_params_for_agile_chan(dfs, radar_found); 961 return; 962 } 963 964 /* Is the primary channel ( or primary 80 segment) to the right 965 * of the center of 160/165Mhz channel. 966 */ 967 if (curchan->dfs_ch_freq > curchan->dfs_ch_mhz_freq_seg2) 968 is_primary_ch_right_of_center = true; 969 970 if (WLAN_IS_CHAN_MODE_160(curchan)) { 971 if (radar_found->freq_offset > 0) { 972 /* Offset positive: Equivalent to Upper IEEE 973 * 80Mhz chans Synthesizer. 974 */ 975 if (!is_primary_ch_right_of_center) 976 radar_found->segment_id = SEG_ID_SECONDARY; 977 radar_found->freq_offset -= 978 DFS_160MHZ_SECOND_SEG_OFFSET; 979 } else { 980 /* Offset negative: Equivalent to Lower IEEE 981 * 80Mhz chans Synthesizer. 982 */ 983 if (is_primary_ch_right_of_center) 984 radar_found->segment_id = SEG_ID_SECONDARY; 985 radar_found->freq_offset += 986 DFS_160MHZ_SECOND_SEG_OFFSET; 987 } 988 } else if (WLAN_IS_CHAN_MODE_165(dfs, curchan)) { 989 /* If offset is greater than 40MHz, radar is found on the 990 * secondary segment. 991 */ 992 if (abs(radar_found->freq_offset) > 40) { 993 radar_found->segment_id = SEG_ID_SECONDARY; 994 /* Update the freq. offset with respect to the 995 * secondary segment center freq. 996 */ 997 if (is_primary_ch_right_of_center) 998 radar_found->freq_offset += 999 DFS_80P80MHZ_SECOND_SEG_OFFSET; 1000 else 1001 radar_found->freq_offset -= 1002 DFS_80P80MHZ_SECOND_SEG_OFFSET; 1003 } 1004 } 1005 } 1006 #endif /* WLAN_DFS_TRUE_160MHZ_SUPPORT */ 1007 1008 /** 1009 * dfs_radar_action_for_hw_mode_switch()- Radar cannot be processed when HW 1010 * switch is in progress. So save the radar found parameters for 1011 * future processing. 1012 * @dfs: Pointer to wlan_dfs structure. 1013 * @radar_found: Pointer to radar found structure. 1014 * 1015 * Return: QDF_STATUS 1016 */ 1017 static QDF_STATUS 1018 dfs_radar_action_for_hw_mode_switch(struct wlan_dfs *dfs, 1019 struct radar_found_info *radar_found) 1020 { 1021 struct radar_found_info *radar_params = NULL; 1022 1023 radar_params = qdf_mem_malloc(sizeof(*radar_params)); 1024 if (!radar_params) 1025 return QDF_STATUS_E_NOMEM; 1026 1027 /* If CAC timer is running, cancel it here rather than 1028 * after processing to avoid handling unnecessary CAC timeouts. 1029 */ 1030 if (dfs->dfs_cac_timer_running) 1031 dfs_cac_stop(dfs); 1032 1033 /* If CAC timer is to be handled after mode switch and then 1034 * we receive radar, no point in handling CAC completion. 1035 */ 1036 if (dfs->dfs_defer_params.is_cac_completed) 1037 dfs->dfs_defer_params.is_cac_completed = false; 1038 qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params)); 1039 dfs->dfs_defer_params.radar_params = radar_params; 1040 dfs->dfs_defer_params.is_radar_detected = true; 1041 1042 return QDF_STATUS_SUCCESS; 1043 } 1044 1045 #ifdef CONFIG_CHAN_FREQ_API 1046 uint8_t 1047 dfs_find_radar_affected_channels(struct wlan_dfs *dfs, 1048 struct radar_found_info *radar_found, 1049 uint16_t *freq_list, 1050 uint32_t freq_center) 1051 { 1052 uint8_t num_channels; 1053 1054 if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS) 1055 num_channels = 1056 dfs_get_bonding_channel_without_seg_info_for_freq 1057 (dfs->dfs_curchan, freq_list); 1058 /* BW reduction is dependent on subchannel marking */ 1059 else if ((dfs->dfs_use_nol_subchannel_marking) && 1060 (!(dfs->dfs_bangradar_type) || 1061 (dfs->dfs_bangradar_type == 1062 DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS))) 1063 num_channels = 1064 dfs_find_radar_affected_subchans_for_freq(dfs, 1065 radar_found, 1066 freq_list, 1067 freq_center); 1068 else 1069 num_channels = dfs_get_bonding_channels_for_freq 1070 (dfs, 1071 dfs->dfs_curchan, 1072 radar_found->segment_id, 1073 radar_found->detector_id, 1074 freq_list); 1075 1076 return num_channels; 1077 } 1078 1079 #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) || \ 1080 defined(QCA_SUPPORT_ADFS_RCAC) 1081 /** 1082 * dfs_is_radarsource_agile() - Indicates whether the radar event is received 1083 * on the agile channel. 1084 * @dfs: Pointer to wlan_dfs structure. 1085 * @radar_found: Pointer to radar_found_info structure. 1086 * 1087 * Return: QDF_STATUS 1088 */ 1089 static 1090 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs, 1091 struct radar_found_info *radar_found) 1092 { 1093 bool is_radar_from_agile_dfs = 1094 ((dfs_is_agile_precac_enabled(dfs) && 1095 dfs_is_precac_timer_running(dfs)) || 1096 dfs_is_agile_rcac_enabled(dfs)) && 1097 (radar_found->detector_id == dfs_get_agile_detector_id(dfs)); 1098 bool is_radar_from_zero_wait_dfs = 1099 (dfs_is_legacy_precac_enabled(dfs) && 1100 dfs_is_precac_timer_running(dfs) && 1101 (radar_found->segment_id == SEG_ID_SECONDARY)); 1102 1103 dfs_debug(dfs, WLAN_DEBUG_DFS_AGILE, 1104 "radar on PreCAC segment: ADFS:%d Zero Wait DFS:%d", 1105 is_radar_from_agile_dfs, 1106 is_radar_from_zero_wait_dfs); 1107 1108 return (is_radar_from_agile_dfs || is_radar_from_zero_wait_dfs); 1109 } 1110 #else 1111 static 1112 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs, 1113 struct radar_found_info *radar_found) 1114 { 1115 return false; 1116 } 1117 #endif 1118 1119 QDF_STATUS 1120 dfs_process_radar_ind(struct wlan_dfs *dfs, 1121 struct radar_found_info *radar_found) 1122 { 1123 QDF_STATUS status; 1124 1125 /* Acquire a lock to avoid initiating mode switch till radar 1126 * processing is completed. 1127 */ 1128 DFS_RADAR_MODE_SWITCH_LOCK(dfs); 1129 1130 if (utils_dfs_can_ignore_radar_event(dfs->dfs_pdev_obj)) { 1131 DFS_RADAR_MODE_SWITCH_UNLOCK(dfs); 1132 return QDF_STATUS_SUCCESS; 1133 } 1134 1135 /* Before processing radar, check if HW mode switch is in progress. 1136 * If in progress, defer the processing of radar event received till 1137 * the mode switch is completed. 1138 */ 1139 if (dfs_is_hw_mode_switch_in_progress(dfs)) 1140 status = dfs_radar_action_for_hw_mode_switch(dfs, radar_found); 1141 else if (dfs_is_radarsource_agile(dfs, radar_found)) 1142 status = dfs_process_radar_ind_on_agile_chan(dfs, radar_found); 1143 else 1144 status = dfs_process_radar_ind_on_home_chan(dfs, radar_found); 1145 1146 DFS_RADAR_MODE_SWITCH_UNLOCK(dfs); 1147 1148 return status; 1149 } 1150 1151 QDF_STATUS 1152 dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs, 1153 struct radar_found_info *radar_found) 1154 { 1155 bool wait_for_csa = false; 1156 uint16_t freq_list[NUM_CHANNELS_160MHZ]; 1157 uint16_t nol_freq_list[NUM_CHANNELS_160MHZ]; 1158 uint8_t num_channels; 1159 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1160 uint32_t freq_center; 1161 uint32_t radarfound_freq; 1162 struct dfs_channel *dfs_curchan; 1163 1164 dfs_curchan = dfs->dfs_curchan; 1165 1166 /* Check if the current channel is a non DFS channel 1167 * If the current channel is non-DFS and the radar is from Agile 1168 * Detector we need to process it since Agile Detector has a 1169 * different channel. 1170 */ 1171 if (!dfs_radar_found_event_basic_sanity(dfs, dfs_curchan)) 1172 goto exit; 1173 1174 dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center); 1175 radarfound_freq = freq_center + radar_found->freq_offset; 1176 1177 if (radar_found->segment_id == SEG_ID_SECONDARY) 1178 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, 1179 "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.", 1180 radarfound_freq, freq_center); 1181 else 1182 dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS, 1183 "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.", 1184 utils_dfs_freq_to_chan(radarfound_freq), 1185 radarfound_freq, dfs_curchan->dfs_ch_ieee, 1186 dfs_curchan->dfs_ch_freq); 1187 1188 utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq, 1189 WLAN_EV_RADAR_DETECTED); 1190 1191 if (!dfs->dfs_use_nol) { 1192 dfs_reset_bangradar(dfs); 1193 dfs_send_csa_to_current_chan(dfs); 1194 status = QDF_STATUS_SUCCESS; 1195 goto exit; 1196 } 1197 num_channels = dfs_find_radar_affected_channels(dfs, 1198 radar_found, 1199 freq_list, 1200 freq_center); 1201 1202 dfs_reset_bangradar(dfs); 1203 1204 status = dfs_radar_add_channel_list_to_nol_for_freq(dfs, 1205 freq_list, 1206 nol_freq_list, 1207 &num_channels); 1208 if (QDF_IS_STATUS_ERROR(status)) { 1209 dfs_err(dfs, WLAN_DEBUG_DFS, 1210 "radar event received on invalid channel"); 1211 goto exit; 1212 } 1213 1214 /* 1215 * If precac is running and the radar found in secondary 1216 * VHT80 mark the channel as radar and add to NOL list. 1217 * Otherwise random channel selection can choose this 1218 * channel. 1219 */ 1220 dfs_debug(dfs, WLAN_DEBUG_DFS, 1221 "found_on_second=%d is_pre=%d", 1222 dfs->is_radar_found_on_secondary_seg, 1223 dfs_is_precac_timer_running(dfs)); 1224 /* 1225 * Even if radar found on primary, we need to mark the channel as NOL 1226 * in preCAC list. The preCAC list also maintains the current CAC 1227 * channels as part of pre-cleared DFS. Hence call the API 1228 * to mark channels as NOL irrespective of preCAC being enabled or not. 1229 */ 1230 1231 dfs_debug(dfs, WLAN_DEBUG_DFS, 1232 "Radar found on dfs detector: %d", radar_found->detector_id); 1233 dfs_mark_precac_nol_for_freq(dfs, 1234 dfs->is_radar_found_on_secondary_seg, 1235 radar_found->detector_id, 1236 nol_freq_list, 1237 num_channels); 1238 1239 dfs_send_nol_ie_and_rcsa(dfs, 1240 radar_found, 1241 nol_freq_list, 1242 num_channels, 1243 &wait_for_csa); 1244 1245 if (!dfs->dfs_is_offload_enabled && 1246 dfs->is_radar_found_on_secondary_seg) { 1247 dfs_second_segment_radar_disable(dfs); 1248 dfs->is_radar_found_on_secondary_seg = 0; 1249 1250 if (dfs->is_radar_during_precac) { 1251 dfs->is_radar_during_precac = 0; 1252 goto exit; 1253 } 1254 } 1255 1256 /* 1257 * XXX TODO: the umac NOL code isn't used, but 1258 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac 1259 * NOL code isn't used, that flag is never cleared. This 1260 * needs to be fixed. See EV 105776. 1261 */ 1262 if (wait_for_csa) 1263 goto exit; 1264 1265 /* 1266 * EV 129487 : We have detected radar in the channel, 1267 * stop processing PHY error data as this can cause 1268 * false detect in the new channel while channel 1269 * change is in progress. 1270 */ 1271 1272 if (!dfs->dfs_is_offload_enabled) { 1273 dfs_radar_disable(dfs); 1274 dfs_second_segment_radar_disable(dfs); 1275 } 1276 1277 dfs_mlme_mark_dfs(dfs->dfs_pdev_obj, 1278 dfs->dfs_curchan->dfs_ch_ieee, 1279 dfs->dfs_curchan->dfs_ch_freq, 1280 dfs->dfs_curchan->dfs_ch_mhz_freq_seg2, 1281 dfs->dfs_curchan->dfs_ch_flags); 1282 1283 exit: 1284 return status; 1285 } 1286 #endif 1287