1 /* 2 * Copyright (c) 2017-2021 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_objmgr_vdev_obj.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 #ifdef CONFIG_CHAN_FREQ_API 153 QDF_STATUS 154 dfs_radar_add_channel_list_to_nol_for_freq(struct wlan_dfs *dfs, 155 uint16_t *freq_list, 156 uint16_t *nol_freq_list, 157 uint8_t *num_channels) 158 { 159 int i; 160 uint16_t last_chan_freq = 0; 161 uint8_t num_ch = 0; 162 163 if (*num_channels > NUM_CHANNELS_160MHZ) { 164 dfs_err(dfs, WLAN_DEBUG_DFS, 165 "Invalid num channels: %d", *num_channels); 166 return QDF_STATUS_E_FAILURE; 167 } 168 169 for (i = 0; i < *num_channels; i++) { 170 if (freq_list[i] == 0 || 171 freq_list[i] == last_chan_freq) 172 continue; 173 if (!utils_is_dfs_chan_for_freq(dfs->dfs_pdev_obj, 174 freq_list[i])) { 175 dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip", 176 freq_list[i]); 177 continue; 178 } 179 last_chan_freq = freq_list[i]; 180 DFS_NOL_ADD_CHAN_LOCKED(dfs, 181 freq_list[i], 182 dfs->wlan_dfs_nol_timeout); 183 nol_freq_list[num_ch++] = last_chan_freq; 184 utils_dfs_deliver_event(dfs->dfs_pdev_obj, 185 freq_list[i], 186 WLAN_EV_NOL_STARTED); 187 dfs_info(dfs, WLAN_DEBUG_DFS_NOL, "ch=%d Added to NOL", 188 last_chan_freq); 189 } 190 191 if (!num_ch) { 192 dfs_err(dfs, WLAN_DEBUG_DFS, 193 "dfs channels not found in channel list"); 194 return QDF_STATUS_E_FAILURE; 195 } 196 *num_channels = num_ch; 197 198 if (!dfs_get_disable_radar_marking(dfs)) { 199 utils_dfs_reg_update_nol_chan_for_freq(dfs->dfs_pdev_obj, 200 nol_freq_list, num_ch, 201 DFS_NOL_SET); 202 203 if (dfs->dfs_is_stadfs_enabled) 204 if (dfs_mlme_is_opmode_sta(dfs->dfs_pdev_obj)) 205 utils_dfs_reg_update_nol_history_chan_for_freq( 206 dfs->dfs_pdev_obj, nol_freq_list, 207 num_ch, DFS_NOL_HISTORY_SET); 208 } 209 210 dfs_nol_update(dfs); 211 utils_dfs_save_nol(dfs->dfs_pdev_obj); 212 213 return QDF_STATUS_SUCCESS; 214 } 215 #endif 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 #ifdef CONFIG_CHAN_FREQ_API 316 void 317 dfs_compute_radar_found_cfreq(struct wlan_dfs *dfs, 318 struct radar_found_info *radar_found, 319 uint32_t *freq_center) 320 { 321 struct dfs_channel *curchan = dfs->dfs_curchan; 322 323 /* Radar found on agile detector ID. 324 * Applicable to chips that have a separate agile radar detector 325 * engine. 326 */ 327 if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) { 328 *freq_center = dfs->dfs_agile_precac_freq_mhz; 329 if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) { 330 if (radar_found->segment_id == PRIMARY_SEG) 331 *freq_center -= DFS_160MHZ_SECOND_SEG_OFFSET; 332 else 333 *freq_center += DFS_160MHZ_SECOND_SEG_OFFSET; 334 } else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ && 335 dfs->dfs_agile_precac_freq_mhz == 336 RESTRICTED_80P80_CHAN_CENTER_FREQ) { 337 /* 338 * The reason why left and right offsets 339 * are different. 340 * Center of 165 is 5730MHz. 341 * Center of left 80 is 5690MHz. 342 * Center of right 80 is 5775MHz. 343 */ 344 if (radar_found->segment_id == PRIMARY_SEG) 345 *freq_center -= 346 DFS_165MHZ_SECOND_SEG_OFFSET_LEFT; 347 else 348 *freq_center += 349 DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT; 350 } 351 } else if (!radar_found->segment_id) { 352 *freq_center = curchan->dfs_ch_mhz_freq_seg1; 353 } else { 354 /* Radar found on secondary segment by the HW when 355 * preCAC was running. It (dfs_precac_enable) is specific to 356 * legacy chips. 357 */ 358 if (dfs_is_precac_timer_running(dfs) && 359 dfs_is_legacy_precac_enabled(dfs)) { 360 *freq_center = dfs->dfs_precac_secondary_freq_mhz; 361 } else { 362 /* Radar found on secondary segment by the HW, when preCAC 363 * was not running in legacy chips or preCAC was running 364 * in Lithium chips. 365 */ 366 *freq_center = curchan->dfs_ch_mhz_freq_seg2; 367 if (WLAN_IS_CHAN_MODE_160(curchan)) { 368 /* If center frequency of entire 160 band 369 * is less than center frequency of primary 370 * segment, then the center frequency of 371 * secondary segment is -40 of center 372 * frequency of entire 160 segment. 373 */ 374 if (curchan->dfs_ch_mhz_freq_seg2 < 375 curchan->dfs_ch_mhz_freq_seg1) 376 *freq_center -= 377 DFS_160MHZ_SECOND_SEG_OFFSET; 378 else 379 *freq_center += 380 DFS_160MHZ_SECOND_SEG_OFFSET; 381 } 382 } 383 } 384 } 385 #endif 386 387 /** 388 * dfs_find_radar_affected_subchans_for_freq() - Find radar affected sub chans. 389 * @dfs: Pointer to wlan_dfs structure. 390 * @radar_found: Pointer to radar_found structure. 391 * @freq_list: Pointer to save radar affected channels. 392 * @freq_center: Freq_center of the radar affected chan. 393 * 394 * Return: Number of channels. 395 */ 396 #ifdef CONFIG_CHAN_FREQ_API 397 static uint8_t 398 dfs_find_radar_affected_subchans_for_freq(struct wlan_dfs *dfs, 399 struct radar_found_info *radar_found, 400 uint16_t *freq_list, 401 uint32_t freq_center) 402 { 403 int i, j; 404 uint8_t num_radar_subchans; 405 uint32_t flag; 406 int32_t sidx; 407 uint16_t candidate_subchan_freq; 408 uint16_t cur_subchans[NUM_CHANNELS_160MHZ]; 409 uint8_t n_cur_subchans; 410 struct dfs_channel *curchan = dfs->dfs_curchan; 411 struct freqs_offsets freq_offset; 412 413 qdf_mem_zero(&freq_offset, sizeof(freq_offset)); 414 flag = curchan->dfs_ch_flags; 415 416 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) 417 freq_offset.offset[i] = radar_found->freq_offset; 418 419 sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset); 420 421 dfs_info(dfs, WLAN_DEBUG_DFS, 422 "seg=%d, det=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d", 423 radar_found->segment_id, radar_found->detector_id, sidx, 424 radar_found->freq_offset, radar_found->is_chirp, 425 flag, freq_center); 426 427 if ((WLAN_IS_CHAN_A(curchan)) || 428 WLAN_IS_CHAN_MODE_20(curchan)) { 429 if (radar_found->is_chirp || 430 (sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) { 431 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 432 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 433 } 434 dfs_radar_chan_for_20(&freq_offset, freq_center); 435 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 436 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 437 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 438 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 439 } 440 dfs_radar_chan_for_40(&freq_offset, freq_center); 441 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 442 WLAN_IS_CHAN_MODE_160(curchan) || 443 WLAN_IS_CHAN_MODE_80_80(curchan)) { 444 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 445 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 446 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 447 } 448 dfs_radar_chan_for_80(&freq_offset, freq_center); 449 } else { 450 dfs_err(dfs, WLAN_DEBUG_DFS, 451 "channel flag=%d is invalid", flag); 452 return 0; 453 } 454 455 n_cur_subchans = 456 dfs_get_bonding_channels_for_freq(dfs, curchan, 457 radar_found->segment_id, 458 radar_found->detector_id, 459 cur_subchans); 460 461 for (i = 0, num_radar_subchans = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 462 candidate_subchan_freq = freq_offset.freq[i]; 463 for (j = 0; j < n_cur_subchans; j++) { 464 if (cur_subchans[j] == candidate_subchan_freq) { 465 freq_list[num_radar_subchans++] = 466 candidate_subchan_freq; 467 dfs_info(dfs, WLAN_DEBUG_DFS, 468 "offset=%d, channel=%d", 469 num_radar_subchans, 470 freq_list[num_radar_subchans - 1]); 471 break; 472 } 473 } 474 } 475 return num_radar_subchans; 476 } 477 #endif 478 479 /* 480 * dfs_get_bonding_channel_without_seg_info_for_freq() - Get bonding frequency 481 * list. 482 * @chan: Pointer to dfs_channel. 483 * @freq_list: Pointer to frequency list. 484 */ 485 #ifdef CONFIG_CHAN_FREQ_API 486 uint8_t 487 dfs_get_bonding_channel_without_seg_info_for_freq(struct dfs_channel *chan, 488 uint16_t *freq_list) 489 { 490 uint16_t center_freq; 491 uint8_t nchannels = 0; 492 493 center_freq = chan->dfs_ch_mhz_freq_seg1; 494 495 if (WLAN_IS_CHAN_MODE_20(chan)) { 496 nchannels = 1; 497 freq_list[0] = center_freq; 498 } else if (WLAN_IS_CHAN_MODE_40(chan)) { 499 nchannels = 2; 500 freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 501 freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 502 } else if (WLAN_IS_CHAN_MODE_80(chan)) { 503 nchannels = 4; 504 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 505 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 506 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 507 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 508 } else if (WLAN_IS_CHAN_MODE_80_80(chan)) { 509 nchannels = 8; 510 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 511 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 512 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 513 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 514 center_freq = chan->dfs_ch_mhz_freq_seg2; 515 freq_list[4] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 516 freq_list[5] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 517 freq_list[6] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 518 freq_list[7] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 519 } else if (WLAN_IS_CHAN_MODE_160(chan)) { 520 nchannels = 8; 521 center_freq = chan->dfs_ch_mhz_freq_seg2; 522 freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 523 freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 524 freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 525 freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 526 freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 527 freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 528 freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 529 freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 530 } 531 532 return nchannels; 533 } 534 #endif 535 536 #ifdef CONFIG_CHAN_FREQ_API 537 /* 538 * dfs_get_80mhz_bonding_channels() - Get bonding frequency list of 80MHz 539 * channel. 540 * @center_freq: Center frequency of the 80MHz channel. 541 * @freq_list: Pointer to frequency list. 542 */ 543 static 544 void dfs_get_80mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list) 545 { 546 freq_list[0] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 547 freq_list[1] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 548 freq_list[2] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 549 freq_list[3] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 550 } 551 552 /* 553 * dfs_get_160mhz_bonding_channels() - Get bonding frequency list of 160MHz 554 * channel. 555 * @center_freq: Center frequency of the 160MHz channel. 556 * @freq_list: Pointer to frequency list. 557 */ 558 static 559 void dfs_get_160mhz_bonding_channels(uint16_t center_freq, uint16_t *freq_list) 560 { 561 freq_list[0] = center_freq - DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 562 freq_list[1] = center_freq - DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 563 freq_list[2] = center_freq - DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 564 freq_list[3] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 565 freq_list[4] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 566 freq_list[5] = center_freq + DFS_5GHZ_2ND_CHAN_FREQ_OFFSET; 567 freq_list[6] = center_freq + DFS_5GHZ_3RD_CHAN_FREQ_OFFSET; 568 freq_list[7] = center_freq + DFS_5GHZ_4TH_CHAN_FREQ_OFFSET; 569 } 570 571 /* 572 * dfs_get_agile_subchans_for_curchan_160() - Get bonding frequency list of 573 * agile channels when current operating channel is 160MHz. 574 * 575 * @dfs: Pointer to DFS structure. 576 * @center_freq: Center frequency of the channel. 577 * @segment_id: Segment ID of interest. 0 for primary segment and 1 for 578 * secondary segment. 579 * @freq_list: Pointer to frequency list. 580 * @nchannels: Number of subchannel. 581 */ 582 static void 583 dfs_get_agile_subchans_for_curchan_160(struct wlan_dfs *dfs, 584 uint16_t center_freq, 585 uint32_t segment_id, 586 uint16_t *freq_list, 587 uint8_t *nchannels) 588 { 589 if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) { 590 /* 591 * The current operating channel is 160MHz and 592 * the agile channel is 80MHz. This can happen 593 * in HK only. 594 */ 595 *nchannels = 4; 596 dfs_get_80mhz_bonding_channels(center_freq, 597 freq_list); 598 } else if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) 599 /* 600 * The current operating channel is 160MHz and 601 * the agile channel is 160MHz. 602 * Pine ADFS specific. 603 */ 604 dfs_get_160mhz_bonding_channels(center_freq, 605 freq_list); 606 else if (dfs->dfs_precac_chwidth == CH_WIDTH_80P80MHZ) { 607 /* 608 * The current operating channel is 160MHz and the agile channel 609 * is 165MHz(restricted 80P80MHZ). Pine ADFS specific. 610 * If the segment id is primary segment 0, shift the center 611 * frequency 5730MHz to the center of left 80MHz segment 5690MHz 612 * and add the subchannels of the left 80MHz segment. 613 * If the segment id is secondary segment 1, shift the center 614 * frequency 5730MHz to the center of right 80MHz segment 615 * 5775MHz and add the subchannels of the right 80MHz segment. 616 */ 617 *nchannels = 4; 618 center_freq = (segment_id) ? 619 (center_freq + DFS_165MHZ_SECOND_SEG_OFFSET_RIGHT) : 620 (center_freq - DFS_165MHZ_SECOND_SEG_OFFSET_LEFT); 621 dfs_get_80mhz_bonding_channels(center_freq, 622 freq_list); 623 } 624 } 625 626 /* 627 * dfs_get_bonding_channels_for_freq() - Get bonding channel frequency. 628 * @dfs: Pointer to wlan_dfs. 629 * @curchan: Pointer to dfs_channel. 630 * @segment_id: Segment ID. 631 * @detector_id: Detector ID. 632 * @freq_list: Pointer to frequency list. 633 */ 634 uint8_t dfs_get_bonding_channels_for_freq(struct wlan_dfs *dfs, 635 struct dfs_channel *curchan, 636 uint32_t segment_id, 637 uint8_t detector_id, 638 uint16_t *freq_list) 639 { 640 uint16_t center_freq; 641 uint8_t nchannels = 0; 642 643 /* 644 * For radar in agile detector, use the center of the channel 645 * configured to the agile detector. 646 * For radar on a 160MHz home channel, use the center of 160MHz. 647 * For radar on all other bandwidths, use the center of the segment 648 * affected. 649 */ 650 if (detector_id == dfs_get_agile_detector_id(dfs)) 651 center_freq = dfs->dfs_agile_precac_freq_mhz; 652 else if (WLAN_IS_CHAN_MODE_160(curchan)) 653 center_freq = curchan->dfs_ch_mhz_freq_seg2; 654 else if (!segment_id) 655 center_freq = curchan->dfs_ch_mhz_freq_seg1; 656 else { 657 /* When precac is running "dfs_ch_vhtop_ch_freq_seg2" is 658 * zero and "dfs_precac_secondary_freq" holds the secondary 659 * frequency. 660 */ 661 if (dfs_is_legacy_precac_enabled(dfs) && 662 dfs_is_precac_timer_running(dfs)) 663 center_freq = dfs->dfs_precac_secondary_freq_mhz; 664 else 665 center_freq = curchan->dfs_ch_mhz_freq_seg2; 666 } 667 668 if (WLAN_IS_CHAN_MODE_20(curchan)) { 669 nchannels = 1; 670 freq_list[0] = center_freq; 671 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 672 nchannels = 2; 673 freq_list[0] = center_freq - DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 674 freq_list[1] = center_freq + DFS_5GHZ_NEXT_CHAN_FREQ_OFFSET; 675 } else if (WLAN_IS_CHAN_MODE_80(curchan)) { 676 nchannels = 4; 677 dfs_get_80mhz_bonding_channels(center_freq, freq_list); 678 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 679 nchannels = 8; 680 if (detector_id == dfs_get_agile_detector_id(dfs)) 681 dfs_get_agile_subchans_for_curchan_160(dfs, 682 center_freq, 683 segment_id, 684 freq_list, 685 &nchannels); 686 else 687 dfs_get_160mhz_bonding_channels(center_freq, freq_list); 688 } else if (WLAN_IS_CHAN_MODE_80_80(curchan)) { 689 /* 690 * If the current channel's bandwidth is 80P80MHz, 691 * the corresponding agile Detector's bandwidth will be 160MHz 692 * in case of Pine ADFS. 693 */ 694 if (detector_id == dfs_get_agile_detector_id(dfs)) { 695 if (dfs->dfs_precac_chwidth == CH_WIDTH_160MHZ) { 696 nchannels = 8; 697 dfs_get_160mhz_bonding_channels(center_freq, 698 freq_list); 699 } else if (dfs->dfs_precac_chwidth == CH_WIDTH_80MHZ) { 700 nchannels = 4; 701 dfs_get_80mhz_bonding_channels(center_freq, 702 freq_list); 703 } else { 704 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 705 "Incorrect precac width %u", 706 dfs->dfs_precac_chwidth); 707 } 708 } else { 709 /* 710 * If the radar is getting detected in 80P80MHz home 711 * channel, only the 80MHz segment that is infected with 712 * radar is of interest. The other 80MHz segment is 713 * ignored. The center frequency of the radar infected 714 * segment is dfs_ch_mhz_freq_seg1 if primary and 715 * dfs_ch_mhz_freq_seg2 in case of secondary. 716 */ 717 nchannels = 4; 718 dfs_get_80mhz_bonding_channels(center_freq, freq_list); 719 } 720 } 721 722 return nchannels; 723 } 724 #endif 725 726 void dfs_reset_bangradar(struct wlan_dfs *dfs) 727 { 728 dfs->dfs_bangradar_type = DFS_NO_BANGRADAR; 729 } 730 731 /** 732 * dfs_radar_found_event_basic_sanity() - Check if radar event is received on a 733 * DFS channel. 734 * @dfs: Pointer to wlan_dfs structure. 735 * @chan: Current channel. 736 * 737 * Return: If a radar event found on NON-DFS channel return false. Otherwise, 738 * return true. 739 */ 740 static 741 bool dfs_radar_found_event_basic_sanity(struct wlan_dfs *dfs, 742 struct dfs_channel *chan) 743 { 744 if (!chan) { 745 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 746 "dfs->dfs_curchan is NULL"); 747 return false; 748 } 749 750 if (!(WLAN_IS_PRIMARY_OR_SECONDARY_CHAN_DFS(chan))) { 751 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, 752 "radar event on non-DFS chan"); 753 return false; 754 } 755 756 return true; 757 } 758 759 void dfs_send_csa_to_current_chan(struct wlan_dfs *dfs) 760 { 761 dfs->wlan_dfstest = 1; 762 dfs->wlan_dfstest_ieeechan = dfs->dfs_curchan->dfs_ch_ieee; 763 dfs->wlan_dfstesttime = 1; /* 1ms */ 764 qdf_timer_sync_cancel(&dfs->wlan_dfstesttimer); 765 qdf_timer_start(&dfs->wlan_dfstesttimer, dfs->wlan_dfstesttime); 766 } 767 768 int dfs_second_segment_radar_disable(struct wlan_dfs *dfs) 769 { 770 dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN; 771 772 return 0; 773 } 774 775 #ifdef WLAN_DFS_FULL_OFFLOAD 776 void dfs_inc_num_radar(struct wlan_dfs *dfs) 777 { 778 dfs->wlan_dfs_stats.num_radar_detects++; 779 } 780 #endif /* WLAN_DFS_FULL_OFFLOAD */ 781 782 #if defined(WLAN_DFS_TRUE_160MHZ_SUPPORT) && defined(WLAN_DFS_FULL_OFFLOAD) 783 void dfs_translate_radar_params(struct wlan_dfs *dfs, 784 struct radar_found_info *radar_found) 785 { 786 struct dfs_channel *curchan = dfs->dfs_curchan; 787 bool is_primary_ch_right_of_center = false; 788 789 if (!dfs_is_true_160mhz_supported(dfs)) 790 return; 791 792 if (radar_found->detector_id == dfs_get_agile_detector_id(dfs)) { 793 dfs_translate_radar_params_for_agile_chan(dfs, radar_found); 794 return; 795 } 796 797 /* Is the primary channel ( or primary 80 segment) to the right 798 * of the center of 160/165Mhz channel. 799 */ 800 if (curchan->dfs_ch_freq > curchan->dfs_ch_mhz_freq_seg2) 801 is_primary_ch_right_of_center = true; 802 803 if (WLAN_IS_CHAN_MODE_160(curchan)) { 804 if (radar_found->freq_offset > 0) { 805 /* Offset positive: Equivalent to Upper IEEE 806 * 80Mhz chans Synthesizer. 807 */ 808 if (!is_primary_ch_right_of_center) 809 radar_found->segment_id = SEG_ID_SECONDARY; 810 radar_found->freq_offset -= 811 DFS_160MHZ_SECOND_SEG_OFFSET; 812 } else { 813 /* Offset negative: Equivalent to Lower IEEE 814 * 80Mhz chans Synthesizer. 815 */ 816 if (is_primary_ch_right_of_center) 817 radar_found->segment_id = SEG_ID_SECONDARY; 818 radar_found->freq_offset += 819 DFS_160MHZ_SECOND_SEG_OFFSET; 820 } 821 } else if (WLAN_IS_CHAN_MODE_165(dfs, curchan)) { 822 /* If offset is greater than 40MHz, radar is found on the 823 * secondary segment. 824 */ 825 if (abs(radar_found->freq_offset) > 40) { 826 radar_found->segment_id = SEG_ID_SECONDARY; 827 /* Update the freq. offset with respect to the 828 * secondary segment center freq. 829 */ 830 if (is_primary_ch_right_of_center) 831 radar_found->freq_offset += 832 DFS_80P80MHZ_SECOND_SEG_OFFSET; 833 else 834 radar_found->freq_offset -= 835 DFS_80P80MHZ_SECOND_SEG_OFFSET; 836 } 837 } 838 } 839 #endif /* WLAN_DFS_TRUE_160MHZ_SUPPORT */ 840 841 /** 842 * dfs_radar_action_for_hw_mode_switch()- Radar cannot be processed when HW 843 * switch is in progress. So save the radar found parameters for 844 * future processing. 845 * @dfs: Pointer to wlan_dfs structure. 846 * @radar_found: Pointer to radar found structure. 847 * 848 * Return: QDF_STATUS 849 */ 850 static QDF_STATUS 851 dfs_radar_action_for_hw_mode_switch(struct wlan_dfs *dfs, 852 struct radar_found_info *radar_found) 853 { 854 struct radar_found_info *radar_params = NULL; 855 856 radar_params = qdf_mem_malloc(sizeof(*radar_params)); 857 if (!radar_params) 858 return QDF_STATUS_E_NOMEM; 859 860 /* If CAC timer is running, cancel it here rather than 861 * after processing to avoid handling unnecessary CAC timeouts. 862 */ 863 if (dfs->dfs_cac_timer_running) 864 dfs_cac_stop(dfs); 865 866 /* If CAC timer is to be handled after mode switch and then 867 * we receive radar, no point in handling CAC completion. 868 */ 869 if (dfs->dfs_defer_params.is_cac_completed) 870 dfs->dfs_defer_params.is_cac_completed = false; 871 qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params)); 872 dfs->dfs_defer_params.radar_params = radar_params; 873 dfs->dfs_defer_params.is_radar_detected = true; 874 875 return QDF_STATUS_SUCCESS; 876 } 877 878 #ifdef CONFIG_CHAN_FREQ_API 879 uint8_t 880 dfs_find_radar_affected_channels(struct wlan_dfs *dfs, 881 struct radar_found_info *radar_found, 882 uint16_t *freq_list, 883 uint32_t freq_center) 884 { 885 uint8_t num_channels; 886 887 if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS) 888 num_channels = 889 dfs_get_bonding_channel_without_seg_info_for_freq 890 (dfs->dfs_curchan, freq_list); 891 /* BW reduction is dependent on subchannel marking */ 892 else if ((dfs->dfs_use_nol_subchannel_marking) && 893 (!(dfs->dfs_bangradar_type) || 894 (dfs->dfs_bangradar_type == 895 DFS_BANGRADAR_FOR_SPECIFIC_SUBCHANS))) 896 num_channels = 897 dfs_find_radar_affected_subchans_for_freq(dfs, 898 radar_found, 899 freq_list, 900 freq_center); 901 else 902 num_channels = dfs_get_bonding_channels_for_freq 903 (dfs, 904 dfs->dfs_curchan, 905 radar_found->segment_id, 906 radar_found->detector_id, 907 freq_list); 908 909 return num_channels; 910 } 911 912 #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) || \ 913 defined(QCA_SUPPORT_ADFS_RCAC) 914 /** 915 * dfs_is_radarsource_agile() - Indicates whether the radar event is received 916 * on the agile channel. 917 * @dfs: Pointer to wlan_dfs structure. 918 * @radar_found: Pointer to radar_found_info structure. 919 * 920 * Return: QDF_STATUS 921 */ 922 static 923 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs, 924 struct radar_found_info *radar_found) 925 { 926 bool is_radar_from_agile_dfs = 927 ((dfs_is_agile_precac_enabled(dfs) && 928 dfs_is_precac_timer_running(dfs)) || 929 dfs_is_agile_rcac_enabled(dfs)) && 930 (radar_found->detector_id == dfs_get_agile_detector_id(dfs)); 931 bool is_radar_from_zero_wait_dfs = 932 (dfs_is_legacy_precac_enabled(dfs) && 933 dfs_is_precac_timer_running(dfs) && 934 (radar_found->segment_id == SEG_ID_SECONDARY)); 935 936 dfs_debug(dfs, WLAN_DEBUG_DFS_AGILE, 937 "radar on PreCAC segment: ADFS:%d Zero Wait DFS:%d", 938 is_radar_from_agile_dfs, 939 is_radar_from_zero_wait_dfs); 940 941 return (is_radar_from_agile_dfs || is_radar_from_zero_wait_dfs); 942 } 943 #else 944 static 945 bool dfs_is_radarsource_agile(struct wlan_dfs *dfs, 946 struct radar_found_info *radar_found) 947 { 948 return false; 949 } 950 #endif 951 952 QDF_STATUS 953 dfs_process_radar_ind(struct wlan_dfs *dfs, 954 struct radar_found_info *radar_found) 955 { 956 QDF_STATUS status; 957 958 /* Acquire a lock to avoid initiating mode switch till radar 959 * processing is completed. 960 */ 961 DFS_RADAR_MODE_SWITCH_LOCK(dfs); 962 963 if (utils_dfs_can_ignore_radar_event(dfs->dfs_pdev_obj)) { 964 DFS_RADAR_MODE_SWITCH_UNLOCK(dfs); 965 return QDF_STATUS_SUCCESS; 966 } 967 968 /* Before processing radar, check if HW mode switch is in progress. 969 * If in progress, defer the processing of radar event received till 970 * the mode switch is completed. 971 */ 972 if (dfs_is_hw_mode_switch_in_progress(dfs)) 973 status = dfs_radar_action_for_hw_mode_switch(dfs, radar_found); 974 else if (dfs_is_radarsource_agile(dfs, radar_found)) 975 status = dfs_process_radar_ind_on_agile_chan(dfs, radar_found); 976 else 977 status = dfs_process_radar_ind_on_home_chan(dfs, radar_found); 978 979 DFS_RADAR_MODE_SWITCH_UNLOCK(dfs); 980 981 return status; 982 } 983 984 QDF_STATUS 985 dfs_process_radar_ind_on_home_chan(struct wlan_dfs *dfs, 986 struct radar_found_info *radar_found) 987 { 988 bool wait_for_csa = false; 989 uint16_t freq_list[NUM_CHANNELS_160MHZ]; 990 uint16_t nol_freq_list[NUM_CHANNELS_160MHZ]; 991 uint8_t num_channels; 992 QDF_STATUS status = QDF_STATUS_E_FAILURE; 993 uint32_t freq_center; 994 uint32_t radarfound_freq; 995 struct dfs_channel *dfs_curchan; 996 997 dfs_curchan = dfs->dfs_curchan; 998 999 /* Check if the current channel is a non DFS channel 1000 * If the current channel is non-DFS and the radar is from Agile 1001 * Detector we need to process it since Agile Detector has a 1002 * different channel. 1003 */ 1004 if (!dfs_radar_found_event_basic_sanity(dfs, dfs_curchan)) 1005 goto exit; 1006 1007 dfs_compute_radar_found_cfreq(dfs, radar_found, &freq_center); 1008 radarfound_freq = freq_center + radar_found->freq_offset; 1009 1010 if (radar_found->segment_id == SEG_ID_SECONDARY) 1011 dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, 1012 "Radar found on second segment.Radarfound Freq=%d MHz.Secondary Chan cfreq=%d MHz.", 1013 radarfound_freq, freq_center); 1014 else 1015 dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS, 1016 "Radar found on channel=%d, freq=%d MHz. Primary beaconning chan:%d, freq=%d MHz.", 1017 utils_dfs_freq_to_chan(radarfound_freq), 1018 radarfound_freq, dfs_curchan->dfs_ch_ieee, 1019 dfs_curchan->dfs_ch_freq); 1020 1021 utils_dfs_deliver_event(dfs->dfs_pdev_obj, radarfound_freq, 1022 WLAN_EV_RADAR_DETECTED); 1023 1024 if (!dfs->dfs_use_nol) { 1025 if (!dfs->dfs_is_offload_enabled) { 1026 dfs_radar_disable(dfs); 1027 dfs_second_segment_radar_disable(dfs); 1028 dfs_flush_additional_pulses(dfs); 1029 } 1030 dfs_reset_bangradar(dfs); 1031 dfs_send_csa_to_current_chan(dfs); 1032 status = QDF_STATUS_SUCCESS; 1033 goto exit; 1034 } 1035 num_channels = dfs_find_radar_affected_channels(dfs, 1036 radar_found, 1037 freq_list, 1038 freq_center); 1039 1040 dfs_reset_bangradar(dfs); 1041 1042 status = dfs_radar_add_channel_list_to_nol_for_freq(dfs, 1043 freq_list, 1044 nol_freq_list, 1045 &num_channels); 1046 if (QDF_IS_STATUS_ERROR(status)) { 1047 dfs_err(dfs, WLAN_DEBUG_DFS, 1048 "radar event received on invalid channel"); 1049 goto exit; 1050 } 1051 1052 /* 1053 * If precac is running and the radar found in secondary 1054 * VHT80 mark the channel as radar and add to NOL list. 1055 * Otherwise random channel selection can choose this 1056 * channel. 1057 */ 1058 dfs_debug(dfs, WLAN_DEBUG_DFS, 1059 "found_on_second=%d is_pre=%d", 1060 dfs->is_radar_found_on_secondary_seg, 1061 dfs_is_precac_timer_running(dfs)); 1062 /* 1063 * Even if radar found on primary, we need to mark the channel as NOL 1064 * in preCAC list. The preCAC list also maintains the current CAC 1065 * channels as part of pre-cleared DFS. Hence call the API 1066 * to mark channels as NOL irrespective of preCAC being enabled or not. 1067 */ 1068 1069 dfs_debug(dfs, WLAN_DEBUG_DFS, 1070 "Radar found on dfs detector: %d", radar_found->detector_id); 1071 dfs_mark_precac_nol_for_freq(dfs, 1072 dfs->is_radar_found_on_secondary_seg, 1073 radar_found->detector_id, 1074 nol_freq_list, 1075 num_channels); 1076 1077 dfs_send_nol_ie_and_rcsa(dfs, 1078 radar_found, 1079 nol_freq_list, 1080 num_channels, 1081 &wait_for_csa); 1082 1083 if (!dfs->dfs_is_offload_enabled && 1084 dfs->is_radar_found_on_secondary_seg) { 1085 dfs_second_segment_radar_disable(dfs); 1086 dfs->is_radar_found_on_secondary_seg = 0; 1087 1088 if (dfs->is_radar_during_precac) { 1089 dfs->is_radar_during_precac = 0; 1090 goto exit; 1091 } 1092 } 1093 1094 /* 1095 * XXX TODO: the umac NOL code isn't used, but 1096 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac 1097 * NOL code isn't used, that flag is never cleared. This 1098 * needs to be fixed. See EV 105776. 1099 */ 1100 if (wait_for_csa) 1101 goto exit; 1102 1103 /* 1104 * EV 129487 : We have detected radar in the channel, 1105 * stop processing PHY error data as this can cause 1106 * false detect in the new channel while channel 1107 * change is in progress. 1108 */ 1109 1110 if (!dfs->dfs_is_offload_enabled) { 1111 dfs_radar_disable(dfs); 1112 dfs_second_segment_radar_disable(dfs); 1113 /* 1114 * The radar queues were reset just after the filter match, but 1115 * the phyerror reception was not disabled. This might 1116 * cause the unwanted additional/accumulated pulses to be 1117 * detected as radar in the new channel. So, clear the radar 1118 * queues and the associated variables. 1119 */ 1120 dfs_flush_additional_pulses(dfs); 1121 } 1122 1123 dfs_mlme_mark_dfs(dfs->dfs_pdev_obj, 1124 dfs->dfs_curchan->dfs_ch_ieee, 1125 dfs->dfs_curchan->dfs_ch_freq, 1126 dfs->dfs_curchan->dfs_ch_mhz_freq_seg2, 1127 dfs->dfs_curchan->dfs_ch_flags); 1128 1129 exit: 1130 return status; 1131 } 1132 #endif 1133