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 { 372 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 373 374 if (!psoc) { 375 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 376 return QDF_STATUS_E_FAILURE; 377 } 378 379 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 380 if (!dfs_tx_ops) { 381 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null dfs_tx_ops"); 382 return QDF_STATUS_E_FAILURE; 383 } 384 385 if (dfs_tx_ops->dfs_reg_ev_handler) 386 return dfs_tx_ops->dfs_reg_ev_handler(psoc); 387 388 return QDF_STATUS_E_FAILURE; 389 } 390 qdf_export_symbol(tgt_dfs_reg_ev_handler); 391 392 QDF_STATUS tgt_dfs_stop(struct wlan_objmgr_pdev *pdev) 393 { 394 struct wlan_dfs *dfs; 395 396 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 397 if (!dfs) { 398 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 399 return QDF_STATUS_E_FAILURE; 400 } 401 402 dfs_stop(dfs); 403 404 return QDF_STATUS_SUCCESS; 405 } 406 qdf_export_symbol(tgt_dfs_stop); 407 408 QDF_STATUS tgt_dfs_process_emulate_bang_radar_cmd(struct wlan_objmgr_pdev *pdev, 409 struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test) 410 { 411 struct wlan_objmgr_psoc *psoc; 412 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 413 414 psoc = wlan_pdev_get_psoc(pdev); 415 if (!psoc) { 416 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 417 return QDF_STATUS_E_FAILURE; 418 } 419 420 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 421 if (dfs_tx_ops && dfs_tx_ops->dfs_process_emulate_bang_radar_cmd) 422 return dfs_tx_ops->dfs_process_emulate_bang_radar_cmd(pdev, 423 dfs_unit_test); 424 else 425 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 426 "dfs_tx_ops=%pK", dfs_tx_ops); 427 428 return QDF_STATUS_E_FAILURE; 429 } 430 qdf_export_symbol(tgt_dfs_process_emulate_bang_radar_cmd); 431 432 #ifdef QCA_MCL_DFS_SUPPORT 433 QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev) 434 { 435 struct wlan_objmgr_psoc *psoc; 436 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 437 struct dfs_soc_priv_obj *soc_obj; 438 439 psoc = wlan_pdev_get_psoc(pdev); 440 if (!psoc) { 441 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 442 return QDF_STATUS_E_FAILURE; 443 } 444 445 soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 446 WLAN_UMAC_COMP_DFS); 447 if (!soc_obj) { 448 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 449 "Failed to get dfs psoc component"); 450 return QDF_STATUS_E_FAILURE; 451 } 452 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 453 if (dfs_tx_ops && dfs_tx_ops->dfs_set_phyerr_filter_offload) 454 return dfs_tx_ops->dfs_set_phyerr_filter_offload(pdev, 455 soc_obj->dfs_is_phyerr_filter_offload); 456 else 457 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 458 "dfs_tx_ops=%pK", dfs_tx_ops); 459 460 return QDF_STATUS_E_FAILURE; 461 } 462 qdf_export_symbol(tgt_dfs_set_phyerr_filter_offload); 463 #endif 464 465 #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) 466 QDF_STATUS 467 tgt_dfs_send_avg_params_to_fw(struct wlan_objmgr_pdev *pdev, 468 struct dfs_radar_found_params *params) 469 { 470 struct wlan_objmgr_psoc *psoc; 471 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 472 struct wlan_dfs *dfs; 473 QDF_STATUS status = QDF_STATUS_E_FAILURE; 474 475 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 476 if (!dfs) { 477 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 478 return status; 479 } 480 481 psoc = wlan_pdev_get_psoc(pdev); 482 if (!psoc) { 483 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 484 return status; 485 } 486 487 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 488 if (dfs_tx_ops && dfs_tx_ops->dfs_send_avg_radar_params_to_fw) 489 status = dfs_tx_ops->dfs_send_avg_radar_params_to_fw(pdev, 490 params); 491 492 if (QDF_IS_STATUS_SUCCESS(status)) { 493 dfs->dfs_average_params_sent = 1; 494 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 495 "Average radar parameters sent %d", 496 dfs->dfs_average_params_sent); 497 } 498 499 return status; 500 } 501 502 qdf_export_symbol(tgt_dfs_send_avg_params_to_fw); 503 504 QDF_STATUS tgt_dfs_action_on_status_from_fw(struct wlan_objmgr_pdev *pdev, 505 uint32_t *status) 506 { 507 struct wlan_dfs *dfs; 508 509 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 510 if (!dfs) { 511 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 512 return QDF_STATUS_E_FAILURE; 513 } 514 515 dfs_action_on_fw_radar_status_check(dfs, status); 516 517 return QDF_STATUS_SUCCESS; 518 } 519 520 qdf_export_symbol(tgt_dfs_action_on_status_from_fw); 521 522 QDF_STATUS tgt_dfs_reset_spoof_test(struct wlan_objmgr_pdev *pdev) 523 { 524 struct wlan_dfs *dfs; 525 526 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 527 if (!dfs) { 528 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 529 return QDF_STATUS_E_FAILURE; 530 } 531 532 dfs_reset_spoof_test(dfs); 533 534 return QDF_STATUS_SUCCESS; 535 } 536 537 qdf_export_symbol(tgt_dfs_reset_spoof_test); 538 #endif 539