1 /* 2 * Copyright (c) 2017-2019 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_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()- Add given channels to nol 154 * @dfs: Pointer to wlan_dfs structure. 155 * @channels: Pointer to the channel list. 156 * @num_channels: Number of channels in the list. 157 * 158 * Add list of channels to nol, only if the channel is dfs. 159 * 160 * Return: QDF_STATUS 161 */ 162 static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs, 163 uint8_t *channels, 164 uint8_t num_channels) 165 { 166 int i; 167 uint8_t last_chan = 0; 168 uint8_t nollist[NUM_CHANNELS_160MHZ]; 169 uint8_t num_ch = 0; 170 171 if (num_channels > NUM_CHANNELS_160MHZ) { 172 dfs_err(dfs, WLAN_DEBUG_DFS, 173 "Invalid num channels: %d", num_channels); 174 return QDF_STATUS_E_FAILURE; 175 } 176 177 for (i = 0; i < num_channels; i++) { 178 if (channels[i] == 0 || 179 channels[i] == last_chan) 180 continue; 181 if (!utils_is_dfs_ch(dfs->dfs_pdev_obj, channels[i])) { 182 dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip", 183 channels[i]); 184 continue; 185 } 186 last_chan = channels[i]; 187 DFS_NOL_ADD_CHAN_LOCKED(dfs, 188 (uint16_t)utils_dfs_chan_to_freq(channels[i]), 189 dfs->wlan_dfs_nol_timeout); 190 nollist[num_ch++] = last_chan; 191 dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL", 192 last_chan); 193 } 194 195 if (!num_ch) { 196 dfs_err(dfs, WLAN_DEBUG_DFS, 197 "dfs channels not found in channel list"); 198 return QDF_STATUS_E_FAILURE; 199 } 200 201 utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj, 202 nollist, num_ch, DFS_NOL_SET); 203 204 if (dfs->dfs_is_stadfs_enabled) 205 if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj)) 206 utils_dfs_reg_update_nol_history_ch( 207 dfs->dfs_pdev_obj, nollist, num_ch, 208 DFS_NOL_HISTORY_SET); 209 210 dfs_nol_update(dfs); 211 utils_dfs_save_nol(dfs->dfs_pdev_obj); 212 213 return QDF_STATUS_SUCCESS; 214 } 215 216 /** 217 * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz 218 * @freq_offset: freq offset 219 * @center_freq: center frequency 220 * 221 * Find frequency offsets for 80MHz 222 * 223 * Return: None 224 */ 225 static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset, 226 uint32_t center_freq) 227 { 228 int i; 229 230 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 231 if (freq_offset->offset[i] < DFS_OFFSET_SECOND_LOWER) 232 freq_offset->freq[i] = 233 DFS_THIRD_LOWER_CHANNEL(center_freq); 234 else if ((freq_offset->offset[i] > DFS_OFFSET_SECOND_LOWER) && 235 (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER)) 236 freq_offset->freq[i] = 237 DFS_SECOND_LOWER_CHANNEL(center_freq); 238 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) && 239 (freq_offset->offset[i] < 0)) 240 freq_offset->freq[i] = 241 DFS_FIRST_LOWER_CHANNEL(center_freq); 242 else if ((freq_offset->offset[i] > 0) && 243 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER)) 244 freq_offset->freq[i] = 245 DFS_FIRST_UPPER_CHANNEL(center_freq); 246 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) && 247 (freq_offset->offset[i] < DFS_OFFSET_SECOND_UPPER)) 248 freq_offset->freq[i] = 249 DFS_SECOND_UPPER_CHANNEL(center_freq); 250 else if (freq_offset->offset[i] > DFS_OFFSET_SECOND_UPPER) 251 freq_offset->freq[i] = 252 DFS_THIRD_UPPER_CHANNEL(center_freq); 253 } 254 } 255 256 /** 257 * dfs_radar_chan_for_40()- Find frequency offsets for 40MHz 258 * @freq_offset: freq offset 259 * @center_freq: center frequency 260 * 261 * Find frequency offsets for 40MHz 262 * 263 * Return: None 264 */ 265 static void dfs_radar_chan_for_40(struct freqs_offsets *freq_offset, 266 uint32_t center_freq) 267 { 268 int i; 269 270 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 271 if (freq_offset->offset[i] < DFS_OFFSET_FIRST_LOWER) 272 freq_offset->freq[i] = 273 DFS_SECOND_LOWER_CHANNEL(center_freq); 274 else if ((freq_offset->offset[i] > DFS_OFFSET_FIRST_LOWER) && 275 (freq_offset->offset[i] < 0)) 276 freq_offset->freq[i] = 277 DFS_FIRST_LOWER_CHANNEL(center_freq); 278 else if ((freq_offset->offset[i] > 0) && 279 (freq_offset->offset[i] < DFS_OFFSET_FIRST_UPPER)) 280 freq_offset->freq[i] = 281 DFS_FIRST_UPPER_CHANNEL(center_freq); 282 else if (freq_offset->offset[i] > DFS_OFFSET_FIRST_UPPER) 283 freq_offset->freq[i] = 284 DFS_SECOND_UPPER_CHANNEL(center_freq); 285 } 286 } 287 288 /** 289 * dfs_radar_chan_for_20()- Find frequency offsets for 20MHz 290 * @freq_offset: freq offset 291 * @center_freq: center frequency 292 * 293 * Find frequency offsets for 20MHz 294 * 295 * Return: None 296 */ 297 static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset, 298 uint32_t center_freq) 299 { 300 int i; 301 302 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 303 if (freq_offset->offset[i] <= DFS_20MZ_OFFSET_LOWER) 304 freq_offset->freq[i] = 305 DFS_20MHZ_LOWER_CHANNEL(center_freq); 306 else if ((freq_offset->offset[i] > DFS_20MZ_OFFSET_LOWER) && 307 (freq_offset->offset[i] < DFS_20MZ_OFFSET_UPPER)) 308 freq_offset->freq[i] = center_freq; 309 else if (freq_offset->offset[i] >= DFS_20MZ_OFFSET_UPPER) 310 freq_offset->freq[i] = 311 DFS_20MHZ_UPPER_CHANNEL(center_freq); 312 } 313 } 314 315 /* dfs_compute_radar_found_cfreq(): Computes the centre frequency of the 316 * radar hit channel. 317 * @dfs: Pointer to wlan_dfs structure. 318 * @radar_found: Pointer to radar_found_info. 319 * @freq_center: Pointer to retrieve the value of radar found cfreq. 320 */ 321 static void 322 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, 323 struct radar_found_info 324 *radar_found, 325 uint32_t *freq_center) 326 { 327 struct dfs_channel *curchan = dfs->dfs_curchan; 328 uint64_t flag; 329 330 flag = curchan->dfs_ch_flags; 331 if (!radar_found->segment_id) { 332 *freq_center = utils_dfs_chan_to_freq( 333 curchan->dfs_ch_vhtop_ch_freq_seg1); 334 } else { 335 if (dfs_is_precac_timer_running(dfs)) { 336 *freq_center = utils_dfs_chan_to_freq( 337 dfs->dfs_precac_secondary_freq); 338 } else { 339 *freq_center = utils_dfs_chan_to_freq( 340 curchan->dfs_ch_vhtop_ch_freq_seg2); 341 if ((flag & WLAN_CHAN_VHT160) || 342 (flag & WLAN_CHAN_HE160)) 343 *freq_center += DFS_160MHZ_SECOND_SEG_OFFSET; 344 } 345 } 346 } 347 348 /** 349 * dfs_find_radar_affected_subchans() - Finds radar affected sub channels. 350 * @dfs: Pointer to wlan_dfs structure. 351 * @radar_found: Pointer to radar_found structure. 352 * @channels: Pointer to save radar affected channels. 353 * @freq_center: Freq_center of the radar affected chan. 354 * 355 * Return: Number of channels. 356 */ 357 static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs, 358 struct radar_found_info 359 *radar_found, 360 uint8_t *channels, 361 uint32_t freq_center) 362 { 363 int i; 364 uint32_t flag; 365 int32_t sidx; 366 struct dfs_channel *curchan = dfs->dfs_curchan; 367 struct freqs_offsets freq_offset; 368 369 qdf_mem_set(&freq_offset, sizeof(freq_offset), 0); 370 flag = curchan->dfs_ch_flags; 371 372 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) 373 freq_offset.offset[i] = radar_found->freq_offset; 374 375 sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset); 376 377 dfs_info(dfs, WLAN_DEBUG_DFS, 378 "seg=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d", 379 radar_found->segment_id, sidx, 380 radar_found->freq_offset, radar_found->is_chirp, 381 flag, freq_center); 382 383 if ((WLAN_IS_CHAN_A(curchan)) || 384 WLAN_IS_CHAN_MODE_20(curchan)) { 385 if (radar_found->is_chirp || 386 (sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) { 387 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 388 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 389 } 390 dfs_radar_chan_for_20(&freq_offset, freq_center); 391 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 392 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 393 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 394 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 395 } 396 dfs_radar_chan_for_40(&freq_offset, freq_center); 397 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 398 WLAN_IS_CHAN_MODE_160(curchan) || 399 WLAN_IS_CHAN_MODE_80_80(curchan)) { 400 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 401 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 402 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 403 } 404 dfs_radar_chan_for_80(&freq_offset, freq_center); 405 } else { 406 dfs_err(dfs, WLAN_DEBUG_DFS, 407 "channel flag=%d is invalid", flag); 408 return 0; 409 } 410 411 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 412 channels[i] = utils_dfs_freq_to_chan(freq_offset.freq[i]); 413 dfs_info(dfs, WLAN_DEBUG_DFS, "offset=%d, channel=%d", 414 i, channels[i]); 415 } 416 417 return i; 418 } 419 420 uint8_t dfs_get_bonding_channels_without_seg_info(struct dfs_channel *chan, 421 uint8_t *channels) 422 { 423 uint8_t center_chan; 424 uint8_t nchannels = 0; 425 426 center_chan = chan->dfs_ch_vhtop_ch_freq_seg1; 427 428 if (WLAN_IS_CHAN_MODE_20(chan)) { 429 nchannels = 1; 430 channels[0] = center_chan; 431 } else if (WLAN_IS_CHAN_MODE_40(chan)) { 432 nchannels = 2; 433 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 434 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 435 } else if (WLAN_IS_CHAN_MODE_80(chan)) { 436 nchannels = 4; 437 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 438 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 439 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 440 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 441 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { 442 nchannels = 8; 443 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 444 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 445 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 446 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 447 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 448 channels[4] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 449 channels[5] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 450 channels[6] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 451 channels[7] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 452 } else if (WLAN_IS_CHAN_MODE_160(chan)) { 453 nchannels = 8; 454 center_chan = chan->dfs_ch_vhtop_ch_freq_seg2; 455 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 456 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 457 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 458 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 459 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 460 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 461 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 462 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 463 } 464 465 return nchannels; 466 } 467 468 uint8_t dfs_get_bonding_channels(struct wlan_dfs *dfs, 469 struct dfs_channel *curchan, 470 uint32_t segment_id, 471 uint8_t *channels) 472 { 473 uint8_t center_chan; 474 uint8_t nchannels = 0; 475 476 if (!segment_id) 477 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1; 478 else { 479 /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is 480 * zero and "dfs_precac_secondary_freq" holds the secondary 481 * frequency. 482 */ 483 if (dfs_is_precac_timer_running(dfs)) 484 center_chan = dfs->dfs_precac_secondary_freq; 485 else 486 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 487 } 488 489 if (WLAN_IS_CHAN_MODE_20(curchan)) { 490 nchannels = 1; 491 channels[0] = center_chan; 492 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 493 nchannels = 2; 494 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 495 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 496 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 497 WLAN_IS_CHAN_MODE_80_80(curchan)) { 498 nchannels = 4; 499 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 500 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 501 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 502 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 503 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 504 nchannels = 8; 505 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 506 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 507 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 508 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 509 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 510 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 511 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 512 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 513 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 514 } 515 516 return nchannels; 517 } 518 519 int dfs_radarevent_basic_sanity(struct wlan_dfs *dfs, 520 struct dfs_channel *chan) 521 { 522 if (!(dfs->dfs_second_segment_bangradar || 523 dfs_is_precac_timer_running(dfs))) 524 if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) { 525 dfs_debug(dfs, WLAN_DEBUG_DFS2, 526 "radar event on non-DFS chan"); 527 if (!(dfs->dfs_is_offload_enabled)) { 528 dfs_reset_radarq(dfs); 529 dfs_reset_alldelaylines(dfs); 530 dfs->dfs_bangradar = 0; 531 } 532 return 0; 533 } 534 535 return 1; 536 } 537 538 /** 539 * dfs_send_csa_to_current_chan() - Send CSA to current channel 540 * @dfs: Pointer to wlan_dfs structure. 541 * 542 * For the test mode(usenol = 0), don't do a CSA; but setup the test timer so 543 * we get a CSA _back_ to the current operating channel. 544 */ 545 static inline void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs) 546 { 547 qdf_timer_stop(&dfs->wlan_dfstesttimer); 548 dfs->wlan_dfstest = 1; 549 dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee; 550 dfs->wlan_dfstesttime = 1; /* 1ms */ 551 qdf_timer_mod(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime); 552 } 553 554 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs) 555 { 556 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 557 558 return 0; 559 } 560 561 static inline void dfs_reset_bangradar(struct wlan_dfs *dfs) 562 { 563 dfs->dfs_bangradar = 0; 564 dfs->dfs_second_segment_bangradar = 0; 565 dfs->dfs_enh_bangradar = false; 566 } 567 568 /* dfs_prepare_nol_ie_bitmap: Create a Bitmap from the radar found subchannels 569 * to be sent along with RCSA. 570 * 571 * Get the subchannels affected by radar and all the channels in current 572 * channel. 573 * start from the first bit pointing to first subchannel in the current 574 * channel, set as 1 if radar affected, 0 if unaffected. 575 * If the number of subchannels increases (future cases), the bitmap should 576 * be an array of required size. 577 * 578 * Please change macro "MIN_DFS_SUBCHAN_BW" when NOL logic changes. 579 */ 580 static void dfs_prepare_nol_ie_bitmap(struct wlan_dfs *dfs, 581 struct radar_found_info *radar_found, 582 uint8_t *in_sub_channels, 583 uint8_t n_in_sub_channels) 584 { 585 uint8_t cur_subchans[NUM_CHANNELS_160MHZ]; 586 uint8_t n_cur_subchans; 587 uint8_t i; 588 uint8_t j; 589 uint8_t bits = 0x01; 590 591 n_cur_subchans = dfs_get_bonding_channels(dfs, dfs->dfs_curchan, 592 radar_found->segment_id, 593 cur_subchans); 594 dfs->dfs_nol_ie_bandwidth = MIN_DFS_SUBCHAN_BW; 595 dfs->dfs_nol_ie_startfreq = 596 (uint16_t)utils_dfs_chan_to_freq(cur_subchans[0]); 597 598 /* Search through the array list of radar affected subchannels 599 * to find if the subchannel in our current channel has radar hit. 600 * Break if found to reduce loop count. 601 */ 602 for (i = 0; i < n_cur_subchans; i++) { 603 for (j = 0; j < n_in_sub_channels; j++) { 604 if (cur_subchans[i] == in_sub_channels[j]) { 605 dfs->dfs_nol_ie_bitmap |= bits; 606 break; 607 } 608 } 609 bits <<= 1; 610 } 611 } 612 613 void dfs_fetch_nol_ie_info(struct wlan_dfs *dfs, 614 uint8_t *nol_ie_bandwidth, 615 uint16_t *nol_ie_startfreq, 616 uint8_t *nol_ie_bitmap) 617 { 618 if (nol_ie_bandwidth) 619 *nol_ie_bandwidth = dfs->dfs_nol_ie_bandwidth; 620 if (nol_ie_startfreq) 621 *nol_ie_startfreq = dfs->dfs_nol_ie_startfreq; 622 if (nol_ie_bitmap) 623 *nol_ie_bitmap = dfs->dfs_nol_ie_bitmap; 624 } 625 626 void dfs_get_rcsa_flags(struct wlan_dfs *dfs, bool *is_rcsa_ie_sent, 627 bool *is_nol_ie_sent) 628 { 629 if (is_rcsa_ie_sent) 630 *is_rcsa_ie_sent = dfs->dfs_is_rcsa_ie_sent; 631 if (is_nol_ie_sent) 632 *is_nol_ie_sent = dfs->dfs_is_nol_ie_sent; 633 } 634 635 void dfs_set_rcsa_flags(struct wlan_dfs *dfs, bool is_rcsa_ie_sent, 636 bool is_nol_ie_sent) 637 { 638 dfs->dfs_is_rcsa_ie_sent = is_rcsa_ie_sent; 639 dfs->dfs_is_nol_ie_sent = is_nol_ie_sent; 640 } 641 642 bool dfs_process_nol_ie_bitmap(struct wlan_dfs *dfs, uint8_t nol_ie_bandwidth, 643 uint16_t nol_ie_startfreq, uint8_t nol_ie_bitmap) 644 { 645 uint8_t num_subchans; 646 uint8_t bits = 0x01; 647 uint8_t radar_subchans[NUM_CHANNELS_160MHZ]; 648 bool should_nol_ie_be_sent = true; 649 650 qdf_mem_zero(radar_subchans, sizeof(radar_subchans)); 651 if (!dfs->dfs_use_nol_subchannel_marking) { 652 /* Since subchannel marking is disabled, disregard 653 * NOL IE and set NOL IE flag as false, so it 654 * can't be sent to uplink. 655 */ 656 num_subchans = 657 dfs_get_bonding_channels(dfs, 658 dfs->dfs_curchan, 659 dfs->dfs_curchan->dfs_ch_freq, 660 radar_subchans); 661 should_nol_ie_be_sent = false; 662 } else { 663 /* Add the NOL IE information in DFS structure so that RCSA 664 * and NOL IE can be sent to uplink if uplink exists. 665 */ 666 uint32_t frequency = (uint32_t)nol_ie_startfreq; 667 668 dfs->dfs_nol_ie_bandwidth = nol_ie_bandwidth; 669 dfs->dfs_nol_ie_startfreq = nol_ie_startfreq; 670 dfs->dfs_nol_ie_bitmap = nol_ie_bitmap; 671 for (num_subchans = 0; num_subchans < NUM_CHANNELS_160MHZ; 672 num_subchans++) { 673 if (nol_ie_bitmap & bits) { 674 radar_subchans[num_subchans] = 675 utils_dfs_freq_to_chan(frequency); 676 } 677 bits <<= 1; 678 frequency += nol_ie_bandwidth; 679 } 680 } 681 682 dfs_radar_add_channel_list_to_nol(dfs, radar_subchans, num_subchans); 683 return should_nol_ie_be_sent; 684 } 685 686 QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, 687 struct radar_found_info *radar_found) 688 { 689 bool wait_for_csa = false; 690 uint8_t channels[NUM_CHANNELS_160MHZ]; 691 uint8_t num_channels; 692 QDF_STATUS status; 693 uint32_t freq_center; 694 uint32_t radarfound_freq; 695 struct dfs_channel *dfs_curchan; 696 697 if (!dfs->dfs_curchan) { 698 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs->dfs_curchan is NULL"); 699 return QDF_STATUS_E_FAILURE; 700 } 701 702 /* Check if the current channel is a non DFS channel */ 703 if (!dfs_radarevent_basic_sanity(dfs, dfs->dfs_curchan)) { 704 dfs_err(dfs, WLAN_DEBUG_DFS, 705 "radar event on a non-DFS channel"); 706 return QDF_STATUS_E_FAILURE; 707 } 708 709 /* For Full Offload, FW sends segment id,freq_offset and chirp 710 * information and gets assigned when there is radar detect. In 711 * case of radartool bangradar enhanced command and real radar 712 * for DA and PO, we assign these information here. 713 */ 714 if (!(dfs->dfs_is_offload_enabled && dfs->dfs_radar_found_for_fo)) { 715 radar_found->segment_id = dfs->dfs_seg_id; 716 radar_found->freq_offset = dfs->dfs_freq_offset; 717 radar_found->is_chirp = dfs->dfs_is_chirp; 718 } 719 720 dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center); 721 722 if (dfs->dfs_bangradar || dfs->dfs_second_segment_bangradar) { 723 dfs_curchan = dfs->dfs_curchan; 724 if (radar_found->segment_id == SEG_ID_SECONDARY) 725 if (dfs_is_precac_timer_running(dfs)) 726 radarfound_freq = 727 dfs->dfs_precac_secondary_freq; 728 else 729 radarfound_freq = 730 dfs_curchan->dfs_ch_vhtop_ch_freq_seg2; 731 else 732 radarfound_freq = dfs->dfs_curchan->dfs_ch_freq; 733 } else { 734 radarfound_freq = freq_center + dfs->dfs_freq_offset; 735 } 736 737 if (radar_found->segment_id == SEG_ID_SECONDARY) 738 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 739 "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.", 740 radarfound_freq, freq_center); 741 else 742 dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, 743 "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.", 744 utils_dfs_freq_to_chan(radarfound_freq), 745 radarfound_freq, dfs->dfs_curchan->dfs_ch_ieee, 746 dfs->dfs_curchan->dfs_ch_freq); 747 748 if (!dfs->dfs_use_nol) { 749 dfs_reset_bangradar(dfs); 750 dfs_send_csa_to_current_chan(dfs); 751 return QDF_STATUS_SUCCESS; 752 } 753 754 /* BW reduction is dependent on subchannel marking */ 755 756 if ((dfs->dfs_use_nol_subchannel_marking || 757 (dfs->dfs_use_nol_subchannel_marking && dfs->dfs_bw_reduced)) && 758 !(dfs->dfs_bangradar || dfs->dfs_second_segment_bangradar)) 759 num_channels = dfs_find_radar_affected_subchans(dfs, 760 radar_found, 761 channels, 762 freq_center); 763 else 764 num_channels = dfs_get_bonding_channels(dfs, 765 dfs->dfs_curchan, 766 radar_found->segment_id, 767 channels); 768 769 dfs_reset_bangradar(dfs); 770 status = dfs_radar_add_channel_list_to_nol(dfs, channels, num_channels); 771 if (QDF_IS_STATUS_ERROR(status)) { 772 dfs_err(dfs, WLAN_DEBUG_DFS, 773 "radar event received on invalid channel"); 774 return status; 775 } 776 dfs->dfs_is_nol_ie_sent = false; 777 (dfs->is_radar_during_precac) ? 778 (dfs->dfs_is_rcsa_ie_sent = false) : 779 (dfs->dfs_is_rcsa_ie_sent = true); 780 if (dfs->dfs_use_nol_subchannel_marking) { 781 dfs_prepare_nol_ie_bitmap(dfs, radar_found, channels, 782 num_channels); 783 dfs->dfs_is_nol_ie_sent = true; 784 } 785 786 /* 787 * If precac is running and the radar found in secondary 788 * VHT80 mark the channel as radar and add to NOL list. 789 * Otherwise random channel selection can choose this 790 * channel. 791 */ 792 dfs_debug(dfs, WLAN_DEBUG_DFS, 793 "found_on_second=%d is_pre=%d", 794 dfs->is_radar_found_on_secondary_seg, 795 dfs_is_precac_timer_running(dfs)); 796 /* 797 * Even if radar found on primary, we need to move the channel 798 * from precac-required-list and precac-done-list to 799 * precac-nol-list. 800 */ 801 802 if (dfs->dfs_precac_enable) 803 dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg); 804 805 if (utils_get_dfsdomain(dfs->dfs_pdev_obj) == DFS_ETSI_DOMAIN) { 806 /* Remove chan from ETSI Pre-CAC Cleared List*/ 807 dfs_info(dfs, WLAN_DEBUG_DFS_NOL, 808 "%s : %d remove channel from ETSI PreCAC List\n", 809 __func__, __LINE__); 810 dfs_mark_etsi_precac_dfs(dfs, channels, num_channels); 811 } 812 /* 813 * This calls into the umac DFS code, which sets the umac 814 * related radar flags and begins the channel change 815 * machinery. 816 817 * Even during precac, this API is called, but with a flag 818 * saying not to send RCSA, but only the radar affected subchannel 819 * information. 820 */ 821 822 dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa); 823 824 if (!dfs->dfs_is_offload_enabled && 825 dfs->is_radar_found_on_secondary_seg) { 826 dfs_second_segment_radar_disable(dfs); 827 dfs->is_radar_found_on_secondary_seg = 0; 828 829 if (dfs->is_radar_during_precac) { 830 dfs->is_radar_during_precac = 0; 831 return QDF_STATUS_SUCCESS; 832 } 833 } 834 835 /* 836 * XXX TODO: the umac NOL code isn't used, but 837 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac 838 * NOL code isn't used, that flag is never cleared. This 839 * needs to be fixed. See EV 105776. 840 */ 841 if (wait_for_csa) 842 return QDF_STATUS_SUCCESS; 843 844 /* 845 * EV 129487 : We have detected radar in the channel, 846 * stop processing PHY error data as this can cause 847 * false detect in the new channel while channel 848 * change is in progress. 849 */ 850 851 if (!dfs->dfs_is_offload_enabled) { 852 dfs_radar_disable(dfs); 853 dfs_second_segment_radar_disable(dfs); 854 } 855 856 dfs_mlme_mark_dfs(dfs->dfs_pdev_obj, 857 dfs->dfs_curchan->dfs_ch_ieee, 858 dfs->dfs_curchan->dfs_ch_freq, 859 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2, 860 dfs->dfs_curchan->dfs_ch_flags); 861 862 return QDF_STATUS_SUCCESS; 863 } 864