1 /* 2 * Copyright (c) 2017-2018 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_etsi_precac.h" 27 #include "../dfs_process_radar_found_ind.h" 28 #include <wlan_reg_services_api.h> 29 #include <wlan_dfs_utils_api.h> 30 #include "wlan_dfs_mlme_api.h" 31 #include "../dfs_internal.h" 32 /** 33 * TODO: The code is not according to the following description needs 34 * modification and correction. Code always adds left and right channels to 35 * NOL even if it is not a chirp radar. 36 * 37 * A) If chirp radar starts at boundary and ends at boundary then three channels 38 * will be affected. 39 * freq_offset.freq[0] = fn (Center frequency) 40 * freq_offset.freq[1] = fn-1 (Left of center) 41 * freq_offset.freq[2] = fn+1 (Right of center) 42 * 43 * Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL. 44 * 45 * Chirp start freq Chirp end freq 46 * | | 47 * | | 48 * V V 49 * _______________________________________________________________________ 50 * | center freq | center freq | center freq | 51 * | ch(n-1) | ch(n) | ch(n+1) | 52 * | | | | | | | 53 * | | | | | | | 54 * | | | | | | | 55 * fn-1 fn boundary fn+1 56 * <-------- 20 Mhz ------> 57 * 58 * B) If chirp radar starts at one channel and continues up to another channel 59 * then two channels will be affected. 60 * freq_offset.freq[0] = fn 61 * freq_offset.freq[1] = 0 62 * freq_offset.freq[2] = fn+1 63 * 64 * Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL. 65 * 66 * Chirp start freq Chirp end freq 67 * | | 68 * | | 69 * V V 70 * _______________________________________________________________________ 71 * | center freq | center freq | center freq | 72 * | ch(n-1) | ch(n) | ch(n+1) | 73 * | | | | | | | 74 * | | | | | | | 75 * | | | | | | | 76 * fn-1 fn boundary fn+1 77 * <-------- 20 Mhz ------> 78 * 79 * C) Radar found at boundary, two channels will be affected. 80 * freq_offset.freq[0] = fn 81 * freq_offset.freq[1] = 0 82 * freq_offset.freq[2] = fn+1 83 * 84 * Two channels, ch(n) and ch(n+1) will be added to NOL. 85 * 86 * dfs_freq_offset (radar found freq) 87 * | 88 * | 89 * V 90 * _______________________________________________________________________ 91 * | center freq | center freq | center freq | 92 * | ch(n-1) | ch(n) | ch(n+1) | 93 * | | | | | | | 94 * | | | | | | | 95 * | | | | | | | 96 * fn-1 fn boundary fn+1 97 * <-------- 20 Mhz ------> 98 * 99 * 100 * D) Else only one channel will be affected. 101 * freq_offset.freq[0] = fn 102 * freq_offset.freq[1] = 0 103 * freq_offset.freq[2] = 0 104 * 105 * One channel ch(n) will be added to NOL. 106 * 107 * 108 * dfs_freq_offset (radar found freq) 109 * | 110 * | 111 * V 112 * _______________________________________________________________________ 113 * | center freq | center freq | center freq | 114 * | ch(n-1) | ch(n) | ch(n+1) | 115 * | | | | | | | 116 * | | | | | | | 117 * | | | | | | | 118 * fn-1 fn boundary fn+1 119 * <-------- 20 Mhz ------> 120 */ 121 122 /** 123 * dfs_radar_add_channel_list_to_nol()- Add given channels to nol 124 * @dfs: Pointer to wlan_dfs structure. 125 * @channels: Pointer to the channel list. 126 * @num_channels: Number of channels in the list. 127 * 128 * Add list of channels to nol, only if the channel is dfs. 129 * 130 * Return: QDF_STATUS 131 */ 132 static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs, 133 uint8_t *channels, 134 uint8_t num_channels) 135 { 136 int i; 137 uint8_t last_chan = 0; 138 uint8_t nollist[NUM_CHANNELS_160MHZ]; 139 uint8_t num_ch = 0; 140 141 if (num_channels > NUM_CHANNELS_160MHZ) { 142 dfs_err(dfs, WLAN_DEBUG_DFS, 143 "Invalid num channels: %d", num_channels); 144 return QDF_STATUS_E_FAILURE; 145 } 146 147 for (i = 0; i < num_channels; i++) { 148 if (channels[i] == 0 || 149 channels[i] == last_chan) 150 continue; 151 if (!utils_is_dfs_ch(dfs->dfs_pdev_obj, channels[i])) { 152 dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip", 153 channels[i]); 154 continue; 155 } 156 last_chan = channels[i]; 157 DFS_NOL_ADD_CHAN_LOCKED(dfs, 158 (uint16_t)utils_dfs_chan_to_freq(channels[i]), 159 dfs->wlan_dfs_nol_timeout); 160 nollist[num_ch++] = last_chan; 161 dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL", 162 last_chan); 163 } 164 165 if (!num_ch) { 166 dfs_err(dfs, WLAN_DEBUG_DFS, 167 "dfs channels not found in channel list"); 168 return QDF_STATUS_E_FAILURE; 169 } 170 171 utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj, 172 nollist, num_ch, DFS_NOL_SET); 173 dfs_nol_update(dfs); 174 utils_dfs_save_nol(dfs->dfs_pdev_obj); 175 176 return QDF_STATUS_SUCCESS; 177 } 178 179 /** 180 * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz 181 * @freq_offset: freq offset 182 * @center_freq: center frequency 183 * 184 * Find frequency offsets for 80MHz 185 * 186 * Return: None 187 */ 188 static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset, 189 uint32_t center_freq) 190 { 191 int i; 192 193 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 194 if (freq_offset->offset[i] < DFS_OFFSET_SECOND_LOWER) 195 freq_offset->freq[i] = 196 DFS_THIRD_LOWER_CHANNEL(center_freq); 197 else if ((freq_offset->offset[i] > DFS_OFFSET_SECOND_LOWER) && 198 (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER)) 199 freq_offset->freq[i] = 200 DFS_SECOND_LOWER_CHANNEL(center_freq); 201 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) && 202 (freq_offset->offset[i] < 0)) 203 freq_offset->freq[i] = 204 DFS_FIRST_LOWER_CHANNEL(center_freq); 205 else if ((freq_offset->offset[i] > 0) && 206 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER)) 207 freq_offset->freq[i] = 208 DFS_FIRST_UPPER_CHANNEL(center_freq); 209 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) && 210 (freq_offset->offset[i] < DFS_OFFSET_SECOND_UPPER)) 211 freq_offset->freq[i] = 212 DFS_SECOND_UPPER_CHANNEL(center_freq); 213 else if (freq_offset->offset[i] > DFS_OFFSET_SECOND_UPPER) 214 freq_offset->freq[i] = 215 DFS_THIRD_UPPER_CHANNEL(center_freq); 216 } 217 } 218 219 /** 220 * dfs_radar_chan_for_40()- Find frequency offsets for 40MHz 221 * @freq_offset: freq offset 222 * @center_freq: center frequency 223 * 224 * Find frequency offsets for 40MHz 225 * 226 * Return: None 227 */ 228 static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset, 229 uint32_t center_freq) 230 { 231 int i; 232 233 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 234 if (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER) 235 freq_offset->freq[i] = 236 DFS_SECOND_LOWER_CHANNEL(center_freq); 237 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) && 238 (freq_offset->offset[i] < 0)) 239 freq_offset->freq[i] = 240 DFS_FIRST_LOWER_CHANNEL(center_freq); 241 else if ((freq_offset->offset[i] > 0) && 242 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER)) 243 freq_offset->freq[i] = 244 DFS_FIRST_UPPER_CHANNEL(center_freq); 245 else if (freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) 246 freq_offset->freq[i] = 247 DFS_SECOND_UPPER_CHANNEL(center_freq); 248 } 249 } 250 251 /** 252 * dfs_radar_chan_for_20()- Find frequency offsets for 20MHz 253 * @freq_offset: freq offset 254 * @center_freq: center frequency 255 * 256 * Find frequency offsets for 20MHz 257 * 258 * Return: None 259 */ 260 static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset, 261 uint32_t center_freq) 262 { 263 int i; 264 265 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 266 if (freq_offset->offset[i] <= DFS_20MZ_OFFSET_LOWER) 267 freq_offset->freq[i] = 268 DFS_20MHZ_LOWER_CHANNEL(center_freq); 269 else if ((freq_offset->offset[i] > DFS_20MZ_OFFSET_LOWER) && 270 (freq_offset->offset[i] < DFS_20MZ_OFFSET_UPPER)) 271 freq_offset->freq[i] = center_freq; 272 else if (freq_offset->offset[i] >= DFS_20MZ_OFFSET_UPPER) 273 freq_offset->freq[i] = 274 DFS_20MHZ_UPPER_CHANNEL(center_freq); 275 } 276 } 277 278 /** 279 * dfs_find_radar_affected_subchans() - Finds radar affected sub channels. 280 * @dfs: Pointer to wlan_dfs structure. 281 * @radar_found: Pointer to radar_found structure. 282 * @channels: Pointer to save radar affected channels. 283 * 284 * Return: Number of channels. 285 */ 286 static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs, 287 struct radar_found_info 288 *radar_found, 289 uint8_t *channels) 290 { 291 int i; 292 uint32_t freq_center, flag; 293 int32_t sidx; 294 struct dfs_channel *curchan = dfs->dfs_curchan; 295 struct freqs_offsets freq_offset; 296 297 qdf_mem_set(&freq_offset, sizeof(freq_offset), 0); 298 flag = curchan->dfs_ch_flags; 299 300 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) 301 freq_offset.offset[i] = radar_found->freq_offset; 302 303 sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset); 304 305 if (!radar_found->segment_id) 306 freq_center = utils_dfs_chan_to_freq( 307 curchan->dfs_ch_vhtop_ch_freq_seg1); 308 else { 309 if (dfs_is_precac_timer_running(dfs)) { 310 freq_center = utils_dfs_chan_to_freq( 311 dfs->dfs_precac_secondary_freq); 312 } else { 313 freq_center = utils_dfs_chan_to_freq( 314 curchan->dfs_ch_vhtop_ch_freq_seg2); 315 if (flag & WLAN_CHAN_VHT160) 316 freq_center += DFS_160MHZ_SECOND_SEG_OFFSET; 317 } 318 } 319 320 dfs_info(dfs, WLAN_DEBUG_DFS, 321 "seg=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d", 322 radar_found->segment_id, sidx, 323 radar_found->freq_offset, radar_found->is_chirp, 324 flag, freq_center); 325 326 if ((WLAN_IS_CHAN_A(curchan)) || 327 WLAN_IS_CHAN_MODE_20(curchan)) { 328 if (radar_found->is_chirp || 329 (sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) { 330 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 331 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 332 } 333 dfs_radar_chan_for_20(&freq_offset, freq_center); 334 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 335 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 336 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 337 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 338 } 339 dfs_radar_chan_for_40(&freq_offset, freq_center); 340 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 341 WLAN_IS_CHAN_MODE_160(curchan) || 342 WLAN_IS_CHAN_MODE_80_80(curchan)) { 343 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 344 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 345 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 346 } 347 dfs_radar_chan_for_80(&freq_offset, freq_center); 348 } else { 349 dfs_err(dfs, WLAN_DEBUG_DFS, 350 "channel flag=%d is invalid", flag); 351 return 0; 352 } 353 354 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 355 channels[i] = utils_dfs_freq_to_chan(freq_offset.freq[i]); 356 dfs_info(dfs, WLAN_DEBUG_DFS, "offset=%d, channel=%d", 357 i, channels[i]); 358 } 359 360 return i; 361 } 362 363 uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, 364 uint8_t *channels) 365 { 366 uint8_t center_chan; 367 uint8_t nchannels = 0; 368 369 center_chan = chan->dfs_ch_vhtop_ch_freq_seg1; 370 371 if (WLAN_IS_CHAN_MODE_20(chan)) { 372 nchannels = 1; 373 channels[0] = center_chan; 374 } else if (WLAN_IS_CHAN_MODE_40(chan)) { 375 nchannels = 2; 376 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 377 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 378 } else if (WLAN_IS_CHAN_MODE_80(chan)) { 379 nchannels = 4; 380 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 381 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 382 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 383 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 384 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { 385 nchannels = 8; 386 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 387 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 388 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 389 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 390 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 391 channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 392 channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 393 channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 394 channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 395 } else if (WLAN_IS_CHAN_MODE_160(chan)) { 396 nchannels = 8; 397 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 398 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 399 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 400 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 401 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 402 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 403 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 404 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 405 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 406 } 407 408 return nchannels; 409 } 410 411 uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, 412 struct dfs_channel *curchan, 413 uint32_t segment_id, 414 uint8_t *channels) 415 { 416 uint8_t center_chan; 417 uint8_t nchannels = 0; 418 419 if (!segment_id) 420 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1; 421 else { 422 /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is 423 * zero and "dfs_precac_secondary_freq" holds the secondary 424 * frequency. 425 */ 426 if (dfs_is_precac_timer_running(dfs)) 427 center_chan = dfs->dfs_precac_secondary_freq; 428 else 429 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 430 } 431 432 if (WLAN_IS_CHAN_MODE_20(curchan)) { 433 nchannels = 1; 434 channels[0] = center_chan; 435 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 436 nchannels = 2; 437 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 438 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 439 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 440 WLAN_IS_CHAN_MODE_80_80(curchan)) { 441 nchannels = 4; 442 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 443 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 444 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 445 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 446 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 447 nchannels = 8; 448 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 449 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 450 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 451 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 452 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 453 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 454 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 455 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 456 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 457 } 458 459 return nchannels; 460 } 461 462 int dfs_radarevent_basic_sanity(struct wlan_dfs *dfs, 463 struct dfs_channel *chan) 464 { 465 if (!(dfs->dfs_second_segment_bangradar || 466 dfs_is_precac_timer_running(dfs))) 467 if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) { 468 dfs_debug(dfs, WLAN_DEBUG_DFS2, 469 "radar event on non-DFS chan"); 470 if (!(dfs->dfs_is_offload_enabled)) { 471 dfs_reset_radarq(dfs); 472 dfs_reset_alldelaylines(dfs); 473 dfs->dfs_bangradar = 0; 474 } 475 return 0; 476 } 477 478 return 1; 479 } 480 481 /** 482 * dfs_send_csa_to_current_chan() - Send CSA to current channel 483 * @dfs: Pointer to wlan_dfs structure. 484 * 485 * For the test mode(usenol = 0), don't do a CSA; but setup the test timer so 486 * we get a CSA _back_ to the current operating channel. 487 */ 488 static inline void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs) 489 { 490 qdf_timer_stop(&dfs->wlan_dfstesttimer); 491 dfs->wlan_dfstest = 1; 492 dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee; 493 dfs->wlan_dfstesttime = 1; /* 1ms */ 494 qdf_timer_mod(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime); 495 } 496 497 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs) 498 { 499 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 500 501 return 0; 502 } 503 504 static inline void dfs_reset_bangradar(struct wlan_dfs *dfs) 505 { 506 dfs->dfs_bangradar = 0; 507 dfs->dfs_second_segment_bangradar = 0; 508 } 509 510 QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, 511 struct radar_found_info *radar_found) 512 { 513 bool wait_for_csa = false; 514 uint8_t channels[NUM_CHANNELS_160MHZ]; 515 uint8_t num_channels; 516 QDF_STATUS status; 517 518 if (!dfs->dfs_curchan) { 519 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs->dfs_curchan is NULL"); 520 return QDF_STATUS_E_FAILURE; 521 } 522 523 /* Check if the current channel is a non DFS channel */ 524 if (!dfs_radarevent_basic_sanity(dfs, dfs->dfs_curchan)) { 525 dfs_err(dfs, WLAN_DEBUG_DFS, 526 "radar event on a non-DFS channel"); 527 return QDF_STATUS_E_FAILURE; 528 } 529 530 /* For Full Offload, FW sends segment id,freq_offset and chirp 531 * information and gets assigned when there is radar detect. In 532 * case of radartool bangradar enhanced command and real radar 533 * for DA and PO, we assign these information here. 534 */ 535 if (!(dfs->dfs_is_offload_enabled && dfs->dfs_radar_found_for_fo)) { 536 radar_found->segment_id = dfs->dfs_seg_id; 537 radar_found->freq_offset = dfs->dfs_freq_offset; 538 radar_found->is_chirp = dfs->dfs_is_chirp; 539 } 540 541 if (radar_found->segment_id == SEG_ID_SECONDARY) 542 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 543 "Radar found on second segment VHT80 freq=%d MHz", 544 dfs->dfs_precac_secondary_freq); 545 else 546 dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, 547 "Radar found on channel=%d, freq=%d MHz", 548 dfs->dfs_curchan->dfs_ch_ieee, 549 dfs->dfs_curchan->dfs_ch_freq); 550 551 if (!dfs->dfs_use_nol) { 552 dfs_reset_bangradar(dfs); 553 dfs_send_csa_to_current_chan(dfs); 554 return QDF_STATUS_SUCCESS; 555 } 556 557 if (dfs->dfs_use_nol_subchannel_marking && 558 !(dfs->dfs_bangradar || dfs->dfs_second_segment_bangradar)) 559 num_channels = dfs_find_radar_affected_subchans(dfs, 560 radar_found, 561 channels); 562 else 563 num_channels = dfs_get_bonding_channels(dfs, 564 dfs->dfs_curchan, 565 radar_found->segment_id, 566 channels); 567 568 dfs_reset_bangradar(dfs); 569 status = dfs_radar_add_channel_list_to_nol(dfs, channels, num_channels); 570 if (QDF_IS_STATUS_ERROR(status)) { 571 dfs_err(dfs, WLAN_DEBUG_DFS, 572 "radar event received on invalid channel"); 573 return status; 574 } 575 576 /* 577 * If precac is running and the radar found in secondary 578 * VHT80 mark the channel as radar and add to NOL list. 579 * Otherwise random channel selection can choose this 580 * channel. 581 */ 582 dfs_debug(dfs, WLAN_DEBUG_DFS, 583 "found_on_second=%d is_pre=%d", 584 dfs->is_radar_found_on_secondary_seg, 585 dfs_is_precac_timer_running(dfs)); 586 587 /* 588 * Even if radar found on primary, we need to move the channel 589 * from precac-required-list and precac-done-list to 590 * precac-nol-list. 591 */ 592 if (dfs->dfs_precac_enable) 593 dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg); 594 595 if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) { 596 /* Remove chan from ETSI Pre-CAC Cleared List*/ 597 dfs_info(dfs, WLAN_DEBUG_DFS_NOL, 598 "%s : %d remove channel from ETSI PreCAC List\n", 599 __func__, __LINE__); 600 dfs_mark_etsi_precac_dfs(dfs, channels, num_channels); 601 } 602 603 if (!dfs->dfs_is_offload_enabled && 604 dfs->is_radar_found_on_secondary_seg) { 605 dfs_second_segment_radar_disable(dfs); 606 dfs->is_radar_found_on_secondary_seg = 0; 607 608 if (dfs->is_radar_during_precac) { 609 dfs->is_radar_during_precac = 0; 610 return QDF_STATUS_SUCCESS; 611 } 612 } 613 614 /* 615 * This calls into the umac DFS code, which sets the umac 616 * related radar flags and begins the channel change 617 * machinery. 618 * XXX TODO: the umac NOL code isn't used, but 619 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac 620 * NOL code isn't used, that flag is never cleared. This 621 * needs to be fixed. See EV 105776. 622 */ 623 dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa); 624 if (wait_for_csa) 625 return QDF_STATUS_SUCCESS; 626 627 /* 628 * EV 129487 : We have detected radar in the channel, 629 * stop processing PHY error data as this can cause 630 * false detect in the new channel while channel 631 * change is in progress. 632 */ 633 634 if (!dfs->dfs_is_offload_enabled) { 635 dfs_radar_disable(dfs); 636 dfs_second_segment_radar_disable(dfs); 637 } 638 639 dfs_mlme_mark_dfs(dfs->dfs_pdev_obj, 640 dfs->dfs_curchan->dfs_ch_ieee, 641 dfs->dfs_curchan->dfs_ch_freq, 642 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2, 643 dfs->dfs_curchan->dfs_ch_flags); 644 645 return QDF_STATUS_SUCCESS; 646 } 647