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 static 373 void target_if_ftm_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 374 { 375 target_if_ftm_register_tx_ops(tx_ops); 376 } 377 378 static 379 QDF_STATUS target_if_register_umac_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 380 { 381 /* call regulatory callback to register tx ops */ 382 target_if_register_regulatory_tx_ops(tx_ops); 383 384 /* call umac callback to register legacy tx ops */ 385 wlan_lmac_if_umac_tx_ops_register(tx_ops); 386 387 /* Register scan tx ops */ 388 target_if_scan_tx_ops_register(tx_ops); 389 390 target_if_atf_tx_ops_register(tx_ops); 391 392 target_if_sa_api_tx_ops_register(tx_ops); 393 394 target_if_wifi_pos_tx_ops_register(tx_ops); 395 396 target_if_nan_tx_ops_register(tx_ops); 397 398 target_if_dfs_tx_ops_register(tx_ops); 399 400 target_if_son_tx_ops_register(tx_ops); 401 402 target_if_tdls_tx_ops_register(tx_ops); 403 404 target_if_fd_tx_ops_register(tx_ops); 405 406 target_if_target_tx_ops_register(tx_ops); 407 408 target_if_offchan_txrx_ops_register(tx_ops); 409 410 target_if_green_ap_tx_ops_register(tx_ops); 411 412 target_if_ftm_tx_ops_register(tx_ops); 413 414 target_if_cp_stats_tx_ops_register(tx_ops); 415 416 /* Converged UMAC components to register their TX-ops here */ 417 return QDF_STATUS_SUCCESS; 418 } 419 420 QDF_STATUS target_if_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 421 { 422 /* Converged UMAC components to register their TX-ops */ 423 target_if_register_umac_tx_ops(tx_ops); 424 425 /* Components parallel to UMAC to register their TX-ops here */ 426 target_if_sptrl_tx_ops_register(tx_ops); 427 428 /* Register direct buffer rx component tx ops here */ 429 target_if_direct_buf_rx_tx_ops_register(tx_ops); 430 431 #ifdef CONVERGED_P2P_ENABLE 432 /* Converged UMAC components to register P2P TX-ops */ 433 target_if_p2p_register_tx_ops(tx_ops); 434 #endif 435 436 return QDF_STATUS_SUCCESS; 437 } 438 qdf_export_symbol(target_if_register_tx_ops); 439 440 wmi_legacy_service_ready_callback 441 target_if_get_psoc_legacy_service_ready_cb(void) 442 { 443 wmi_legacy_service_ready_callback service_ready_cb; 444 445 qdf_spin_lock_bh(&g_target_if_ctx->lock); 446 if (g_target_if_ctx->service_ready_cb) 447 service_ready_cb = g_target_if_ctx->service_ready_cb; 448 else 449 service_ready_cb = NULL; 450 qdf_spin_unlock_bh(&g_target_if_ctx->lock); 451 452 return service_ready_cb; 453 } 454 qdf_export_symbol(target_if_get_psoc_legacy_service_ready_cb); 455 456 QDF_STATUS target_if_register_legacy_service_ready_cb( 457 wmi_legacy_service_ready_callback service_ready_cb) 458 { 459 qdf_spin_lock_bh(&g_target_if_ctx->lock); 460 g_target_if_ctx->service_ready_cb = service_ready_cb; 461 qdf_spin_unlock_bh(&g_target_if_ctx->lock); 462 463 return QDF_STATUS_SUCCESS; 464 } 465 qdf_export_symbol(target_if_register_legacy_service_ready_cb); 466 467 QDF_STATUS target_if_alloc_pdev_tgt_info(struct wlan_objmgr_pdev *pdev) 468 { 469 struct target_pdev_info *tgt_pdev_info; 470 471 if (!pdev) { 472 target_if_err("pdev is null"); 473 return QDF_STATUS_E_INVAL; 474 } 475 476 tgt_pdev_info = qdf_mem_malloc(sizeof(*tgt_pdev_info)); 477 478 if (tgt_pdev_info == NULL) { 479 target_if_err("Failed to allocate pdev target info"); 480 return QDF_STATUS_E_NOMEM; 481 } 482 483 wlan_pdev_set_tgt_if_handle(pdev, tgt_pdev_info); 484 485 return QDF_STATUS_SUCCESS; 486 } 487 488 QDF_STATUS target_if_free_pdev_tgt_info(struct wlan_objmgr_pdev *pdev) 489 { 490 struct target_pdev_info *tgt_pdev_info; 491 492 if (!pdev) { 493 target_if_err("pdev is null"); 494 return QDF_STATUS_E_INVAL; 495 } 496 497 tgt_pdev_info = wlan_pdev_get_tgt_if_handle(pdev); 498 499 wlan_pdev_set_tgt_if_handle(pdev, NULL); 500 501 qdf_mem_free(tgt_pdev_info); 502 503 return QDF_STATUS_SUCCESS; 504 } 505 506 QDF_STATUS target_if_alloc_psoc_tgt_info(struct wlan_objmgr_psoc *psoc) 507 { 508 struct target_psoc_info *tgt_psoc_info; 509 510 if (!psoc) { 511 target_if_err("psoc is null"); 512 return QDF_STATUS_E_INVAL; 513 } 514 515 tgt_psoc_info = qdf_mem_malloc(sizeof(*tgt_psoc_info)); 516 517 if (tgt_psoc_info == NULL) { 518 target_if_err("Failed to allocate psoc target info"); 519 return QDF_STATUS_E_NOMEM; 520 } 521 522 wlan_psoc_set_tgt_if_handle(psoc, tgt_psoc_info); 523 target_psoc_set_preferred_hw_mode(tgt_psoc_info, WMI_HOST_HW_MODE_MAX); 524 525 qdf_init_waitqueue_head(&tgt_psoc_info->info.event_queue); 526 527 return QDF_STATUS_SUCCESS; 528 } 529 530 QDF_STATUS target_if_free_psoc_tgt_info(struct wlan_objmgr_psoc *psoc) 531 { 532 struct target_psoc_info *tgt_psoc_info; 533 struct wlan_psoc_host_service_ext_param *ext_param; 534 535 if (!psoc) { 536 target_if_err("psoc is null"); 537 return QDF_STATUS_E_INVAL; 538 } 539 540 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 541 542 ext_param = target_psoc_get_service_ext_param(tgt_psoc_info); 543 if (!ext_param) { 544 target_if_err("tgt_psoc_info is NULL"); 545 return QDF_STATUS_E_INVAL; 546 } 547 init_deinit_chainmask_table_free(ext_param); 548 init_deinit_dbr_ring_cap_free(tgt_psoc_info); 549 550 wlan_psoc_set_tgt_if_handle(psoc, NULL); 551 552 qdf_mem_free(tgt_psoc_info); 553 554 return QDF_STATUS_SUCCESS; 555 } 556 557 bool target_is_tgt_type_ar900b(uint32_t target_type) 558 { 559 return target_type == TARGET_TYPE_AR900B; 560 } 561 562 bool target_is_tgt_type_ipq4019(uint32_t target_type) 563 { 564 return target_type == TARGET_TYPE_IPQ4019; 565 } 566 567 bool target_is_tgt_type_qca9984(uint32_t target_type) 568 { 569 return target_type == TARGET_TYPE_QCA9984; 570 } 571 572 bool target_is_tgt_type_qca9888(uint32_t target_type) 573 { 574 return target_type == TARGET_TYPE_QCA9888; 575 } 576