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