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