1 /* 2 * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: API for processing radar found indication. 21 * 22 */ 23 24 #include "../dfs.h" 25 #include "../dfs_process_radar_found_ind.h" 26 #include <wlan_reg_services_api.h> 27 #include <wlan_dfs_utils_api.h> 28 #include "wlan_dfs_mlme_api.h" 29 30 /** 31 * TODO: The code is not according to the following description needs 32 * modification and correction. Code always adds left and right channels to 33 * NOL even if it is not a chirp radar. 34 * 35 * A) If chirp radar starts at boundary and ends at boundary then three channels 36 * will be affected. 37 * freq_offset.freq[0] = fn (Center frequency) 38 * freq_offset.freq[1] = fn-1 (Left of center) 39 * freq_offset.freq[2] = fn+1 (Right of center) 40 * 41 * Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL. 42 * 43 * Chirp start freq Chirp end freq 44 * | | 45 * | | 46 * V V 47 * _______________________________________________________________________ 48 * | center freq | center freq | center freq | 49 * | ch(n-1) | ch(n) | ch(n+1) | 50 * | | | | | | | 51 * | | | | | | | 52 * | | | | | | | 53 * fn-1 fn boundary fn+1 54 * <-------- 20 Mhz ------> 55 * 56 * B) If chirp radar starts at one channel and continues up to another channel 57 * then two channels will be affected. 58 * freq_offset.freq[0] = fn 59 * freq_offset.freq[1] = 0 60 * freq_offset.freq[2] = fn+1 61 * 62 * Three channels, ch(n-1), ch(n)and ch(n+1) will be added to NOL. 63 * 64 * Chirp start freq Chirp end freq 65 * | | 66 * | | 67 * V V 68 * _______________________________________________________________________ 69 * | center freq | center freq | center freq | 70 * | ch(n-1) | ch(n) | ch(n+1) | 71 * | | | | | | | 72 * | | | | | | | 73 * | | | | | | | 74 * fn-1 fn boundary fn+1 75 * <-------- 20 Mhz ------> 76 * 77 * C) Radar found at boundary, two channels will be affected. 78 * freq_offset.freq[0] = fn 79 * freq_offset.freq[1] = 0 80 * freq_offset.freq[2] = fn+1 81 * 82 * Two channels, ch(n) and ch(n+1) will be added to NOL. 83 * 84 * dfs_freq_offset (radar found freq) 85 * | 86 * | 87 * V 88 * _______________________________________________________________________ 89 * | center freq | center freq | center freq | 90 * | ch(n-1) | ch(n) | ch(n+1) | 91 * | | | | | | | 92 * | | | | | | | 93 * | | | | | | | 94 * fn-1 fn boundary fn+1 95 * <-------- 20 Mhz ------> 96 * 97 * 98 * D) Else only one channel will be affected. 99 * freq_offset.freq[0] = fn 100 * freq_offset.freq[1] = 0 101 * freq_offset.freq[2] = 0 102 * 103 * One channel ch(n) will be added to NOL. 104 * 105 * 106 * dfs_freq_offset (radar found freq) 107 * | 108 * | 109 * V 110 * _______________________________________________________________________ 111 * | center freq | center freq | center freq | 112 * | ch(n-1) | ch(n) | ch(n+1) | 113 * | | | | | | | 114 * | | | | | | | 115 * | | | | | | | 116 * fn-1 fn boundary fn+1 117 * <-------- 20 Mhz ------> 118 */ 119 120 /** 121 * dfs_radar_add_channel_list_to_nol()- Add given channels to nol 122 * @dfs: Pointer to wlan_dfs structure. 123 * @channels: Pointer to the channel list. 124 * @num_channels: Number of channels in the list. 125 * 126 * Add list of channels to nol, only if the channel is dfs. 127 * 128 * Return: QDF_STATUS 129 */ 130 static QDF_STATUS dfs_radar_add_channel_list_to_nol(struct wlan_dfs *dfs, 131 uint8_t *channels, 132 uint8_t num_channels) 133 { 134 int i; 135 uint8_t last_chan = 0; 136 uint8_t nollist[NUM_CHANNELS_160MHZ]; 137 uint8_t num_ch = 0; 138 139 if (num_channels > NUM_CHANNELS_160MHZ) { 140 dfs_err(dfs, WLAN_DEBUG_DFS, 141 "Invalid num channels: %d", num_channels); 142 return QDF_STATUS_E_FAILURE; 143 } 144 145 for (i = 0; i < num_channels; i++) { 146 if (channels[i] == 0 || 147 channels[i] == last_chan) 148 continue; 149 if (!utils_is_dfs_ch(dfs->dfs_pdev_obj, channels[i])) { 150 dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d is not dfs, skip", 151 channels[i]); 152 continue; 153 } 154 last_chan = channels[i]; 155 DFS_NOL_ADD_CHAN_LOCKED(dfs, 156 (uint16_t)utils_dfs_chan_to_freq(channels[i]), 157 dfs->wlan_dfs_nol_timeout); 158 nollist[num_ch++] = last_chan; 159 dfs_info(dfs, WLAN_DEBUG_DFS, "ch=%d Added to NOL", last_chan); 160 } 161 162 if (!num_ch) { 163 dfs_err(dfs, WLAN_DEBUG_DFS, 164 "dfs channels not found in channel list"); 165 return QDF_STATUS_E_FAILURE; 166 } 167 168 utils_dfs_reg_update_nol_ch(dfs->dfs_pdev_obj, 169 nollist, num_ch, DFS_NOL_SET); 170 dfs_nol_update(dfs); 171 utils_dfs_save_nol(dfs->dfs_pdev_obj); 172 173 return QDF_STATUS_SUCCESS; 174 } 175 176 /** 177 * dfs_radar_chan_for_80()- Find frequency offsets for 80MHz 178 * @freq_offset: freq offset 179 * @center_freq: center frequency 180 * 181 * Find frequency offsets for 80MHz 182 * 183 * Return: None 184 */ 185 static void dfs_radar_chan_for_80(struct freqs_offsets *freq_offset, 186 uint32_t center_freq) 187 { 188 int i; 189 190 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 191 if (freq_offset->offset[i] < DFS_OFFET_SECOND_LOWER) 192 freq_offset->freq[i] = 193 DFS_THIRD_LOWER_CHANNEL(center_freq); 194 else if ((freq_offset->offset[i] > DFS_OFFET_SECOND_LOWER) && 195 (freq_offset->offset[i] < DFS_OFFET_FIRST_LOWER)) 196 freq_offset->freq[i] = 197 DFS_SECOND_LOWER_CHANNEL(center_freq); 198 else if ((freq_offset->offset[i] > DFS_OFFET_FIRST_LOWER) && 199 (freq_offset->offset[i] < 0)) 200 freq_offset->freq[i] = 201 DFS_FIRST_LOWER_CHANNEL(center_freq); 202 else if ((freq_offset->offset[i] > 0) && 203 (freq_offset->offset[i] < DFS_OFFET_FIRST_UPPER)) 204 freq_offset->freq[i] = 205 DFS_FIRST_UPPER_CHANNEL(center_freq); 206 else if ((freq_offset->offset[i] > DFS_OFFET_FIRST_UPPER) && 207 (freq_offset->offset[i] < DFS_OFFET_SECOND_UPPER)) 208 freq_offset->freq[i] = 209 DFS_SECOND_UPPER_CHANNEL(center_freq); 210 else if (freq_offset->offset[i] > DFS_OFFET_SECOND_UPPER) 211 freq_offset->freq[i] = 212 DFS_THIRD_UPPER_CHANNEL(center_freq); 213 } 214 } 215 216 /** 217 * dfs_radar_chan_for_40()- Find frequency offsets for 40MHz 218 * @freq_offset: freq offset 219 * @center_freq: center frequency 220 * 221 * Find frequency offsets for 40MHz 222 * 223 * Return: None 224 */ 225 static void dfs_radar_chan_for_40(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_OFFET_FIRST_LOWER) 232 freq_offset->freq[i] = 233 DFS_SECOND_LOWER_CHANNEL(center_freq); 234 else if ((freq_offset->offset[i] > DFS_OFFET_FIRST_LOWER) && 235 (freq_offset->offset[i] < 0)) 236 freq_offset->freq[i] = 237 DFS_FIRST_LOWER_CHANNEL(center_freq); 238 else if ((freq_offset->offset[i] > 0) && 239 (freq_offset->offset[i] < DFS_OFFET_FIRST_UPPER)) 240 freq_offset->freq[i] = 241 DFS_FIRST_UPPER_CHANNEL(center_freq); 242 else if (freq_offset->offset[i] > DFS_OFFET_FIRST_UPPER) 243 freq_offset->freq[i] = 244 DFS_SECOND_UPPER_CHANNEL(center_freq); 245 } 246 } 247 248 /** 249 * dfs_radar_chan_for_20()- Find frequency offsets for 20MHz 250 * @freq_offset: freq offset 251 * @center_freq: center frequency 252 * 253 * Find frequency offsets for 20MHz 254 * 255 * Return: None 256 */ 257 static void dfs_radar_chan_for_20(struct freqs_offsets *freq_offset, 258 uint32_t center_freq) 259 { 260 int i; 261 262 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 263 if (freq_offset->offset[i] <= DFS_20MZ_OFFSET_LOWER) 264 freq_offset->freq[i] = 265 DFS_20MHZ_LOWER_CHANNEL(center_freq); 266 else if ((freq_offset->offset[i] > DFS_20MZ_OFFSET_LOWER) && 267 (freq_offset->offset[i] < DFS_20MZ_OFFSET_UPPER)) 268 freq_offset->freq[i] = center_freq; 269 else if (freq_offset->offset[i] >= DFS_20MZ_OFFSET_UPPER) 270 freq_offset->freq[i] = 271 DFS_20MHZ_UPPER_CHANNEL(center_freq); 272 } 273 } 274 275 /** 276 * dfs_find_radar_affected_subchans() - Finds radar affected sub channels. 277 * @dfs: Pointer to wlan_dfs structure. 278 * @radar_found: Pointer to radar_found structure. 279 * @channels: Pointer to save radar affected channels. 280 * 281 * Return: Number of channels. 282 */ 283 static uint8_t dfs_find_radar_affected_subchans(struct wlan_dfs *dfs, 284 struct radar_found_info 285 *radar_found, 286 uint8_t *channels) 287 { 288 int i; 289 uint32_t freq_center, flag; 290 int32_t sidx; 291 struct dfs_channel *curchan = dfs->dfs_curchan; 292 struct freqs_offsets freq_offset; 293 294 qdf_mem_set(&freq_offset, sizeof(freq_offset), 0); 295 flag = curchan->dfs_ch_flags; 296 297 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) 298 freq_offset.offset[i] = radar_found->freq_offset; 299 300 sidx = DFS_FREQ_OFFSET_TO_SIDX(radar_found->freq_offset); 301 302 if (!radar_found->segment_id) 303 freq_center = utils_dfs_chan_to_freq( 304 curchan->dfs_ch_vhtop_ch_freq_seg1); 305 else { 306 if (dfs_is_precac_timer_running(dfs)) { 307 freq_center = utils_dfs_chan_to_freq( 308 dfs->dfs_precac_secondary_freq); 309 } else { 310 freq_center = utils_dfs_chan_to_freq( 311 curchan->dfs_ch_vhtop_ch_freq_seg2); 312 if (flag & WLAN_CHAN_VHT160) 313 freq_center += DFS_160MHZ_SECOND_SEG_OFFSET; 314 } 315 } 316 317 dfs_info(dfs, WLAN_DEBUG_DFS, 318 "seg=%d, sidx=%d, offset=%d, chirp=%d, flag=%d, f=%d", 319 radar_found->segment_id, sidx, 320 radar_found->freq_offset, radar_found->is_chirp, 321 flag, freq_center); 322 323 if ((WLAN_IS_CHAN_A(curchan)) || 324 WLAN_IS_CHAN_MODE_20(curchan)) { 325 if (radar_found->is_chirp || 326 (sidx && !(abs(sidx) % DFS_BOUNDARY_SIDX))) { 327 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 328 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 329 } 330 dfs_radar_chan_for_20(&freq_offset, freq_center); 331 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 332 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 333 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 334 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 335 } 336 dfs_radar_chan_for_40(&freq_offset, freq_center); 337 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 338 WLAN_IS_CHAN_MODE_160(curchan) || 339 WLAN_IS_CHAN_MODE_80_80(curchan)) { 340 if (radar_found->is_chirp || !(abs(sidx) % DFS_BOUNDARY_SIDX)) { 341 freq_offset.offset[LEFT_CH] -= DFS_CHIRP_OFFSET; 342 freq_offset.offset[RIGHT_CH] += DFS_CHIRP_OFFSET; 343 } 344 dfs_radar_chan_for_80(&freq_offset, freq_center); 345 } else { 346 dfs_err(dfs, WLAN_DEBUG_DFS, 347 "channel flag=%d is invalid", flag); 348 return 0; 349 } 350 351 for (i = 0; i < DFS_NUM_FREQ_OFFSET; i++) { 352 channels[i] = utils_dfs_freq_to_chan(freq_offset.freq[i]); 353 dfs_info(dfs, WLAN_DEBUG_DFS, "offset=%d, channel=%d", 354 i, channels[i]); 355 } 356 357 return i; 358 } 359 360 /** 361 * dfs_get_bonding_channels() - Get bonding channels. 362 * @curchan: Pointer to dfs_channels to know width and primary channel. 363 * @segment_id: Segment id, useful for 80+80/160 MHz operating band. 364 * @channels: Pointer to save radar affected channels. 365 * 366 * Return: Number of channels. 367 */ 368 static uint8_t dfs_get_bonding_channels(struct dfs_channel *curchan, 369 uint32_t segment_id, 370 uint8_t *channels) 371 { 372 uint8_t center_chan; 373 uint8_t nchannels = 0; 374 375 if (!segment_id) 376 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg1; 377 else 378 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 379 380 if (WLAN_IS_CHAN_MODE_20(curchan)) { 381 nchannels = 1; 382 channels[0] = center_chan; 383 } else if (WLAN_IS_CHAN_MODE_40(curchan)) { 384 nchannels = 2; 385 channels[0] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 386 channels[1] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 387 } else if (WLAN_IS_CHAN_MODE_80(curchan) || 388 WLAN_IS_CHAN_MODE_80_80(curchan)) { 389 nchannels = 4; 390 channels[0] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 391 channels[1] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 392 channels[2] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 393 channels[3] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 394 } else if (WLAN_IS_CHAN_MODE_160(curchan)) { 395 nchannels = 8; 396 center_chan = curchan->dfs_ch_vhtop_ch_freq_seg2; 397 channels[0] = center_chan - DFS_5GHZ_4TH_CHAN_OFFSET; 398 channels[1] = center_chan - DFS_5GHZ_3RD_CHAN_OFFSET; 399 channels[2] = center_chan - DFS_5GHZ_2ND_CHAN_OFFSET; 400 channels[3] = center_chan - DFS_5GHZ_NEXT_CHAN_OFFSET; 401 channels[4] = center_chan + DFS_5GHZ_NEXT_CHAN_OFFSET; 402 channels[5] = center_chan + DFS_5GHZ_2ND_CHAN_OFFSET; 403 channels[6] = center_chan + DFS_5GHZ_3RD_CHAN_OFFSET; 404 channels[7] = center_chan + DFS_5GHZ_4TH_CHAN_OFFSET; 405 } 406 407 return nchannels; 408 } 409 410 QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, 411 struct radar_found_info *radar_found) 412 { 413 bool wait_for_csa = false; 414 uint8_t channels[NUM_CHANNELS_160MHZ]; 415 uint8_t num_channels; 416 QDF_STATUS status; 417 418 if (!dfs->dfs_curchan) { 419 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs->dfs_curchan is NULL"); 420 return QDF_STATUS_E_FAILURE; 421 } 422 423 /* Check if the current channel is a non DFS channel */ 424 if (!dfs_radarevent_basic_sanity(dfs, dfs->dfs_curchan)) { 425 dfs_err(dfs, WLAN_DEBUG_DFS, 426 "radar event on a non-DFS channel"); 427 return QDF_STATUS_E_FAILURE; 428 } 429 430 if (!dfs->dfs_use_nol) { 431 dfs_send_csa_to_current_chan(dfs); 432 return QDF_STATUS_SUCCESS; 433 } 434 435 if (dfs->dfs_use_nol_subchannel_marking) 436 num_channels = dfs_find_radar_affected_subchans(dfs, 437 radar_found, 438 channels); 439 else 440 num_channels = dfs_get_bonding_channels(dfs->dfs_curchan, 441 radar_found->segment_id, 442 channels); 443 444 status = dfs_radar_add_channel_list_to_nol(dfs, channels, num_channels); 445 if (QDF_IS_STATUS_ERROR(status)) { 446 dfs_err(dfs, WLAN_DEBUG_DFS, 447 "radar event received on invalid channel"); 448 return status; 449 } 450 451 if (radar_found->segment_id == SEG_ID_SECONDARY) 452 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 453 "Radar found on second segment VHT80 freq=%d MHz", 454 dfs->dfs_precac_secondary_freq); 455 else 456 dfs_info(NULL, WLAN_DEBUG_DFS_ALWAYS, 457 "Radar found on channel=%d, freq=%d MHz", 458 dfs->dfs_curchan->dfs_ch_ieee, 459 dfs->dfs_curchan->dfs_ch_freq); 460 461 /* 462 * If precac is running and the radar found in secondary 463 * VHT80 mark the channel as radar and add to NOL list. 464 * Otherwise random channel selection can choose this 465 * channel. 466 */ 467 dfs_debug(dfs, WLAN_DEBUG_DFS, 468 "found_on_second=%d is_pre=%d", 469 dfs->is_radar_found_on_secondary_seg, 470 dfs_is_precac_timer_running(dfs)); 471 472 /* 473 * Even if radar found on primary, we need to move the channel 474 * from precac-required-list and precac-done-list to 475 * precac-nol-list. 476 */ 477 if (dfs->dfs_precac_enable) 478 dfs_mark_precac_dfs(dfs, dfs->is_radar_found_on_secondary_seg); 479 480 if (!dfs->dfs_is_offload_enabled && 481 dfs->is_radar_found_on_secondary_seg) { 482 dfs_second_segment_radar_disable(dfs); 483 dfs->is_radar_found_on_secondary_seg = 0; 484 485 if (dfs->is_radar_during_precac) { 486 dfs->is_radar_during_precac = 0; 487 return QDF_STATUS_SUCCESS; 488 } 489 } 490 491 /* 492 * This calls into the umac DFS code, which sets the umac 493 * related radar flags and begins the channel change 494 * machinery. 495 * XXX TODO: the umac NOL code isn't used, but 496 * WLAN_CHAN_DFS_RADAR still gets set. Since the umac 497 * NOL code isn't used, that flag is never cleared. This 498 * needs to be fixed. See EV 105776. 499 */ 500 dfs_mlme_start_rcsa(dfs->dfs_pdev_obj, &wait_for_csa); 501 if (wait_for_csa) 502 return QDF_STATUS_SUCCESS; 503 504 /* 505 * EV 129487 : We have detected radar in the channel, 506 * stop processing PHY error data as this can cause 507 * false detect in the new channel while channel 508 * change is in progress. 509 */ 510 511 if (!dfs->dfs_is_offload_enabled) { 512 dfs_radar_disable(dfs); 513 dfs_second_segment_radar_disable(dfs); 514 } 515 516 dfs_mlme_mark_dfs(dfs->dfs_pdev_obj, 517 dfs->dfs_curchan->dfs_ch_ieee, 518 dfs->dfs_curchan->dfs_ch_freq, 519 dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2, 520 dfs->dfs_curchan->dfs_ch_flags); 521 522 return QDF_STATUS_SUCCESS; 523 } 524