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 } else if (!radar_found->segment_id) { 328 *freq_center = curchan->dfs_ch_mhz_freq_seg1; 329 } else { 330 /* Radar found on secondary segment by the HW when 331 * preCAC was running. It (dfs_precac_enable) is specific to 332 * legacy chips. 333 */ 334 if (dfs_is_precac_timer_running(dfs) && 335 dfs_is_legacy_precac_enabled(dfs)) { 336 *freq_center = dfs->dfs_precac_secondary_freq_mhz; 337 } else { 338 /* Radar found on secondary segment by the HW, when preCAC 339 * was not running in legacy chips or preCAC was running 340 * in Lithium chips. 341 */ 342 *freq_center = curchan->dfs_ch_mhz_freq_seg2; 343 if (WLAN_IS_CHAN_MODE_160(curchan)) { 344 /* If center frequency of entire 160 band 345 * is less than center frequency of primary 346 * segment, then the center frequency of 347 * secondary segment is -40 of center 348 * frequency of entire 160 segment. 349 */ 350 if (curchan->dfs_ch_mhz_freq_seg2 < 351 curchan->dfs_ch_mhz_freq_seg1) 352 *freq_center -= 353 DFS_160MHZ_SECOND_SEG_OFFSET; 354 else 355 *freq_center += 356 DFS_160MHZ_SECOND_SEG_OFFSET; 357 } 358 } 359 } 360 } 361 #else 362 #ifdef CONFIG_CHAN_NUM_API 363 static void 364 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, 365 struct radar_found_info 366 *radar_found, 367 uint32_t *freq_center) 368 { 369 struct dfs_channel *curchan = dfs->dfs_curchan; 370 /* Radar found on agile detector ID. 371 * Applicable to chips that have a separate agile radar detector 372 * engine. 373 */ 374 if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) { 375 *freq_center = utils_dfs_chan_to_freq( 376 dfs->dfs_agile_precac_freq); 377 if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ || 378 dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ) { 379 if (radar_found->segment_id == PRIMARY_SEG) 380 *freq_center -= DFS_160MHZ_SECOND_SEG_OFFSET; 381 else 382 *freq_center += DFS_160MHZ_SECOND_SEG_OFFSET; 383 } 384 /* Radar found on primary segment by the HW. */ 385 } else if (radar_found->segment_id == PRIMARY_SEG) { 386 *freq_center = utils_dfs_chan_to_freq( 387 curchan->dfs_ch_vhtop_ch_freq_seg1); 388 } else { 389 /* Radar found on secondary segment by the HW when 390 * preCAC was running. It (dfs_precac_enable) is specific to 391 * legacy chips. 392 */ 393 if (dfs_is_precac_timer_running(dfs) && 394 dfs_is_legacy_precac_enabled(dfs)) { 395 *freq_center = utils_dfs_chan_to_freq( 396 dfs->dfs_precac_secondary_freq); 397 } else { 398 /* Radar found on secondary segment by the HW, when preCAC 399 * was not running in legacy chips or preCAC was running 400 * in Lithium chips. 401 */ 402 *freq_center = utils_dfs_chan_to_freq( 403 curchan->dfs_ch_vhtop_ch_freq_seg2); 404 if (WLAN_IS_CHAN_MODE_160(curchan)) { 405 /* If center frequency of entire 160 band 406 * is less than center frequency of primary 407 * segment, then the center frequency of 408 * secondary segment is -40 of center 409 * frequency of entire 160 segment. 410 */ 411 if (curchan->dfs_ch_vhtop_ch_freq_seg2 < 412 curchan->dfs_ch_vhtop_ch_freq_seg1) 413 *freq_center -= 414 DFS_160MHZ_SECOND_SEG_OFFSET; 415 else 416 *freq_center += 417 DFS_160MHZ_SECOND_SEG_OFFSET; 418 } 419 } 420 } 421 } 422 #endif 423 #endif 424 425 /** 426 * dfs_find_radar_affected_subchans_for_freq() - Find radar affected sub chans. 427 * @dfs: Pointer to wlan_dfs structure. 428 * @radar_found: Pointer to radar_found structure. 429 * @freq_list: Pointer to save radar affected channels. 430 * @freq_center: Freq_center of the radar affected chan. 431 * 432 * Return: Number of channels. 433 */ 434 #ifdef CONFIG_CHAN_FREQ_API 435 static uint8_t 436 dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs *dfs, 437 struct radar_found_info *radar_found, 438 uint16_t *freq_list, 439 uint32_t freq_center) 440 { 441 int i, j; 442 uint8_t num_radar_subchans; 443 uint32_t flag; 444 int32_t sidx; 445 uint16_t candidate_subchan_freq; 446 uint16_t cur_subchans[NUM_CHANNELS_160MHZ]; 447 uint8_t n_cur_subchans; 448 struct dfs_channel *curchan = dfs->dfs_curchan; 449 struct freqs_offsets freq_offset; 450 451 qdf_mem_zero(&freq_offset, sizeof(freq_offset)); 452 flag = curchan->dfs_ch_flags; 453 454 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) 455 freq_offset.offset[i] = radar_found->freq_offset; 456 457 sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset); 458 459 dfs_info(dfs, WLAN_DEBUG_DFS, 460 "seg=%d, det=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d", 461 radar_found->segment_id, radar_found->detector_id, sidx, 462 radar_found->freq_offset, radar_found->is_chirp, 463 flag, freq_center); 464 465 if ((WLAN_IS_CHAN_A(curchan)) || 466 WLAN_IS_CHAN_MODE_20(curchan)) { 467 if (radar_found->is_chirp || 468 (sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) { 469 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 470 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 471 } 472 dfs_radar_chan_for_20(&freq_offset, freq_center); 473 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 474 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 475 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 476 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 477 } 478 dfs_radar_chan_for_40(&freq_offset, freq_center); 479 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 480 WLAN_IS_CHAN_MODE_160(curchan) || 481 WLAN_IS_CHAN_MODE_80_80(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_80(&freq_offset, freq_center); 487 } else { 488 dfs_err(dfs, WLAN_DEBUG_DFS, 489 "channel flag=%d is invalid", flag); 490 return 0; 491 } 492 493 n_cur_subchans = 494 dfs_get_bonding_channels_for_freq(dfs, curchan, 495 radar_found->segment_id, 496 radar_found->detector_id, 497 cur_subchans); 498 499 for (i = 0, num_radar_subchans = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 500 candidate_subchan_freq = freq_offset.freq[i]; 501 for (j = 0; j < n_cur_subchans; j++) { 502 if (cur_subchans[j] == candidate_subchan_freq) { 503 freq_list[num_radar_subchans++] = 504 candidate_subchan_freq; 505 dfs_info(dfs, WLAN_DEBUG_DFS, 506 "offset=%d, channel=%d", 507 num_radar_subchans, 508 freq_list[num_radar_subchans - 1]); 509 break; 510 } 511 } 512 } 513 return num_radar_subchans; 514 } 515 #endif 516 517 #ifdef CONFIG_CHAN_NUM_API 518 uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, 519 uint8_t *channels) 520 { 521 uint8_t center_chan; 522 uint8_t nchannels = 0; 523 524 center_chan = chan->dfs_ch_vhtop_ch_freq_seg1; 525 526 if (WLAN_IS_CHAN_MODE_20(chan)) { 527 nchannels = 1; 528 channels[0] = center_chan; 529 } else if (WLAN_IS_CHAN_MODE_40(chan)) { 530 nchannels = 2; 531 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 532 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 533 } else if (WLAN_IS_CHAN_MODE_80(chan)) { 534 nchannels = 4; 535 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 536 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 537 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 538 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 539 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { 540 nchannels = 8; 541 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 542 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 543 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 544 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 545 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 546 channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 547 channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 548 channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 549 channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 550 } else if (WLAN_IS_CHAN_MODE_160(chan)) { 551 nchannels = 8; 552 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 553 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 554 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 555 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 556 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 557 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 558 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 559 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 560 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 561 } 562 563 return nchannels; 564 } 565 #endif 566 567 /* 568 * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding frequency 569 * list. 570 * @chan: Pointer to dfs_channel. 571 * @freq_list: Pointer to frequency list. 572 */ 573 #ifdef CONFIG_CHAN_FREQ_API 574 uint8_t 575 dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan, 576 uint16_t *freq_list) 577 { 578 uint16_t center_freq; 579 uint8_t nchannels = 0; 580 581 center_freq = chan->dfs_ch_mhz_freq_seg1; 582 583 if (WLAN_IS_CHAN_MODE_20(chan)) { 584 nchannels = 1; 585 freq_list[0] = center_freq; 586 } else if (WLAN_IS_CHAN_MODE_40(chan)) { 587 nchannels = 2; 588 freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 589 freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 590 } else if (WLAN_IS_CHAN_MODE_80(chan)) { 591 nchannels = 4; 592 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 593 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 594 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 595 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 596 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { 597 nchannels = 8; 598 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 599 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 600 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 601 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 602 center_freq = chan->dfs_ch_mhz_freq_seg2; 603 freq_list[4] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 604 freq_list[5] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 605 freq_list[6] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 606 freq_list[7] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 607 } else if (WLAN_IS_CHAN_MODE_160(chan)) { 608 nchannels = 8; 609 center_freq = chan->dfs_ch_mhz_freq_seg2; 610 freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 611 freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 612 freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 613 freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 614 freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 615 freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 616 freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 617 freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 618 } 619 620 return nchannels; 621 } 622 #endif 623 624 /* 625 * dfs_get_bonding_channels_for_freq() - Get bonding channel frequency. 626 * @dfs: Pointer to wlan_dfs. 627 * @curchan: Pointer to dfs_channel. 628 * @segment_id: Segment ID. 629 * @detector_id: Detector ID. 630 * @freq_list: Pointer to frequency list. 631 */ 632 #ifdef CONFIG_CHAN_FREQ_API 633 uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs, 634 struct dfs_channel *curchan, 635 uint32_t segment_id, 636 uint8_t detector_id, 637 uint16_t *freq_list) 638 { 639 uint16_t center_freq; 640 uint8_t nchannels = 0; 641 642 if (detector_id == dfs_get_agile_detector_id(dfs)) 643 center_freq = dfs->dfs_agile_precac_freq_mhz; 644 else if (!segment_id) 645 center_freq = curchan->dfs_ch_mhz_freq_seg1; 646 else { 647 /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is 648 * zero and "dfs_precac_secondary_freq" holds the secondary 649 * frequency. 650 */ 651 if (dfs_is_precac_timer_running(dfs)) 652 center_freq = dfs->dfs_precac_secondary_freq_mhz; 653 else 654 center_freq = curchan->dfs_ch_mhz_freq_seg2; 655 } 656 657 if (WLAN_IS_CHAN_MODE_20(curchan)) { 658 nchannels = 1; 659 freq_list[0] = center_freq; 660 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 661 nchannels = 2; 662 freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 663 freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 664 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 665 WLAN_IS_CHAN_MODE_80_80(curchan) || 666 detector_id == dfs_get_agile_detector_id(dfs)) { 667 /* If the current channel's bandwidth is 80/80+80/160Mhz, 668 * the corresponding agile Detector's bandwidth will be 80Mhz. 669 * Therefore, if radar is found on the agile detector find 670 * subchannels for 80Mhz bandwidth. 671 */ 672 nchannels = 4; 673 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 674 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 675 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 676 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 677 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 678 nchannels = 8; 679 center_freq = curchan->dfs_ch_mhz_freq_seg2; 680 freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 681 freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 682 freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 683 freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 684 freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 685 freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 686 freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 687 freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 688 } 689 690 return nchannels; 691 } 692 #endif 693 694 #ifdef CONFIG_CHAN_NUM_API 695 uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, 696 struct dfs_channel *curchan, 697 uint32_t segment_id, 698 uint8_t detector_id, 699 uint8_t *channels) 700 { 701 uint8_t center_chan; 702 uint8_t nchannels = 0; 703 704 if (detector_id == dfs_get_agile_detector_id(dfs)) 705 center_chan = dfs->dfs_agile_precac_freq; 706 else if (!segment_id) 707 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1; 708 else { 709 /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is 710 * zero and "dfs_precac_secondary_freq" holds the secondary 711 * frequency in case of legacy chips. 712 * For chips that support a separate agile detector engine, 713 * "dfs_agile_precac_freq" holds the frequency that agile 714 * engine operates on. 715 * 716 * In case of radar detected by the HW in the secondary 80 717 * channel,"dfs_ch_vhtop_ch_freq_seg2" holds the secondary 718 * segment center frequency in the below cases: 719 * 1. preCAC timer is running in chips that support separate 720 * agile engines. 721 * 2. preCAC timer is not running. 722 */ 723 if (dfs_is_precac_timer_running(dfs) && 724 dfs_is_legacy_precac_enabled(dfs)) 725 center_chan = dfs->dfs_precac_secondary_freq; 726 else 727 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 728 } 729 730 if (WLAN_IS_CHAN_MODE_20(curchan)) { 731 nchannels = 1; 732 channels[0] = center_chan; 733 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 734 nchannels = 2; 735 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 736 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 737 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 738 WLAN_IS_CHAN_MODE_80_80(curchan) || 739 detector_id == dfs_get_agile_detector_id(dfs)) { 740 /* If the current channel's bandwidth is 80/80+80/160Mhz, 741 * the corresponding agile Detector's bandwidth will be 80Mhz. 742 * Therefore, if radar is found on the agile detector find 743 * subchannels for 80Mhz bandwidth. 744 */ 745 nchannels = 4; 746 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 747 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 748 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 749 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 750 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 751 nchannels = 8; 752 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 753 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 754 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 755 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 756 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 757 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 758 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 759 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 760 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 761 } 762 763 return nchannels; 764 } 765 #endif 766 767 void dfs_reset_bangradar(struct wlan_dfs *dfs) 768 { 769 dfs->dfs_bangradar_type = DFS_NO_BANGRADAR; 770 } 771 772 int dfs_radarevent_basic_sanity(struct wlan_dfs *dfs, 773 struct dfs_channel *chan) 774 { 775 if (!chan) { 776 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 777 "dfs->dfs_curchan is NULL"); 778 return 0; 779 } 780 781 if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) { 782 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, 783 "radar event on non-DFS chan"); 784 if (!(dfs->dfs_is_offload_enabled)) { 785 dfs_reset_radarq(dfs); 786 dfs_reset_alldelaylines(dfs); 787 dfs_reset_bangradar(dfs); 788 } 789 return 0; 790 } 791 792 return 1; 793 } 794 795 void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs) 796 { 797 qdf_timer_stop(&dfs->wlan_dfstesttimer); 798 dfs->wlan_dfstest = 1; 799 dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee; 800 dfs->wlan_dfstesttime = 1; /* 1ms */ 801 qdf_timer_mod(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime); 802 } 803 804 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs) 805 { 806 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 807 808 return 0; 809 } 810 811 #if defined(QCA_DFS_RCSA_SUPPORT) 812 /* dfs_prepare_nol_ie_bitmap: Create a Bitmap from the radar found subchannels 813 * to be sent along with RCSA. 814 * @dfs: Pointer to wlan_dfs. 815 * @radar_found: Pointer to radar_found_info. 816 * @in_sub_channels: Pointer to Sub-channels. 817 * @n_in_sub_channels: Number of sub-channels. 818 */ 819 #ifdef CONFIG_CHAN_FREQ_API 820 static void 821 dfs_prepare_nol_ie_bitmap_for_freq(struct wlan_dfs *dfs, 822 struct radar_found_info *radar_found, 823 uint16_t *in_sub_channels, 824 uint8_t n_in_sub_channels) 825 { 826 uint16_t cur_subchans[NUM_CHANNELS_160MHZ]; 827 uint8_t n_cur_subchans; 828 uint8_t i; 829 uint8_t j; 830 uint8_t bits = 0x01; 831 832 n_cur_subchans = 833 dfs_get_bonding_channels_for_freq(dfs, dfs->dfs_curchan, 834 radar_found->segment_id, 835 radar_found->detector_id, 836 cur_subchans); 837 dfs->dfs_nol_ie_bandwidth = MIN_DFS_SUBCHAN_BW; 838 dfs->dfs_nol_ie_startfreq = cur_subchans[0]; 839 840 /* Search through the array list of radar affected subchannels 841 * to find if the subchannel in our current channel has radar hit. 842 * Break if found to reduce loop count. 843 */ 844 for (i = 0; i < n_cur_subchans; i++) { 845 for (j = 0; j < n_in_sub_channels; j++) { 846 if (cur_subchans[i] == in_sub_channels[j]) { 847 dfs->dfs_nol_ie_bitmap |= bits; 848 break; 849 } 850 } 851 bits <<= 1; 852 } 853 } 854 #endif 855 856 void dfs_fetch_nol_ie_info(struct wlan_dfs *dfs, 857 uint8_t *nol_ie_bandwidth, 858 uint16_t *nol_ie_startfreq, 859 uint8_t *nol_ie_bitmap) 860 { 861 if (nol_ie_bandwidth) 862 *nol_ie_bandwidth = dfs->dfs_nol_ie_bandwidth; 863 if (nol_ie_startfreq) 864 *nol_ie_startfreq = dfs->dfs_nol_ie_startfreq; 865 if (nol_ie_bitmap) 866 *nol_ie_bitmap = dfs->dfs_nol_ie_bitmap; 867 } 868 869 void dfs_get_rcsa_flags(struct wlan_dfs *dfs, bool *is_rcsa_ie_sent, 870 bool *is_nol_ie_sent) 871 { 872 if (is_rcsa_ie_sent) 873 *is_rcsa_ie_sent = dfs->dfs_is_rcsa_ie_sent; 874 if (is_nol_ie_sent) 875 *is_nol_ie_sent = dfs->dfs_is_nol_ie_sent; 876 } 877 878 void dfs_set_rcsa_flags(struct wlan_dfs *dfs, bool is_rcsa_ie_sent, 879 bool is_nol_ie_sent) 880 { 881 dfs->dfs_is_rcsa_ie_sent = is_rcsa_ie_sent; 882 dfs->dfs_is_nol_ie_sent = is_nol_ie_sent; 883 } 884 885 static void dfs_reset_nol_ie_bitmap(struct wlan_dfs *dfs) 886 { 887 dfs->dfs_nol_ie_bitmap = 0; 888 } 889 890 #ifdef CONFIG_CHAN_FREQ_API 891 bool dfs_process_nol_ie_bitmap(struct wlan_dfs *dfs, uint8_t nol_ie_bandwidth, 892 uint16_t nol_ie_startfreq, uint8_t nol_ie_bitmap) 893 { 894 uint8_t num_subchans; 895 uint8_t bits = 0x01; 896 uint16_t radar_subchans[NUM_CHANNELS_160MHZ]; 897 uint16_t nol_freq_list[NUM_CHANNELS_160MHZ]; 898 bool should_nol_ie_be_sent = true; 899 900 qdf_mem_zero(radar_subchans, sizeof(radar_subchans)); 901 if (!dfs->dfs_use_nol_subchannel_marking) { 902 /* Since subchannel marking is disabled, disregard 903 * NOL IE and set NOL IE flag as false, so it 904 * can't be sent to uplink. 905 */ 906 num_subchans = 907 dfs_get_bonding_channels_for_freq(dfs, 908 dfs->dfs_curchan, 909 SEG_ID_PRIMARY, 910 DETECTOR_ID_0, 911 radar_subchans); 912 should_nol_ie_be_sent = false; 913 } else { 914 /* Add the NOL IE information in DFS structure so that RCSA 915 * and NOL IE can be sent to uplink if uplink exists. 916 */ 917 uint32_t frequency = (uint32_t)nol_ie_startfreq; 918 919 dfs->dfs_nol_ie_bandwidth = nol_ie_bandwidth; 920 dfs->dfs_nol_ie_startfreq = nol_ie_startfreq; 921 dfs->dfs_nol_ie_bitmap = nol_ie_bitmap; 922 for (num_subchans = 0; num_subchans < NUM_CHANNELS_160MHZ; 923 num_subchans++) { 924 if (nol_ie_bitmap & bits) { 925 radar_subchans[num_subchans] = frequency; 926 } 927 bits <<= 1; 928 frequency += nol_ie_bandwidth; 929 } 930 } 931 932 dfs_radar_add_channel_list_to_nol_for_freq(dfs, radar_subchans, 933 nol_freq_list, 934 &num_subchans); 935 return should_nol_ie_be_sent; 936 } 937 #endif 938 #endif /* QCA_DFS_RCSA_SUPPORT */ 939 940 #if defined(WLAN_DFS_TRUE_160MHZ_SUPPORT) && defined(WLAN_DFS_FULL_OFFLOAD) 941 void dfs_translate_radar_params(struct wlan_dfs *dfs, 942 struct radar_found_info *radar_found) 943 { 944 struct dfs_channel *curchan = dfs->dfs_curchan; 945 bool is_primary_ch_right_of_center = false; 946 947 if (!dfs_is_true_160mhz_supported(dfs)) 948 return; 949 950 /* Is the primary channel ( or primary 80 segment) to the right 951 * of the center of 160/165Mhz channel. 952 */ 953 if (curchan->dfs_ch_freq > curchan->dfs_ch_mhz_freq_seg2) 954 is_primary_ch_right_of_center = true; 955 956 if (WLAN_IS_CHAN_MODE_160(curchan)) { 957 if (radar_found->freq_offset > 0) { 958 /* Offset positive: Equivalent to Upper IEEE 959 * 80Mhz chans Synthesizer. 960 */ 961 if (!is_primary_ch_right_of_center) 962 radar_found->segment_id = SEG_ID_SECONDARY; 963 radar_found->freq_offset -= 964 DFS_160MHZ_SECOND_SEG_OFFSET; 965 } else { 966 /* Offset negative: Equivalent to Lower IEEE 967 * 80Mhz chans Synthesizer. 968 */ 969 if (is_primary_ch_right_of_center) 970 radar_found->segment_id = SEG_ID_SECONDARY; 971 radar_found->freq_offset += 972 DFS_160MHZ_SECOND_SEG_OFFSET; 973 } 974 } else if (WLAN_IS_CHAN_MODE_165(dfs, curchan)) { 975 /* If offset is greater than 40MHz, radar is found on the 976 * secondary segment. 977 */ 978 if (abs(radar_found->freq_offset) > 40) { 979 radar_found->segment_id = SEG_ID_SECONDARY; 980 /* Update the freq. offset with respect to the 981 * secondary segment center freq. 982 */ 983 if (is_primary_ch_right_of_center) 984 radar_found->freq_offset += 985 DFS_80P80MHZ_SECOND_SEG_OFFSET; 986 else 987 radar_found->freq_offset -= 988 DFS_80P80MHZ_SECOND_SEG_OFFSET; 989 } 990 } 991 } 992 #endif /* WLAN_DFS_TRUE_160MHZ_SUPPORT */ 993 994 /** 995 * dfs_radar_action_for_hw_mode_switch()- Radar cannot be processed when HW 996 * switch is in progress. So save the radar found parameters for 997 * future processing. 998 * @dfs: Pointer to wlan_dfs structure. 999 * @radar_found: Pointer to radar found structure. 1000 * 1001 * Return: QDF_STATUS 1002 */ 1003 static QDF_STATUS 1004 dfs_radar_action_for_hw_mode_switch(struct wlan_dfs *dfs, 1005 struct radar_found_info *radar_found) 1006 { 1007 struct radar_found_info *radar_params = NULL; 1008 1009 radar_params = qdf_mem_malloc(sizeof(*radar_params)); 1010 if (!radar_params) 1011 return QDF_STATUS_E_NOMEM; 1012 1013 /* If CAC timer is running, cancel it here rather than 1014 * after processing to avoid handling unnecessary CAC timeouts. 1015 */ 1016 if (dfs->dfs_cac_timer_running) 1017 dfs_cac_stop(dfs); 1018 1019 /* If CAC timer is to be handled after mode switch and then 1020 * we receive radar, no point in handling CAC completion. 1021 */ 1022 if (dfs->dfs_defer_params.is_cac_completed) 1023 dfs->dfs_defer_params.is_cac_completed = false; 1024 qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params)); 1025 dfs->dfs_defer_params.radar_params = radar_params; 1026 dfs->dfs_defer_params.is_radar_detected = true; 1027 1028 return QDF_STATUS_SUCCESS; 1029 } 1030 1031 #ifdef CONFIG_CHAN_FREQ_API 1032 uint8_t 1033 dfs_find_radar_affected_channels(struct wlan_dfs *dfs, 1034 struct radar_found_info *radar_found, 1035 uint16_t *freq_list, 1036 uint32_t freq_center) 1037 { 1038 uint8_t num_channels; 1039 1040 if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS) 1041 num_channels = 1042 dfs_get_bonding_channel_without_seg_info_for_freq 1043 (dfs->dfs_curchan, freq_list); 1044 /* BW reduction is dependent on subchannel marking */ 1045 else if ((dfs->dfs_use_nol_subchannel_marking) && 1046 (!(dfs->dfs_bangradar_type) || 1047 (dfs->dfs_bangradar_type == 1048 DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS))) 1049 num_channels = 1050 dfs_find_radar_affected_subchans_for_freq(dfs, 1051 radar_found, 1052 freq_list, 1053 freq_center); 1054 else 1055 num_channels = dfs_get_bonding_channels_for_freq 1056 (dfs, 1057 dfs->dfs_curchan, 1058 radar_found->segment_id, 1059 radar_found->detector_id, 1060 freq_list); 1061 1062 return num_channels; 1063 } 1064 1065 #if defined(QCA_DFS_RCSA_SUPPORT) 1066 /** 1067 * dfs_send_nol_ie_and_rcsa()- Send NOL IE and RCSA action frames. 1068 * @dfs: Pointer to wlan_dfs structure. 1069 * @radar_found: Pointer to radar found structure. 1070 * @nol_freq_list: List of 20MHz frequencies on which radar has been detected. 1071 * @num_channels: number of radar affected channels. 1072 * @wait_for_csa: indicates if the repeater AP should take DFS action or wait 1073 * for CSA 1074 * 1075 * Return: void. 1076 */ 1077 static void 1078 dfs_send_nol_ie_and_rcsa(struct wlan_dfs *dfs, 1079 struct radar_found_info *radar_found, 1080 uint16_t *nol_freq_list, 1081 uint8_t num_channels, 1082 bool *wait_for_csa) 1083 { 1084 dfs->dfs_is_nol_ie_sent = false; 1085 (dfs->is_radar_during_precac || 1086 radar_found->detector_id == dfs_get_agile_detector_id(dfs)) ? 1087 (dfs->dfs_is_rcsa_ie_sent = false) : 1088 (dfs->dfs_is_rcsa_ie_sent = true); 1089 if (dfs->dfs_use_nol_subchannel_marking) { 1090 dfs_reset_nol_ie_bitmap(dfs); 1091 dfs_prepare_nol_ie_bitmap_for_freq(dfs, radar_found, 1092 nol_freq_list, 1093 num_channels); 1094 dfs->dfs_is_nol_ie_sent = true; 1095 } 1096 1097 /* 1098 * This calls into the umac DFS code, which sets the umac 1099 * related radar flags and begins the channel change 1100 * machinery. 1101 1102 * Even during precac, this API is called, but with a flag 1103 * saying not to send RCSA, but only the radar affected subchannel 1104 * information. 1105 */ 1106 dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, wait_for_csa); 1107 } 1108 #else 1109 static void 1110 dfs_send_nol_ie_and_rcsa(struct wlan_dfs *dfs, 1111 struct radar_found_info *radar_found, 1112 uint16_t *nol_freq_list, 1113 uint8_t num_channels, 1114 bool *wait_for_csa) 1115 { 1116 } 1117 #endif /* QCA_DFS_RCSA_SUPPORT */ 1118 1119 #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) || \ 1120 defined(QCA_SUPPORT_ADFS_RCAC) 1121 /** 1122 * dfs_is_radarsource_agile() - Indicates whether the radar event is received 1123 * on the agile channel. 1124 * @dfs: Pointer to wlan_dfs structure. 1125 * @radar_found: Pointer to radar_found_info structure. 1126 * 1127 * Return: QDF_STATUS 1128 */ 1129 static 1130 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs, 1131 struct radar_found_info *radar_found) 1132 { 1133 bool is_radar_from_agile_dfs = 1134 (radar_found->detector_id == dfs_get_agile_detector_id(dfs)); 1135 bool is_radar_from_zero_wait_dfs = 1136 (dfs_is_legacy_precac_enabled(dfs) && 1137 dfs_is_precac_timer_running(dfs) && 1138 (radar_found->segment_id == SEG_ID_SECONDARY)); 1139 1140 return (is_radar_from_agile_dfs || is_radar_from_zero_wait_dfs); 1141 } 1142 #else 1143 static 1144 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs, 1145 struct radar_found_info *radar_found) 1146 { 1147 return false; 1148 } 1149 #endif 1150 1151 QDF_STATUS 1152 dfs_process_radar_ind(struct wlan_dfs *dfs, 1153 struct radar_found_info *radar_found) 1154 { 1155 QDF_STATUS status; 1156 1157 /* Acquire a lock to avoid initiating mode switch till radar 1158 * processing is completed. 1159 */ 1160 DFS_RADAR_MODE_SWITCH_LOCK(dfs); 1161 1162 if (utils_dfs_can_ignore_radar_event(dfs->dfs_pdev_obj)) { 1163 DFS_RADAR_MODE_SWITCH_UNLOCK(dfs); 1164 return QDF_STATUS_SUCCESS; 1165 } 1166 1167 /* Before processing radar, check if HW mode switch is in progress. 1168 * If in progress, defer the processing of radar event received till 1169 * the mode switch is completed. 1170 */ 1171 if (dfs_is_hw_mode_switch_in_progress(dfs)) 1172 status = dfs_radar_action_for_hw_mode_switch(dfs, radar_found); 1173 else if (dfs_is_radarsource_agile(dfs, radar_found)) 1174 status = dfs_process_radar_ind_on_agile_chan(dfs, radar_found); 1175 else 1176 status = dfs_process_radar_ind_on_home_chan(dfs, radar_found); 1177 1178 DFS_RADAR_MODE_SWITCH_UNLOCK(dfs); 1179 1180 return status; 1181 } 1182 1183 QDF_STATUS 1184 dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs, 1185 struct radar_found_info *radar_found) 1186 { 1187 bool wait_for_csa = false; 1188 uint16_t freq_list[NUM_CHANNELS_160MHZ]; 1189 uint16_t nol_freq_list[NUM_CHANNELS_160MHZ]; 1190 uint8_t num_channels; 1191 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1192 uint32_t freq_center; 1193 uint32_t radarfound_freq; 1194 struct dfs_channel *dfs_curchan; 1195 1196 dfs_curchan = dfs->dfs_curchan; 1197 1198 /* Check if the current channel is a non DFS channel 1199 * If the current channel is non-DFS and the radar is from Agile 1200 * Detector we need to process it since Agile Detector has a 1201 * different channel. 1202 */ 1203 if (!dfs_radarevent_basic_sanity(dfs, dfs_curchan)) 1204 goto exit; 1205 1206 dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center); 1207 radarfound_freq = freq_center + radar_found->freq_offset; 1208 1209 if (radar_found->segment_id == SEG_ID_SECONDARY) 1210 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 1211 "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.", 1212 radarfound_freq, freq_center); 1213 else 1214 dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, 1215 "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.", 1216 utils_dfs_freq_to_chan(radarfound_freq), 1217 radarfound_freq, dfs_curchan->dfs_ch_ieee, 1218 dfs_curchan->dfs_ch_freq); 1219 1220 utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq, 1221 WLAN_EV_RADAR_DETECTED); 1222 1223 if (!dfs->dfs_use_nol) { 1224 dfs_reset_bangradar(dfs); 1225 dfs_send_csa_to_current_chan(dfs); 1226 status = QDF_STATUS_SUCCESS; 1227 goto exit; 1228 } 1229 num_channels = dfs_find_radar_affected_channels(dfs, 1230 radar_found, 1231 freq_list, 1232 freq_center); 1233 1234 dfs_reset_bangradar(dfs); 1235 1236 status = dfs_radar_add_channel_list_to_nol_for_freq(dfs, 1237 freq_list, 1238 nol_freq_list, 1239 &num_channels); 1240 if (QDF_IS_STATUS_ERROR(status)) { 1241 dfs_err(dfs, WLAN_DEBUG_DFS, 1242 "radar event received on invalid channel"); 1243 goto exit; 1244 } 1245 1246 /* 1247 * If precac is running and the radar found in secondary 1248 * VHT80 mark the channel as radar and add to NOL list. 1249 * Otherwise random channel selection can choose this 1250 * channel. 1251 */ 1252 dfs_debug(dfs, WLAN_DEBUG_DFS, 1253 "found_on_second=%d is_pre=%d", 1254 dfs->is_radar_found_on_secondary_seg, 1255 dfs_is_precac_timer_running(dfs)); 1256 /* 1257 * Even if radar found on primary, we need to mark the channel as NOL 1258 * in preCAC list. The preCAC list also maintains the current CAC 1259 * channels as part of pre-cleared DFS. Hence call the API 1260 * to mark channels as NOL irrespective of preCAC being enabled or not. 1261 */ 1262 1263 dfs_debug(dfs, WLAN_DEBUG_DFS, 1264 "%s: %d Radar found on dfs detector:%d", 1265 __func__, __LINE__, radar_found->detector_id); 1266 dfs_mark_precac_nol_for_freq(dfs, 1267 dfs->is_radar_found_on_secondary_seg, 1268 radar_found->detector_id, 1269 nol_freq_list, 1270 num_channels); 1271 1272 dfs_send_nol_ie_and_rcsa(dfs, 1273 radar_found, 1274 nol_freq_list, 1275 num_channels, 1276 &wait_for_csa); 1277 1278 if (!dfs->dfs_is_offload_enabled && 1279 dfs->is_radar_found_on_secondary_seg) { 1280 dfs_second_segment_radar_disable(dfs); 1281 dfs->is_radar_found_on_secondary_seg = 0; 1282 1283 if (dfs->is_radar_during_precac) { 1284 dfs->is_radar_during_precac = 0; 1285 goto exit; 1286 } 1287 } 1288 1289 /* 1290 * XXX TODO: the umac NOL code isn't used, but 1291 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac 1292 * NOL code isn't used, that flag is never cleared. This 1293 * needs to be fixed. See EV 105776. 1294 */ 1295 if (wait_for_csa) 1296 goto exit; 1297 1298 /* 1299 * EV 129487 : We have detected radar in the channel, 1300 * stop processing PHY error data as this can cause 1301 * false detect in the new channel while channel 1302 * change is in progress. 1303 */ 1304 1305 if (!dfs->dfs_is_offload_enabled) { 1306 dfs_radar_disable(dfs); 1307 dfs_second_segment_radar_disable(dfs); 1308 } 1309 1310 dfs_mlme_mark_dfs_for_freq(dfs->dfs_pdev_obj, 1311 dfs->dfs_curchan->dfs_ch_ieee, 1312 dfs->dfs_curchan->dfs_ch_freq, 1313 dfs->dfs_curchan->dfs_ch_mhz_freq_seg2, 1314 dfs->dfs_curchan->dfs_ch_flags); 1315 1316 exit: 1317 return status; 1318 } 1319 #endif 1320