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