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 interacting with target interface. 21 * 22 */ 23 24 #include "target_if.h" 25 #include "target_type.h" 26 #ifdef WLAN_ATF_ENABLE 27 #include "target_if_atf.h" 28 #endif 29 #ifdef WLAN_SA_API_ENABLE 30 #include "target_if_sa_api.h" 31 #endif 32 #ifdef WLAN_CONV_SPECTRAL_ENABLE 33 #include "target_if_spectral.h" 34 #endif 35 #include <target_if_reg.h> 36 #include <target_if_scan.h> 37 #include <target_if_ftm.h> 38 #ifdef DFS_COMPONENT_ENABLE 39 #include <target_if_dfs.h> 40 #endif 41 42 #ifdef CONVERGED_P2P_ENABLE 43 #include "target_if_p2p.h" 44 #endif 45 46 #ifdef WIFI_POS_CONVERGED 47 #include "target_if_wifi_pos.h" 48 #endif 49 50 #ifdef WLAN_FEATURE_NAN_CONVERGENCE 51 #include "target_if_nan.h" 52 #endif /* WLAN_FEATURE_NAN_CONVERGENCE */ 53 #ifdef CONVERGED_TDLS_ENABLE 54 #include "target_if_tdls.h" 55 #endif 56 #ifdef QCA_SUPPORT_SON 57 #include <target_if_son.h> 58 #endif 59 #ifdef WLAN_OFFCHAN_TXRX_ENABLE 60 #include <target_if_offchan_txrx_api.h> 61 #endif 62 #ifdef WLAN_SUPPORT_GREEN_AP 63 #include <target_if_green_ap.h> 64 #endif 65 #include <init_deinit_lmac.h> 66 #include <service_ready_util.h> 67 68 #ifdef DIRECT_BUF_RX_ENABLE 69 #include <target_if_direct_buf_rx_api.h> 70 #endif 71 72 #ifdef WLAN_SUPPORT_FILS 73 #include <target_if_fd.h> 74 #endif 75 #include "qdf_module.h" 76 77 #include <target_if_cp_stats.h> 78 79 static struct target_if_ctx *g_target_if_ctx; 80 81 struct target_if_ctx *target_if_get_ctx() 82 { 83 return g_target_if_ctx; 84 } 85 86 struct wlan_objmgr_psoc *target_if_get_psoc_from_scn_hdl(void *scn_handle) 87 { 88 struct wlan_objmgr_psoc *psoc; 89 90 qdf_spin_lock_bh(&g_target_if_ctx->lock); 91 if (scn_handle && g_target_if_ctx->get_psoc_hdl_cb) 92 psoc = g_target_if_ctx->get_psoc_hdl_cb(scn_handle); 93 else 94 psoc = NULL; 95 qdf_spin_unlock_bh(&g_target_if_ctx->lock); 96 97 return psoc; 98 } 99 100 struct wlan_objmgr_pdev *target_if_get_pdev_from_scn_hdl(void *scn_handle) 101 { 102 struct wlan_objmgr_pdev *pdev; 103 104 qdf_spin_lock_bh(&g_target_if_ctx->lock); 105 if (scn_handle && g_target_if_ctx->get_pdev_hdl_cb) 106 pdev = g_target_if_ctx->get_pdev_hdl_cb(scn_handle); 107 else 108 pdev = NULL; 109 qdf_spin_unlock_bh(&g_target_if_ctx->lock); 110 111 return pdev; 112 } 113 114 #ifdef DIRECT_BUF_RX_ENABLE 115 static QDF_STATUS target_if_direct_buf_rx_init(void) 116 { 117 return direct_buf_rx_init(); 118 } 119 120 static QDF_STATUS target_if_direct_buf_rx_deinit(void) 121 { 122 return direct_buf_rx_deinit(); 123 } 124 #else 125 static QDF_STATUS target_if_direct_buf_rx_init(void) 126 { 127 return QDF_STATUS_SUCCESS; 128 } 129 130 static QDF_STATUS target_if_direct_buf_rx_deinit(void) 131 { 132 return QDF_STATUS_SUCCESS; 133 } 134 #endif /* DIRECT_BUF_RX_ENABLE */ 135 136 QDF_STATUS target_if_open(get_psoc_handle_callback psoc_hdl_cb) 137 { 138 g_target_if_ctx = qdf_mem_malloc(sizeof(*g_target_if_ctx)); 139 if (!g_target_if_ctx) { 140 target_if_err("Cannot allocate target if ctx"); 141 QDF_ASSERT(0); 142 return QDF_STATUS_E_NOMEM; 143 } 144 145 qdf_spinlock_create(&g_target_if_ctx->lock); 146 147 qdf_spin_lock_bh(&g_target_if_ctx->lock); 148 g_target_if_ctx->magic = TGT_MAGIC; 149 g_target_if_ctx->get_psoc_hdl_cb = psoc_hdl_cb; 150 qdf_spin_unlock_bh(&g_target_if_ctx->lock); 151 152 target_if_direct_buf_rx_init(); 153 154 return QDF_STATUS_SUCCESS; 155 } 156 157 QDF_STATUS target_if_close(void) 158 { 159 if (!g_target_if_ctx) { 160 QDF_ASSERT(0); 161 target_if_err("target if ctx is null"); 162 return QDF_STATUS_E_INVAL; 163 } 164 165 qdf_spin_lock_bh(&g_target_if_ctx->lock); 166 g_target_if_ctx->magic = 0; 167 g_target_if_ctx->get_psoc_hdl_cb = NULL; 168 g_target_if_ctx->get_pdev_hdl_cb = NULL; 169 g_target_if_ctx->service_ready_cb = NULL; 170 qdf_spin_unlock_bh(&g_target_if_ctx->lock); 171 172 qdf_spinlock_destroy(&g_target_if_ctx->lock); 173 qdf_mem_free(g_target_if_ctx); 174 g_target_if_ctx = NULL; 175 176 target_if_direct_buf_rx_deinit(); 177 178 return QDF_STATUS_SUCCESS; 179 } 180 qdf_export_symbol(target_if_close); 181 182 QDF_STATUS target_if_store_pdev_target_if_ctx( 183 get_pdev_handle_callback pdev_hdl_cb) 184 { 185 if (!g_target_if_ctx) { 186 QDF_ASSERT(0); 187 target_if_err("target if ctx is null"); 188 return QDF_STATUS_E_INVAL; 189 } 190 191 qdf_spin_lock_bh(&g_target_if_ctx->lock); 192 g_target_if_ctx->get_pdev_hdl_cb = pdev_hdl_cb; 193 qdf_spin_unlock_bh(&g_target_if_ctx->lock); 194 195 return QDF_STATUS_SUCCESS; 196 } 197 198 #ifndef WLAN_OFFCHAN_TXRX_ENABLE 199 static void target_if_offchan_txrx_ops_register( 200 struct wlan_lmac_if_tx_ops *tx_ops) 201 { 202 } 203 #endif /* WLAN_OFFCHAN_TXRX_ENABLE */ 204 205 #ifndef WLAN_ATF_ENABLE 206 static void target_if_atf_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 207 { 208 } 209 #endif /* WLAN_ATF_ENABLE */ 210 211 #ifndef WLAN_SA_API_ENABLE 212 static void target_if_sa_api_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 213 { 214 } 215 #endif /* WLAN_SA_API_ENABLE */ 216 217 #ifdef WLAN_SUPPORT_FILS 218 static void target_if_fd_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 219 { 220 target_if_fd_register_tx_ops(tx_ops); 221 } 222 #else 223 static void target_if_fd_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 224 { 225 } 226 #endif 227 228 #ifdef WIFI_POS_CONVERGED 229 static void target_if_wifi_pos_tx_ops_register( 230 struct wlan_lmac_if_tx_ops *tx_ops) 231 { 232 target_if_wifi_pos_register_tx_ops(tx_ops); 233 } 234 #else 235 static void target_if_wifi_pos_tx_ops_register( 236 struct wlan_lmac_if_tx_ops *tx_ops) 237 { 238 } 239 #endif 240 #ifdef QCA_SUPPORT_SON 241 static void target_if_son_tx_ops_register( 242 struct wlan_lmac_if_tx_ops *tx_ops) 243 { 244 target_if_son_register_tx_ops(tx_ops); 245 return; 246 } 247 #else 248 static void target_if_son_tx_ops_register( 249 struct wlan_lmac_if_tx_ops *tx_ops) 250 { 251 return; 252 } 253 #endif 254 255 #ifdef WLAN_FEATURE_NAN_CONVERGENCE 256 static void target_if_nan_tx_ops_register( 257 struct wlan_lmac_if_tx_ops *tx_ops) 258 { 259 target_if_nan_register_tx_ops(tx_ops); 260 } 261 #else 262 static void target_if_nan_tx_ops_register( 263 struct wlan_lmac_if_tx_ops *tx_ops) 264 { 265 } 266 #endif /* WLAN_FEATURE_NAN_CONVERGENCE */ 267 268 #ifdef CONVERGED_TDLS_ENABLE 269 static void target_if_tdls_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 270 { 271 target_if_tdls_register_tx_ops(tx_ops); 272 } 273 #else 274 static void target_if_tdls_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 275 { 276 } 277 #endif /* CONVERGED_TDLS_ENABLE */ 278 279 #ifdef DFS_COMPONENT_ENABLE 280 static void target_if_dfs_tx_ops_register( 281 struct wlan_lmac_if_tx_ops *tx_ops) 282 { 283 target_if_register_dfs_tx_ops(tx_ops); 284 } 285 #else 286 static void target_if_dfs_tx_ops_register( 287 struct wlan_lmac_if_tx_ops *tx_ops) 288 { 289 } 290 #endif /* DFS_COMPONENT_ENABLE */ 291 292 #ifdef WLAN_CONV_SPECTRAL_ENABLE 293 static void target_if_sptrl_tx_ops_register( 294 struct wlan_lmac_if_tx_ops *tx_ops) 295 { 296 target_if_sptrl_register_tx_ops(tx_ops); 297 } 298 #else 299 static void target_if_sptrl_tx_ops_register( 300 struct wlan_lmac_if_tx_ops *tx_ops) 301 { 302 } 303 #endif /* WLAN_CONV_SPECTRAL_ENABLE */ 304 305 #ifdef DIRECT_BUF_RX_ENABLE 306 static void target_if_direct_buf_rx_tx_ops_register( 307 struct wlan_lmac_if_tx_ops *tx_ops) 308 { 309 target_if_direct_buf_rx_register_tx_ops(tx_ops); 310 } 311 #else 312 static void target_if_direct_buf_rx_tx_ops_register( 313 struct wlan_lmac_if_tx_ops *tx_ops) 314 { 315 } 316 #endif /* DIRECT_BUF_RX_ENABLE */ 317 318 #ifdef WLAN_SUPPORT_GREEN_AP 319 static QDF_STATUS target_if_green_ap_tx_ops_register( 320 struct wlan_lmac_if_tx_ops *tx_ops) 321 { 322 return target_if_register_green_ap_tx_ops(tx_ops); 323 } 324 #else 325 static QDF_STATUS target_if_green_ap_tx_ops_register( 326 struct wlan_lmac_if_tx_ops *tx_ops) 327 { 328 return QDF_STATUS_SUCCESS; 329 } 330 #endif /* WLAN_SUPPORT_GREEN_AP */ 331 332 static void target_if_target_tx_ops_register( 333 struct wlan_lmac_if_tx_ops *tx_ops) 334 { 335 struct wlan_lmac_if_target_tx_ops *target_tx_ops; 336 337 if (!tx_ops) { 338 target_if_err("invalid tx_ops"); 339 return; 340 } 341 342 target_tx_ops = &tx_ops->target_tx_ops; 343 344 target_tx_ops->tgt_is_tgt_type_ar900b = 345 target_is_tgt_type_ar900b; 346 347 target_tx_ops->tgt_is_tgt_type_ipq4019 = 348 target_is_tgt_type_ipq4019; 349 350 target_tx_ops->tgt_is_tgt_type_qca9984 = 351 target_is_tgt_type_qca9984; 352 353 target_tx_ops->tgt_is_tgt_type_qca9888 = 354 target_is_tgt_type_qca9888; 355 356 target_tx_ops->tgt_get_tgt_type = 357 lmac_get_tgt_type; 358 359 target_tx_ops->tgt_get_tgt_version = 360 lmac_get_tgt_version; 361 362 target_tx_ops->tgt_get_tgt_revision = 363 lmac_get_tgt_revision; 364 } 365 366 static QDF_STATUS 367 target_if_cp_stats_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 368 { 369 return target_if_cp_stats_register_tx_ops(tx_ops); 370 } 371 372 #ifdef QCA_WIFI_FTM 373 static 374 void target_if_ftm_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 375 { 376 target_if_ftm_register_tx_ops(tx_ops); 377 } 378 #else 379 static 380 void target_if_ftm_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 381 { 382 } 383 #endif 384 static 385 QDF_STATUS target_if_register_umac_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 386 { 387 /* call regulatory callback to register tx ops */ 388 target_if_register_regulatory_tx_ops(tx_ops); 389 390 /* call umac callback to register legacy tx ops */ 391 wlan_lmac_if_umac_tx_ops_register(tx_ops); 392 393 /* Register scan tx ops */ 394 target_if_scan_tx_ops_register(tx_ops); 395 396 target_if_atf_tx_ops_register(tx_ops); 397 398 target_if_sa_api_tx_ops_register(tx_ops); 399 400 target_if_wifi_pos_tx_ops_register(tx_ops); 401 402 target_if_nan_tx_ops_register(tx_ops); 403 404 target_if_dfs_tx_ops_register(tx_ops); 405 406 target_if_son_tx_ops_register(tx_ops); 407 408 target_if_tdls_tx_ops_register(tx_ops); 409 410 target_if_fd_tx_ops_register(tx_ops); 411 412 target_if_target_tx_ops_register(tx_ops); 413 414 target_if_offchan_txrx_ops_register(tx_ops); 415 416 target_if_green_ap_tx_ops_register(tx_ops); 417 418 target_if_ftm_tx_ops_register(tx_ops); 419 420 target_if_cp_stats_tx_ops_register(tx_ops); 421 422 /* Converged UMAC components to register their TX-ops here */ 423 return QDF_STATUS_SUCCESS; 424 } 425 426 QDF_STATUS target_if_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 427 { 428 /* Converged UMAC components to register their TX-ops */ 429 target_if_register_umac_tx_ops(tx_ops); 430 431 /* Components parallel to UMAC to register their TX-ops here */ 432 target_if_sptrl_tx_ops_register(tx_ops); 433 434 /* Register direct buffer rx component tx ops here */ 435 target_if_direct_buf_rx_tx_ops_register(tx_ops); 436 437 #ifdef CONVERGED_P2P_ENABLE 438 /* Converged UMAC components to register P2P TX-ops */ 439 target_if_p2p_register_tx_ops(tx_ops); 440 #endif 441 442 return QDF_STATUS_SUCCESS; 443 } 444 qdf_export_symbol(target_if_register_tx_ops); 445 446 wmi_legacy_service_ready_callback 447 target_if_get_psoc_legacy_service_ready_cb(void) 448 { 449 wmi_legacy_service_ready_callback service_ready_cb; 450 451 qdf_spin_lock_bh(&g_target_if_ctx->lock); 452 if (g_target_if_ctx->service_ready_cb) 453 service_ready_cb = g_target_if_ctx->service_ready_cb; 454 else 455 service_ready_cb = NULL; 456 qdf_spin_unlock_bh(&g_target_if_ctx->lock); 457 458 return service_ready_cb; 459 } 460 qdf_export_symbol(target_if_get_psoc_legacy_service_ready_cb); 461 462 QDF_STATUS target_if_register_legacy_service_ready_cb( 463 wmi_legacy_service_ready_callback service_ready_cb) 464 { 465 qdf_spin_lock_bh(&g_target_if_ctx->lock); 466 g_target_if_ctx->service_ready_cb = service_ready_cb; 467 qdf_spin_unlock_bh(&g_target_if_ctx->lock); 468 469 return QDF_STATUS_SUCCESS; 470 } 471 qdf_export_symbol(target_if_register_legacy_service_ready_cb); 472 473 QDF_STATUS target_if_alloc_pdev_tgt_info(struct wlan_objmgr_pdev *pdev) 474 { 475 struct target_pdev_info *tgt_pdev_info; 476 477 if (!pdev) { 478 target_if_err("pdev is null"); 479 return QDF_STATUS_E_INVAL; 480 } 481 482 tgt_pdev_info = qdf_mem_malloc(sizeof(*tgt_pdev_info)); 483 484 if (tgt_pdev_info == NULL) { 485 target_if_err("Failed to allocate pdev target info"); 486 return QDF_STATUS_E_NOMEM; 487 } 488 489 wlan_pdev_set_tgt_if_handle(pdev, tgt_pdev_info); 490 491 return QDF_STATUS_SUCCESS; 492 } 493 494 QDF_STATUS target_if_free_pdev_tgt_info(struct wlan_objmgr_pdev *pdev) 495 { 496 struct target_pdev_info *tgt_pdev_info; 497 498 if (!pdev) { 499 target_if_err("pdev is null"); 500 return QDF_STATUS_E_INVAL; 501 } 502 503 tgt_pdev_info = wlan_pdev_get_tgt_if_handle(pdev); 504 505 wlan_pdev_set_tgt_if_handle(pdev, NULL); 506 507 qdf_mem_free(tgt_pdev_info); 508 509 return QDF_STATUS_SUCCESS; 510 } 511 512 QDF_STATUS target_if_alloc_psoc_tgt_info(struct wlan_objmgr_psoc *psoc) 513 { 514 struct target_psoc_info *tgt_psoc_info; 515 516 if (!psoc) { 517 target_if_err("psoc is null"); 518 return QDF_STATUS_E_INVAL; 519 } 520 521 tgt_psoc_info = qdf_mem_malloc(sizeof(*tgt_psoc_info)); 522 523 if (tgt_psoc_info == NULL) { 524 target_if_err("Failed to allocate psoc target info"); 525 return QDF_STATUS_E_NOMEM; 526 } 527 528 wlan_psoc_set_tgt_if_handle(psoc, tgt_psoc_info); 529 target_psoc_set_preferred_hw_mode(tgt_psoc_info, WMI_HOST_HW_MODE_MAX); 530 531 qdf_event_create(&tgt_psoc_info->info.event); 532 533 return QDF_STATUS_SUCCESS; 534 } 535 536 QDF_STATUS target_if_free_psoc_tgt_info(struct wlan_objmgr_psoc *psoc) 537 { 538 struct target_psoc_info *tgt_psoc_info; 539 struct wlan_psoc_host_service_ext_param *ext_param; 540 541 if (!psoc) { 542 target_if_err("psoc is null"); 543 return QDF_STATUS_E_INVAL; 544 } 545 546 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 547 548 ext_param = target_psoc_get_service_ext_param(tgt_psoc_info); 549 if (!ext_param) { 550 target_if_err("tgt_psoc_info is NULL"); 551 return QDF_STATUS_E_INVAL; 552 } 553 init_deinit_chainmask_table_free(ext_param); 554 init_deinit_dbr_ring_cap_free(tgt_psoc_info); 555 556 qdf_event_destroy(&tgt_psoc_info->info.event); 557 558 wlan_psoc_set_tgt_if_handle(psoc, NULL); 559 560 qdf_mem_free(tgt_psoc_info); 561 562 return QDF_STATUS_SUCCESS; 563 } 564 565 bool target_is_tgt_type_ar900b(uint32_t target_type) 566 { 567 return target_type == TARGET_TYPE_AR900B; 568 } 569 570 bool target_is_tgt_type_ipq4019(uint32_t target_type) 571 { 572 return target_type == TARGET_TYPE_IPQ4019; 573 } 574 575 bool target_is_tgt_type_qca9984(uint32_t target_type) 576 { 577 return target_type == TARGET_TYPE_QCA9984; 578 } 579 580 bool target_is_tgt_type_qca9888(uint32_t target_type) 581 { 582 return target_type == TARGET_TYPE_QCA9888; 583 } 584