1 /* 2 * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. 3 * 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: This file has the DFS dispatcher API implementation which is exposed 22 * to outside of DFS component. 23 */ 24 #include <wlan_objmgr_pdev_obj.h> 25 #include "wlan_dfs_tgt_api.h" 26 #include "wlan_lmac_if_def.h" 27 #include "wlan_lmac_if_api.h" 28 #include "wlan_dfs_mlme_api.h" 29 #include "../../core/src/dfs.h" 30 #include "../../core/src/dfs_zero_cac.h" 31 #include "../../core/src/dfs_process_radar_found_ind.h" 32 #include <qdf_module.h> 33 #include "../../core/src/dfs_partial_offload_radar.h" 34 35 struct wlan_lmac_if_dfs_tx_ops * 36 wlan_psoc_get_dfs_txops(struct wlan_objmgr_psoc *psoc) 37 { 38 return &((psoc->soc_cb.tx_ops.dfs_tx_ops)); 39 } 40 41 QDF_STATUS tgt_dfs_set_current_channel(struct wlan_objmgr_pdev *pdev, 42 uint16_t dfs_ch_freq, 43 uint64_t dfs_ch_flags, 44 uint16_t dfs_ch_flagext, 45 uint8_t dfs_ch_ieee, 46 uint8_t dfs_ch_vhtop_ch_freq_seg1, 47 uint8_t dfs_ch_vhtop_ch_freq_seg2) 48 { 49 struct wlan_dfs *dfs; 50 51 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 52 if (!dfs) { 53 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 54 return QDF_STATUS_E_FAILURE; 55 } 56 57 dfs_set_current_channel(dfs, 58 dfs_ch_freq, 59 dfs_ch_flags, 60 dfs_ch_flagext, 61 dfs_ch_ieee, 62 dfs_ch_vhtop_ch_freq_seg1, 63 dfs_ch_vhtop_ch_freq_seg2); 64 65 return QDF_STATUS_SUCCESS; 66 } 67 qdf_export_symbol(tgt_dfs_set_current_channel); 68 69 QDF_STATUS tgt_dfs_radar_enable(struct wlan_objmgr_pdev *pdev, 70 int no_cac, uint32_t opmode) 71 { 72 struct wlan_dfs *dfs; 73 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 74 struct wlan_objmgr_psoc *psoc; 75 QDF_STATUS status; 76 77 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 78 if (!dfs) { 79 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 80 return QDF_STATUS_E_FAILURE; 81 } 82 83 if (!dfs->dfs_is_offload_enabled) { 84 dfs_radar_enable(dfs, no_cac, opmode); 85 return QDF_STATUS_SUCCESS; 86 } 87 88 psoc = wlan_pdev_get_psoc(pdev); 89 if (!psoc) { 90 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 91 return QDF_STATUS_E_FAILURE; 92 } 93 94 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 95 if (!dfs_tx_ops) { 96 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_tx_ops is null"); 97 return QDF_STATUS_E_FAILURE; 98 } 99 100 status = dfs_tx_ops->dfs_send_offload_enable_cmd(pdev, true); 101 if (QDF_IS_STATUS_ERROR(status)) 102 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 103 "Failed to enable dfs offload, pdev_id: %d", 104 wlan_objmgr_pdev_get_pdev_id(pdev)); 105 106 return status; 107 } 108 qdf_export_symbol(tgt_dfs_radar_enable); 109 110 void tgt_dfs_is_radar_enabled(struct wlan_objmgr_pdev *pdev, int *ignore_dfs) 111 { 112 struct wlan_dfs *dfs; 113 114 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 115 if (!dfs) { 116 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 117 return; 118 } 119 120 dfs_is_radar_enabled(dfs, ignore_dfs); 121 } 122 123 qdf_export_symbol(tgt_dfs_is_radar_enabled); 124 125 QDF_STATUS tgt_dfs_process_phyerr(struct wlan_objmgr_pdev *pdev, 126 void *buf, 127 uint16_t datalen, 128 uint8_t r_rssi, 129 uint8_t r_ext_rssi, 130 uint32_t r_rs_tstamp, 131 uint64_t r_fulltsf) 132 { 133 struct wlan_dfs *dfs; 134 135 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 136 if (!dfs) { 137 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 138 return QDF_STATUS_E_FAILURE; 139 } 140 141 if (!dfs->dfs_is_offload_enabled) 142 dfs_process_phyerr(dfs, buf, datalen, r_rssi, 143 r_ext_rssi, r_rs_tstamp, r_fulltsf); 144 else 145 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 146 "Unexpect phyerror as DFS is offloaded, pdev_id: %d", 147 wlan_objmgr_pdev_get_pdev_id(pdev)); 148 149 return QDF_STATUS_SUCCESS; 150 } 151 qdf_export_symbol(tgt_dfs_process_phyerr); 152 153 #ifdef QCA_MCL_DFS_SUPPORT 154 QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev, 155 struct radar_event_info 156 *wlan_radar_event) 157 { 158 struct wlan_dfs *dfs; 159 160 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 161 if (!dfs) { 162 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 163 return QDF_STATUS_E_FAILURE; 164 } 165 if (!dfs->dfs_is_offload_enabled) 166 dfs_process_phyerr_filter_offload(dfs, wlan_radar_event); 167 else 168 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 169 "Unexpect phyerror as DFS is offloaded, pdev_id: %d", 170 wlan_objmgr_pdev_get_pdev_id(pdev)); 171 172 return QDF_STATUS_SUCCESS; 173 } 174 qdf_export_symbol(tgt_dfs_process_phyerr_filter_offload); 175 176 QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_psoc *psoc, 177 bool *is_phyerr_filter_offload) 178 { 179 struct dfs_soc_priv_obj *soc_obj; 180 181 if (!psoc) { 182 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 183 return QDF_STATUS_E_FAILURE; 184 } 185 186 soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 187 WLAN_UMAC_COMP_DFS); 188 if (!soc_obj) { 189 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 190 "Failed to get dfs psoc component"); 191 return QDF_STATUS_E_FAILURE; 192 } 193 194 *is_phyerr_filter_offload = soc_obj->dfs_is_phyerr_filter_offload; 195 196 return QDF_STATUS_SUCCESS; 197 } 198 qdf_export_symbol(tgt_dfs_is_phyerr_filter_offload); 199 #else 200 QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev, 201 struct radar_event_info 202 *wlan_radar_event) 203 { 204 return QDF_STATUS_SUCCESS; 205 } 206 207 QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_psoc *psoc, 208 bool *is_phyerr_filter_offload) 209 { 210 return QDF_STATUS_SUCCESS; 211 } 212 #endif 213 214 QDF_STATUS tgt_dfs_is_precac_timer_running(struct wlan_objmgr_pdev *pdev, 215 bool *is_precac_timer_running) 216 { 217 struct wlan_dfs *dfs; 218 219 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 220 if (!dfs) { 221 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 222 return QDF_STATUS_E_FAILURE; 223 } 224 225 *is_precac_timer_running = dfs_is_precac_timer_running(dfs); 226 227 return QDF_STATUS_SUCCESS; 228 } 229 qdf_export_symbol(tgt_dfs_is_precac_timer_running); 230 231 QDF_STATUS tgt_dfs_get_radars(struct wlan_objmgr_pdev *pdev) 232 { 233 struct wlan_dfs *dfs; 234 235 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 236 if (!dfs) { 237 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 238 return QDF_STATUS_E_FAILURE; 239 } 240 241 if (!dfs->dfs_is_offload_enabled) 242 dfs_get_radars(dfs); 243 244 return QDF_STATUS_SUCCESS; 245 } 246 qdf_export_symbol(tgt_dfs_get_radars); 247 248 QDF_STATUS tgt_dfs_destroy_object(struct wlan_objmgr_pdev *pdev) 249 { 250 struct wlan_dfs *dfs; 251 252 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 253 if (!dfs) { 254 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 255 return QDF_STATUS_E_FAILURE; 256 } 257 258 dfs_destroy_object(dfs); 259 260 return QDF_STATUS_SUCCESS; 261 } 262 qdf_export_symbol(tgt_dfs_destroy_object); 263 264 #ifdef QCA_MCL_DFS_SUPPORT 265 QDF_STATUS tgt_dfs_set_tx_leakage_threshold(struct wlan_objmgr_pdev *pdev, 266 uint16_t tx_leakage_threshold) 267 { 268 struct wlan_dfs *dfs; 269 270 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 271 if (!dfs) { 272 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 273 return QDF_STATUS_E_FAILURE; 274 } 275 276 dfs->tx_leakage_threshold = tx_leakage_threshold; 277 278 return QDF_STATUS_SUCCESS; 279 } 280 qdf_export_symbol(tgt_dfs_set_tx_leakage_threshold); 281 #endif 282 283 QDF_STATUS tgt_dfs_control(struct wlan_objmgr_pdev *pdev, 284 u_int id, 285 void *indata, 286 uint32_t insize, 287 void *outdata, 288 uint32_t *outsize, 289 int *error) 290 { 291 struct wlan_dfs *dfs; 292 293 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 294 if (!dfs) { 295 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 296 return QDF_STATUS_E_FAILURE; 297 } 298 299 *error = dfs_control(dfs, id, indata, insize, outdata, outsize); 300 301 return QDF_STATUS_SUCCESS; 302 } 303 qdf_export_symbol(tgt_dfs_control); 304 305 QDF_STATUS tgt_dfs_find_vht80_chan_for_precac(struct wlan_objmgr_pdev *pdev, 306 uint32_t chan_mode, 307 uint8_t ch_freq_seg1, 308 uint32_t *cfreq1, 309 uint32_t *cfreq2, 310 uint32_t *phy_mode, 311 bool *dfs_set_cfreq2, 312 bool *set_agile) 313 { 314 struct wlan_dfs *dfs; 315 316 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 317 if (!dfs) { 318 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 319 return QDF_STATUS_E_FAILURE; 320 } 321 322 dfs_find_vht80_chan_for_precac(dfs, 323 chan_mode, 324 ch_freq_seg1, 325 cfreq1, 326 cfreq2, 327 phy_mode, 328 dfs_set_cfreq2, 329 set_agile); 330 331 return QDF_STATUS_SUCCESS; 332 } 333 qdf_export_symbol(tgt_dfs_find_vht80_chan_for_precac); 334 335 QDF_STATUS tgt_dfs_process_radar_ind(struct wlan_objmgr_pdev *pdev, 336 struct radar_found_info *radar_found) 337 { 338 struct wlan_dfs *dfs; 339 340 if (!pdev) { 341 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null pdev"); 342 return QDF_STATUS_E_FAILURE; 343 } 344 345 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 346 if (!dfs) { 347 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is null"); 348 return QDF_STATUS_E_FAILURE; 349 } 350 351 return dfs_process_radar_ind(dfs, radar_found); 352 } 353 qdf_export_symbol(tgt_dfs_process_radar_ind); 354 355 #ifndef QCA_MCL_DFS_SUPPORT 356 QDF_STATUS tgt_dfs_cac_complete(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id) 357 { 358 return QDF_STATUS_SUCCESS; 359 } 360 #else 361 QDF_STATUS tgt_dfs_cac_complete(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id) 362 { 363 dfs_mlme_proc_cac(pdev, vdev_id); 364 365 return QDF_STATUS_SUCCESS; 366 } 367 #endif 368 qdf_export_symbol(tgt_dfs_cac_complete); 369 370 QDF_STATUS tgt_dfs_reg_ev_handler(struct wlan_objmgr_psoc *psoc, 371 bool dfs_offload) 372 { 373 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 374 375 if (!psoc) { 376 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 377 return QDF_STATUS_E_FAILURE; 378 } 379 380 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 381 if (!dfs_tx_ops) { 382 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null dfs_tx_ops"); 383 return QDF_STATUS_E_FAILURE; 384 } 385 386 if (dfs_tx_ops->dfs_reg_ev_handler) 387 return dfs_tx_ops->dfs_reg_ev_handler(psoc, dfs_offload); 388 389 return QDF_STATUS_E_FAILURE; 390 } 391 qdf_export_symbol(tgt_dfs_reg_ev_handler); 392 393 QDF_STATUS tgt_dfs_stop(struct wlan_objmgr_pdev *pdev) 394 { 395 struct wlan_dfs *dfs; 396 397 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 398 if (!dfs) { 399 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 400 return QDF_STATUS_E_FAILURE; 401 } 402 403 dfs_stop(dfs); 404 405 return QDF_STATUS_SUCCESS; 406 } 407 qdf_export_symbol(tgt_dfs_stop); 408 409 QDF_STATUS tgt_dfs_process_emulate_bang_radar_cmd(struct wlan_objmgr_pdev *pdev, 410 struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test) 411 { 412 struct wlan_objmgr_psoc *psoc; 413 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 414 415 psoc = wlan_pdev_get_psoc(pdev); 416 if (!psoc) { 417 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 418 return QDF_STATUS_E_FAILURE; 419 } 420 421 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 422 if (dfs_tx_ops && dfs_tx_ops->dfs_process_emulate_bang_radar_cmd) 423 return dfs_tx_ops->dfs_process_emulate_bang_radar_cmd(pdev, 424 dfs_unit_test); 425 else 426 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 427 "dfs_tx_ops=%pK", dfs_tx_ops); 428 429 return QDF_STATUS_E_FAILURE; 430 } 431 qdf_export_symbol(tgt_dfs_process_emulate_bang_radar_cmd); 432 433 #ifdef QCA_MCL_DFS_SUPPORT 434 QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev) 435 { 436 struct wlan_objmgr_psoc *psoc; 437 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 438 struct dfs_soc_priv_obj *soc_obj; 439 440 psoc = wlan_pdev_get_psoc(pdev); 441 if (!psoc) { 442 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 443 return QDF_STATUS_E_FAILURE; 444 } 445 446 soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 447 WLAN_UMAC_COMP_DFS); 448 if (!soc_obj) { 449 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 450 "Failed to get dfs psoc component"); 451 return QDF_STATUS_E_FAILURE; 452 } 453 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 454 if (dfs_tx_ops && dfs_tx_ops->dfs_set_phyerr_filter_offload) 455 return dfs_tx_ops->dfs_set_phyerr_filter_offload(pdev, 456 soc_obj->dfs_is_phyerr_filter_offload); 457 else 458 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 459 "dfs_tx_ops=%pK", dfs_tx_ops); 460 461 return QDF_STATUS_E_FAILURE; 462 } 463 qdf_export_symbol(tgt_dfs_set_phyerr_filter_offload); 464 #endif 465 466 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) 467 QDF_STATUS 468 tgt_dfs_send_avg_params_to_fw(struct wlan_objmgr_pdev *pdev, 469 struct dfs_radar_found_params *params) 470 { 471 struct wlan_objmgr_psoc *psoc; 472 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 473 struct wlan_dfs *dfs; 474 QDF_STATUS status = QDF_STATUS_E_FAILURE; 475 476 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 477 if (!dfs) { 478 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 479 return status; 480 } 481 482 psoc = wlan_pdev_get_psoc(pdev); 483 if (!psoc) { 484 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 485 return status; 486 } 487 488 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 489 if (dfs_tx_ops && dfs_tx_ops->dfs_send_avg_radar_params_to_fw) 490 status = dfs_tx_ops->dfs_send_avg_radar_params_to_fw(pdev, 491 params); 492 493 if (QDF_IS_STATUS_SUCCESS(status)) { 494 dfs->dfs_average_params_sent = 1; 495 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 496 "Average radar parameters sent %d", 497 dfs->dfs_average_params_sent); 498 } 499 500 return status; 501 } 502 503 qdf_export_symbol(tgt_dfs_send_avg_params_to_fw); 504 505 QDF_STATUS tgt_dfs_action_on_status_from_fw(struct wlan_objmgr_pdev *pdev, 506 uint32_t *status) 507 { 508 struct wlan_dfs *dfs; 509 510 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 511 if (!dfs) { 512 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 513 return QDF_STATUS_E_FAILURE; 514 } 515 516 dfs_action_on_fw_radar_status_check(dfs, status); 517 518 return QDF_STATUS_SUCCESS; 519 } 520 521 qdf_export_symbol(tgt_dfs_action_on_status_from_fw); 522 523 QDF_STATUS tgt_dfs_reset_spoof_test(struct wlan_objmgr_pdev *pdev) 524 { 525 struct wlan_dfs *dfs; 526 527 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 528 if (!dfs) { 529 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 530 return QDF_STATUS_E_FAILURE; 531 } 532 533 dfs_reset_spoof_test(dfs); 534 535 return QDF_STATUS_SUCCESS; 536 } 537 538 qdf_export_symbol(tgt_dfs_reset_spoof_test); 539 #endif 540