1 /* 2 * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2011, Atheros Communications Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "../dfs.h" 19 #include "../dfs_zero_cac.h" 20 #include "../dfs_filter_init.h" 21 #include "wlan_dfs_mlme_api.h" 22 #include "wlan_dfs_lmac_api.h" 23 #include "../dfs_partial_offload_radar.h" 24 #include "../dfs_internal.h" 25 26 void dfs_get_radars(struct wlan_dfs *dfs) 27 { 28 struct wlan_objmgr_psoc *psoc; 29 30 if (!dfs) { 31 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 32 return; 33 } 34 35 psoc = wlan_pdev_get_psoc(dfs->dfs_pdev_obj); 36 if (!psoc) { 37 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "psoc is NULL"); 38 return; 39 } 40 41 if (wlan_objmgr_psoc_get_dev_type(psoc) == WLAN_DEV_OL) { 42 /* For Partial offload */ 43 dfs_get_po_radars(dfs); 44 } 45 } 46 47 int dfs_radar_disable(struct wlan_dfs *dfs) 48 { 49 dfs->dfs_proc_phyerr &= ~DFS_AR_EN; 50 dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; 51 52 return 0; 53 } 54 55 void dfs_phyerr_param_copy(struct wlan_dfs_phyerr_param *dst, 56 struct wlan_dfs_phyerr_param *src) 57 { 58 qdf_mem_copy(dst, src, sizeof(*dst)); 59 } 60 61 #ifdef CONFIG_CHAN_FREQ_API 62 struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index, 63 int ext_chan_flag) 64 { 65 struct dfs_state *rs = NULL; 66 struct dfs_channel *ch, cmp_ch1; 67 int i; 68 QDF_STATUS err; 69 70 if (!dfs) { 71 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 72 return NULL; 73 } 74 ch = &cmp_ch1; 75 if (ext_chan_flag) { 76 err = dfs_mlme_get_extchan_for_freq( 77 dfs->dfs_pdev_obj, 78 &ch->dfs_ch_freq, 79 &ch->dfs_ch_flags, 80 &ch->dfs_ch_flagext, 81 &ch->dfs_ch_ieee, 82 &ch->dfs_ch_vhtop_ch_freq_seg1, 83 &ch->dfs_ch_vhtop_ch_freq_seg2, 84 &ch->dfs_ch_mhz_freq_seg1, 85 &ch->dfs_ch_mhz_freq_seg2); 86 87 if (err == QDF_STATUS_SUCCESS) { 88 dfs_debug(dfs, WLAN_DEBUG_DFS2, 89 "Extension channel freq = %u flags=0x%x", 90 ch->dfs_ch_freq, 91 ch->dfs_ch_flagext); 92 } else { 93 return NULL; 94 } 95 } else { 96 ch = dfs->dfs_curchan; 97 dfs_debug(dfs, WLAN_DEBUG_DFS2, 98 "Primary channel freq = %u flags=0x%x", 99 ch->dfs_ch_freq, ch->dfs_ch_flagext); 100 } 101 102 for (i = 0; i < DFS_NUM_RADAR_STATES; i++) { 103 if ((dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 104 ch->dfs_ch_freq) && 105 (dfs->dfs_radar[i].rs_chan.dfs_ch_flags == 106 ch->dfs_ch_flags)) { 107 if (index) 108 *index = (uint8_t)i; 109 return &dfs->dfs_radar[i]; 110 } 111 } 112 /* No existing channel found, look for first free channel state entry.*/ 113 for (i = 0; i < DFS_NUM_RADAR_STATES; i++) { 114 if (dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 0) { 115 rs = &dfs->dfs_radar[i]; 116 /* Found one, set channel info and default thresholds.*/ 117 rs->rs_chan = *ch; 118 119 /* Copy the parameters from the default set. */ 120 dfs_phyerr_param_copy(&rs->rs_param, 121 &dfs->dfs_defaultparams); 122 123 if (index) 124 *index = (uint8_t)i; 125 126 return rs; 127 } 128 } 129 dfs_debug(dfs, WLAN_DEBUG_DFS2, "No more radar states left."); 130 131 return NULL; 132 } 133 #else 134 #ifdef CONFIG_CHAN_NUM_API 135 struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index, 136 int ext_chan_flag) 137 { 138 struct dfs_state *rs = NULL; 139 struct dfs_channel *cmp_ch, cmp_ch1; 140 int i; 141 QDF_STATUS err; 142 143 if (!dfs) { 144 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 145 return NULL; 146 } 147 cmp_ch = &cmp_ch1; 148 if (ext_chan_flag) { 149 err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj, 150 &(cmp_ch->dfs_ch_freq), 151 &(cmp_ch->dfs_ch_flags), 152 &(cmp_ch->dfs_ch_flagext), 153 &(cmp_ch->dfs_ch_ieee), 154 &(cmp_ch->dfs_ch_vhtop_ch_freq_seg1), 155 &(cmp_ch->dfs_ch_vhtop_ch_freq_seg2)); 156 157 if (err == QDF_STATUS_SUCCESS) { 158 dfs_debug(dfs, WLAN_DEBUG_DFS2, 159 "Extension channel freq = %u flags=0x%x", 160 cmp_ch->dfs_ch_freq, 161 cmp_ch->dfs_ch_flagext); 162 } else 163 return NULL; 164 } else { 165 cmp_ch = dfs->dfs_curchan; 166 dfs_debug(dfs, WLAN_DEBUG_DFS2, 167 "Primary channel freq = %u flags=0x%x", 168 cmp_ch->dfs_ch_freq, cmp_ch->dfs_ch_flagext); 169 } 170 171 for (i = 0; i < DFS_NUM_RADAR_STATES; i++) { 172 if ((dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 173 cmp_ch->dfs_ch_freq) && 174 (dfs->dfs_radar[i].rs_chan.dfs_ch_flags == 175 cmp_ch->dfs_ch_flags) 176 ) { 177 if (index) 178 *index = (uint8_t)i; 179 return &(dfs->dfs_radar[i]); 180 } 181 } 182 /* No existing channel found, look for first free channel state entry.*/ 183 for (i = 0; i < DFS_NUM_RADAR_STATES; i++) { 184 if (dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 0) { 185 rs = &(dfs->dfs_radar[i]); 186 /* Found one, set channel info and default thresholds.*/ 187 rs->rs_chan = *cmp_ch; 188 189 /* Copy the parameters from the default set. */ 190 dfs_phyerr_param_copy(&rs->rs_param, 191 &dfs->dfs_defaultparams); 192 193 if (index) 194 *index = (uint8_t)i; 195 196 return rs; 197 } 198 } 199 dfs_debug(dfs, WLAN_DEBUG_DFS2, "No more radar states left."); 200 201 return NULL; 202 } 203 #endif 204 #endif 205 206 #ifdef CONFIG_CHAN_FREQ_API 207 void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode) 208 { 209 int is_ext_ch; 210 int is_fastclk = 0; 211 struct dfs_channel *exch, extchan; 212 QDF_STATUS err = QDF_STATUS_E_FAILURE; 213 214 if (!dfs) { 215 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 216 return; 217 } 218 219 is_ext_ch = WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan); 220 lmac_dfs_disable(dfs->dfs_pdev_obj, no_cac); 221 /* 222 * In all modes, if the primary is DFS then we have to 223 * enable radar detection. In HT80_80, we can have 224 * primary non-DFS 80MHz with extension 80MHz DFS. 225 */ 226 if ((WLAN_IS_CHAN_DFS(dfs->dfs_curchan) || 227 ((WLAN_IS_CHAN_11AC_VHT160(dfs->dfs_curchan) || 228 WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) && 229 WLAN_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) || 230 (dfs_is_precac_timer_running(dfs))) { 231 struct dfs_state *rs_pri = NULL, *rs_ext = NULL; 232 uint8_t index_pri, index_ext; 233 234 dfs->dfs_proc_phyerr |= DFS_AR_EN; 235 dfs->dfs_proc_phyerr |= DFS_RADAR_EN; 236 dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN; 237 238 exch = &extchan; 239 if (is_ext_ch) { 240 err = dfs_mlme_get_extchan_for_freq 241 ( 242 dfs->dfs_pdev_obj, 243 &exch->dfs_ch_freq, 244 &exch->dfs_ch_flags, 245 &exch->dfs_ch_flagext, 246 &exch->dfs_ch_ieee, 247 &exch->dfs_ch_vhtop_ch_freq_seg1, 248 &exch->dfs_ch_vhtop_ch_freq_seg2, 249 &exch->dfs_ch_mhz_freq_seg1, 250 &exch->dfs_ch_mhz_freq_seg2); 251 } 252 dfs_reset_alldelaylines(dfs); 253 254 rs_pri = dfs_getchanstate(dfs, &index_pri, 0); 255 if (err == QDF_STATUS_SUCCESS) 256 rs_ext = dfs_getchanstate(dfs, &index_ext, 1); 257 258 if (rs_pri && ((err == QDF_STATUS_E_FAILURE) || (rs_ext))) { 259 struct wlan_dfs_phyerr_param pe; 260 261 qdf_mem_set(&pe, sizeof(pe), '\0'); 262 263 if (index_pri != dfs->dfs_curchan_radindex) 264 dfs_reset_alldelaylines(dfs); 265 266 dfs->dfs_curchan_radindex = (int16_t)index_pri; 267 268 if (rs_ext) 269 dfs->dfs_extchan_radindex = (int16_t)index_ext; 270 271 dfs_phyerr_param_copy(&pe, &rs_pri->rs_param); 272 dfs_debug(dfs, WLAN_DEBUG_DFS3, 273 "firpwr=%d, rssi=%d, height=%d, prssi=%d, inband=%d, relpwr=%d, relstep=%d, maxlen=%d", 274 pe.pe_firpwr, 275 pe.pe_rrssi, pe.pe_height, 276 pe.pe_prssi, pe.pe_inband, 277 pe.pe_relpwr, pe.pe_relstep, 278 pe.pe_maxlen); 279 280 lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk, 281 &pe, dfs->dfsdomain); 282 dfs_debug(dfs, WLAN_DEBUG_DFS, 283 "Enabled radar detection on channel %d", 284 dfs->dfs_curchan->dfs_ch_freq); 285 286 dfs->dur_multiplier = is_fastclk ? 287 DFS_FAST_CLOCK_MULTIPLIER : 288 DFS_NO_FAST_CLOCK_MULTIPLIER; 289 290 dfs_debug(dfs, WLAN_DEBUG_DFS3, 291 "duration multiplier is %d", 292 dfs->dur_multiplier); 293 } else 294 dfs_debug(dfs, WLAN_DEBUG_DFS, 295 "No more radar states left"); 296 } 297 } 298 #else 299 #ifdef CONFIG_CHAN_NUM_API 300 void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode) 301 { 302 int is_ext_ch; 303 int is_fastclk = 0; 304 struct dfs_channel *ext_ch, extchan; 305 QDF_STATUS err = QDF_STATUS_E_FAILURE; 306 307 if (!dfs) { 308 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 309 return; 310 } 311 312 is_ext_ch = WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan); 313 lmac_dfs_disable(dfs->dfs_pdev_obj, no_cac); 314 /* 315 * In all modes, if the primary is DFS then we have to 316 * enable radar detection. In HT80_80, we can have 317 * primary non-DFS 80MHz with extension 80MHz DFS. 318 */ 319 if ((WLAN_IS_CHAN_DFS(dfs->dfs_curchan) || 320 ((WLAN_IS_CHAN_11AC_VHT160(dfs->dfs_curchan) || 321 WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) 322 && 323 WLAN_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) || 324 (dfs_is_precac_timer_running(dfs))) { 325 struct dfs_state *rs_pri = NULL, *rs_ext = NULL; 326 uint8_t index_pri, index_ext; 327 328 dfs->dfs_proc_phyerr |= DFS_AR_EN; 329 dfs->dfs_proc_phyerr |= DFS_RADAR_EN; 330 dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN; 331 332 ext_ch = &extchan; 333 if (is_ext_ch) 334 err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj, 335 &(ext_ch->dfs_ch_freq), 336 &(ext_ch->dfs_ch_flags), 337 &(ext_ch->dfs_ch_flagext), 338 &(ext_ch->dfs_ch_ieee), 339 &(ext_ch->dfs_ch_vhtop_ch_freq_seg1), 340 &(ext_ch->dfs_ch_vhtop_ch_freq_seg2)); 341 342 343 dfs_reset_alldelaylines(dfs); 344 345 rs_pri = dfs_getchanstate(dfs, &index_pri, 0); 346 if (err == QDF_STATUS_SUCCESS) 347 rs_ext = dfs_getchanstate(dfs, &index_ext, 1); 348 349 if (rs_pri && ((err == QDF_STATUS_E_FAILURE) || 350 (rs_ext))) { 351 struct wlan_dfs_phyerr_param pe; 352 353 qdf_mem_set(&pe, sizeof(pe), '\0'); 354 355 if (index_pri != dfs->dfs_curchan_radindex) 356 dfs_reset_alldelaylines(dfs); 357 358 dfs->dfs_curchan_radindex = (int16_t)index_pri; 359 360 if (rs_ext) 361 dfs->dfs_extchan_radindex = (int16_t)index_ext; 362 363 dfs_phyerr_param_copy(&pe, &rs_pri->rs_param); 364 dfs_debug(dfs, WLAN_DEBUG_DFS3, 365 "firpwr=%d, rssi=%d, height=%d, prssi=%d, inband=%d, relpwr=%d, relstep=%d, maxlen=%d", 366 pe.pe_firpwr, 367 pe.pe_rrssi, pe.pe_height, 368 pe.pe_prssi, pe.pe_inband, 369 pe.pe_relpwr, pe.pe_relstep, 370 pe.pe_maxlen); 371 372 lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk, 373 &pe, dfs->dfsdomain); 374 dfs_debug(dfs, WLAN_DEBUG_DFS, 375 "Enabled radar detection on channel %d", 376 dfs->dfs_curchan->dfs_ch_freq); 377 378 dfs->dur_multiplier = is_fastclk ? 379 DFS_FAST_CLOCK_MULTIPLIER : 380 DFS_NO_FAST_CLOCK_MULTIPLIER; 381 382 dfs_debug(dfs, WLAN_DEBUG_DFS3, 383 "duration multiplier is %d", 384 dfs->dur_multiplier); 385 } else 386 dfs_debug(dfs, WLAN_DEBUG_DFS, 387 "No more radar states left"); 388 } 389 } 390 #endif 391 #endif 392 393 int dfs_set_thresholds(struct wlan_dfs *dfs, const uint32_t threshtype, 394 const uint32_t value) 395 { 396 int16_t chanindex; 397 struct dfs_state *rs; 398 struct wlan_dfs_phyerr_param pe; 399 int is_fastclk = 0; 400 401 if (!dfs) { 402 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 403 return 0; 404 } 405 406 chanindex = dfs->dfs_curchan_radindex; 407 if ((chanindex < 0) || (chanindex >= DFS_NUM_RADAR_STATES)) { 408 dfs_debug(dfs, WLAN_DEBUG_DFS1, 409 "chanindex = %d, DFS_NUM_RADAR_STATES=%d", 410 chanindex, 411 DFS_NUM_RADAR_STATES); 412 return 0; 413 } 414 415 dfs_debug(dfs, WLAN_DEBUG_DFS, 416 "threshtype=%d, value=%d", threshtype, value); 417 418 wlan_dfs_phyerr_init_noval(&pe); 419 420 rs = &(dfs->dfs_radar[chanindex]); 421 switch (threshtype) { 422 case DFS_PARAM_FIRPWR: 423 rs->rs_param.pe_firpwr = (int32_t) value; 424 pe.pe_firpwr = value; 425 break; 426 case DFS_PARAM_RRSSI: 427 rs->rs_param.pe_rrssi = value; 428 pe.pe_rrssi = value; 429 break; 430 case DFS_PARAM_HEIGHT: 431 rs->rs_param.pe_height = value; 432 pe.pe_height = value; 433 break; 434 case DFS_PARAM_PRSSI: 435 rs->rs_param.pe_prssi = value; 436 pe.pe_prssi = value; 437 break; 438 case DFS_PARAM_INBAND: 439 rs->rs_param.pe_inband = value; 440 pe.pe_inband = value; 441 break; 442 /* 5413 specific */ 443 case DFS_PARAM_RELPWR: 444 rs->rs_param.pe_relpwr = value; 445 pe.pe_relpwr = value; 446 break; 447 case DFS_PARAM_RELSTEP: 448 rs->rs_param.pe_relstep = value; 449 pe.pe_relstep = value; 450 break; 451 case DFS_PARAM_MAXLEN: 452 rs->rs_param.pe_maxlen = value; 453 pe.pe_maxlen = value; 454 break; 455 default: 456 dfs_debug(dfs, WLAN_DEBUG_DFS1, 457 "unknown threshtype (%d)", threshtype); 458 break; 459 } 460 461 462 /* 463 * The driver layer dfs_enable routine is tasked with translating 464 * values from the global format to the per-device (HAL, offload) 465 * format. 466 */ 467 lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk, 468 &pe, dfs->dfsdomain); 469 470 return 1; 471 } 472 473 int dfs_get_thresholds(struct wlan_dfs *dfs, 474 struct wlan_dfs_phyerr_param *param) 475 { 476 lmac_dfs_get_thresholds(dfs->dfs_pdev_obj, param); 477 478 return 1; 479 } 480 481 uint16_t dfs_chan2freq(struct dfs_channel *chan) 482 { 483 if (!chan) 484 return 0; 485 486 return chan == WLAN_CHAN_ANYC ? WLAN_CHAN_ANY : chan->dfs_ch_freq; 487 } 488