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