1 /* 2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 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 #include "htc_debug.h" 21 #include "htc_internal.h" 22 #include "htc_credit_history.h" 23 #include "htc_hang_event.h" 24 #include <hif.h> 25 #include <qdf_nbuf.h> /* qdf_nbuf_t */ 26 #include <qdf_types.h> /* qdf_print */ 27 28 #define MAX_HTC_RX_BUNDLE 2 29 30 #if defined(WLAN_DEBUG) || defined(DEBUG) 31 static ATH_DEBUG_MASK_DESCRIPTION g_htc_debug_description[] = { 32 {ATH_DEBUG_SEND, "Send"}, 33 {ATH_DEBUG_RECV, "Recv"}, 34 {ATH_DEBUG_SYNC, "Sync"}, 35 {ATH_DEBUG_DUMP, "Dump Data (RX or TX)"}, 36 {ATH_DEBUG_SETUP, "Setup"}, 37 }; 38 39 ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc, 40 "htc", 41 "Host Target Communications", 42 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO | 43 ATH_DEBUG_SETUP, 44 ATH_DEBUG_DESCRIPTION_COUNT 45 (g_htc_debug_description), 46 g_htc_debug_description); 47 48 #endif 49 50 #if defined(WMI_MULTI_MAC_SVC) 51 static const uint32_t svc_id[] = {WMI_CONTROL_SVC, WMI_CONTROL_SVC_WMAC1, 52 WMI_CONTROL_SVC_WMAC2}; 53 #else 54 static const uint32_t svc_id[] = {WMI_CONTROL_SVC}; 55 #endif 56 57 extern unsigned int htc_credit_flow; 58 59 static void reset_endpoint_states(HTC_TARGET *target); 60 destroy_htc_tx_ctrl_packet(HTC_PACKET * pPacket)61 static void destroy_htc_tx_ctrl_packet(HTC_PACKET *pPacket) 62 { 63 qdf_nbuf_t netbuf; 64 65 netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 66 if (netbuf) 67 qdf_nbuf_free(netbuf); 68 qdf_mem_free(pPacket); 69 } 70 build_htc_tx_ctrl_packet(qdf_device_t osdev)71 static HTC_PACKET *build_htc_tx_ctrl_packet(qdf_device_t osdev) 72 { 73 HTC_PACKET *pPacket = NULL; 74 qdf_nbuf_t netbuf; 75 76 do { 77 pPacket = (HTC_PACKET *) qdf_mem_malloc(sizeof(HTC_PACKET)); 78 if (!pPacket) 79 break; 80 netbuf = qdf_nbuf_alloc(osdev, HTC_CONTROL_BUFFER_SIZE, 81 20, 4, true); 82 if (!netbuf) { 83 qdf_mem_free(pPacket); 84 pPacket = NULL; 85 break; 86 } 87 SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf); 88 } while (false); 89 90 return pPacket; 91 } 92 htc_free_control_tx_packet(HTC_TARGET * target,HTC_PACKET * pPacket)93 void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket) 94 { 95 96 #ifdef TODO_FIXME 97 LOCK_HTC(target); 98 HTC_PACKET_ENQUEUE(&target->ControlBufferTXFreeList, pPacket); 99 UNLOCK_HTC(target); 100 /* TODO_FIXME netbufs cannot be RESET! */ 101 #else 102 destroy_htc_tx_ctrl_packet(pPacket); 103 #endif 104 105 } 106 htc_alloc_control_tx_packet(HTC_TARGET * target)107 HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target) 108 { 109 #ifdef TODO_FIXME 110 HTC_PACKET *pPacket; 111 112 LOCK_HTC(target); 113 pPacket = htc_packet_dequeue(&target->ControlBufferTXFreeList); 114 UNLOCK_HTC(target); 115 116 return pPacket; 117 #else 118 return build_htc_tx_ctrl_packet(target->osdev); 119 #endif 120 } 121 122 /* Set the target failure handling callback */ htc_set_target_failure_callback(HTC_HANDLE HTCHandle,HTC_TARGET_FAILURE Callback)123 void htc_set_target_failure_callback(HTC_HANDLE HTCHandle, 124 HTC_TARGET_FAILURE Callback) 125 { 126 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 127 128 target->HTCInitInfo.TargetFailure = Callback; 129 } 130 htc_dump(HTC_HANDLE HTCHandle,uint8_t CmdId,bool start)131 void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start) 132 { 133 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 134 135 hif_dump(target->hif_dev, CmdId, start); 136 } 137 htc_ce_tasklet_debug_dump(HTC_HANDLE htc_handle)138 void htc_ce_tasklet_debug_dump(HTC_HANDLE htc_handle) 139 { 140 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); 141 142 if (!target->hif_dev) 143 return; 144 145 hif_display_stats(target->hif_dev); 146 } 147 148 #ifdef FEATURE_RUNTIME_PM 149 /** 150 * htc_dec_return_wmi_runtime_cnt: Decrement htc wmi runtime count 151 * @target: HTC target 152 * 153 * Return: value of runtime count after decrement 154 */ 155 static inline htc_dec_return_wmi_runtime_cnt(HTC_TARGET * target)156 int32_t htc_dec_return_wmi_runtime_cnt(HTC_TARGET *target) 157 { 158 return qdf_atomic_dec_return(&target->htc_wmi_runtime_cnt); 159 } 160 161 /** 162 * htc_init_wmi_runtime_cnt: Initialize htc wmi runtime count 163 * @target: HTC target 164 * 165 * Return: None 166 */ 167 static inline htc_init_wmi_runtime_cnt(HTC_TARGET * target)168 void htc_init_wmi_runtime_cnt(HTC_TARGET *target) 169 { 170 qdf_atomic_init(&target->htc_wmi_runtime_cnt); 171 } 172 #else 173 static inline htc_dec_return_wmi_runtime_cnt(HTC_TARGET * target)174 int32_t htc_dec_return_wmi_runtime_cnt(HTC_TARGET *target) 175 { 176 return -1; 177 } 178 179 static inline htc_init_wmi_runtime_cnt(HTC_TARGET * target)180 void htc_init_wmi_runtime_cnt(HTC_TARGET *target) 181 { 182 } 183 #endif 184 /* cleanup the HTC instance */ htc_cleanup(HTC_TARGET * target)185 static void htc_cleanup(HTC_TARGET *target) 186 { 187 HTC_PACKET *pPacket; 188 int i; 189 HTC_ENDPOINT *endpoint; 190 HTC_PACKET_QUEUE *pkt_queue; 191 qdf_nbuf_t netbuf; 192 193 while (htc_dec_return_htt_runtime_cnt((void *)target) >= 0) 194 hif_rtpm_put(HIF_RTPM_PUT_ASYNC, HIF_RTPM_ID_HTT); 195 196 while (htc_dec_return_wmi_runtime_cnt((void *)target) >= 0) 197 hif_rtpm_put(HIF_RTPM_PUT_ASYNC, HIF_RTPM_ID_WMI); 198 199 if (target->hif_dev) { 200 hif_detach_htc(target->hif_dev); 201 hif_mask_interrupt_call(target->hif_dev); 202 target->hif_dev = NULL; 203 } 204 205 while (true) { 206 pPacket = allocate_htc_packet_container(target); 207 if (!pPacket) 208 break; 209 qdf_mem_free(pPacket); 210 } 211 212 LOCK_HTC_TX(target); 213 pPacket = target->pBundleFreeList; 214 target->pBundleFreeList = NULL; 215 UNLOCK_HTC_TX(target); 216 while (pPacket) { 217 HTC_PACKET *pPacketTmp = (HTC_PACKET *) pPacket->ListLink.pNext; 218 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 219 if (netbuf) 220 qdf_nbuf_free(netbuf); 221 pkt_queue = pPacket->pContext; 222 if (pkt_queue) 223 qdf_mem_free(pkt_queue); 224 qdf_mem_free(pPacket); 225 pPacket = pPacketTmp; 226 } 227 228 #ifdef TODO_FIXME 229 while (true) { 230 pPacket = htc_alloc_control_tx_packet(target); 231 if (!pPacket) 232 break; 233 netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 234 if (netbuf) 235 qdf_nbuf_free(netbuf); 236 qdf_mem_free(pPacket); 237 } 238 #endif 239 HTC_INFO("%s: Non flow ctrl enabled endpoints nbuf map: %d, unamp: %d", 240 __func__, target->nbuf_nfc_map_count, 241 target->nbuf_nfc_unmap_count); 242 243 htc_flush_endpoint_txlookupQ(target, ENDPOINT_0, true); 244 245 qdf_spinlock_destroy(&target->HTCLock); 246 qdf_spinlock_destroy(&target->HTCRxLock); 247 qdf_spinlock_destroy(&target->HTCTxLock); 248 for (i = 0; i < ENDPOINT_MAX; i++) { 249 endpoint = &target->endpoint[i]; 250 qdf_spinlock_destroy(&endpoint->lookup_queue_lock); 251 } 252 253 /* free our instance */ 254 qdf_mem_free(target); 255 } 256 257 #ifdef FEATURE_RUNTIME_PM 258 /** 259 * htc_runtime_pm_init(): runtime pm related initialization 260 * @target: HTC target 261 * 262 * need to initialize a work item. 263 */ htc_runtime_pm_init(HTC_TARGET * target)264 static void htc_runtime_pm_init(HTC_TARGET *target) 265 { 266 qdf_create_work(0, &target->queue_kicker, htc_kick_queues, target); 267 } 268 269 /** 270 * htc_runtime_suspend() - runtime suspend HTC 271 * 272 * @htc_ctx: HTC context pointer 273 * 274 * This is a dummy function for symmetry. 275 * 276 * Return: 0 for success 277 */ htc_runtime_suspend(HTC_HANDLE htc_ctx)278 int htc_runtime_suspend(HTC_HANDLE htc_ctx) 279 { 280 return 0; 281 } 282 283 /** 284 * htc_runtime_resume(): resume htc 285 * 286 * The htc message queue needs to be kicked off after 287 * a runtime resume. Otherwise messages would get stuck. 288 * 289 * @htc_ctx: HTC context pointer 290 * 291 * Return: 0 for success; 292 */ htc_runtime_resume(HTC_HANDLE htc_ctx)293 int htc_runtime_resume(HTC_HANDLE htc_ctx) 294 { 295 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_ctx); 296 297 if (!target) 298 return 0; 299 300 qdf_sched_work(0, &target->queue_kicker); 301 return 0; 302 } 303 304 /** 305 * htc_runtime_pm_deinit(): runtime pm related de-intialization 306 * 307 * need to de-initialize the work item. 308 * 309 * @target: HTC target pointer 310 * 311 */ htc_runtime_pm_deinit(HTC_TARGET * target)312 static void htc_runtime_pm_deinit(HTC_TARGET *target) 313 { 314 if (!target) 315 return; 316 317 qdf_destroy_work(0, &target->queue_kicker); 318 } 319 htc_dec_return_htt_runtime_cnt(HTC_HANDLE htc)320 int32_t htc_dec_return_htt_runtime_cnt(HTC_HANDLE htc) 321 { 322 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc); 323 324 return qdf_atomic_dec_return(&target->htc_htt_runtime_cnt); 325 } 326 327 /** 328 * htc_init_htt_runtime_cnt: Initialize htc htt runtime count 329 * @target: HTC target 330 * 331 * Return: None 332 */ 333 static inline htc_init_htt_runtime_cnt(HTC_TARGET * target)334 void htc_init_htt_runtime_cnt(HTC_TARGET *target) 335 { 336 qdf_atomic_init(&target->htc_htt_runtime_cnt); 337 } 338 #else htc_runtime_pm_init(HTC_TARGET * target)339 static inline void htc_runtime_pm_init(HTC_TARGET *target) { } htc_runtime_pm_deinit(HTC_TARGET * target)340 static inline void htc_runtime_pm_deinit(HTC_TARGET *target) { } 341 342 static inline htc_init_htt_runtime_cnt(HTC_TARGET * target)343 void htc_init_htt_runtime_cnt(HTC_TARGET *target) 344 { 345 } 346 #endif 347 348 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) 349 static htc_update_rx_bundle_stats(void * ctx,uint8_t no_of_pkt_in_bundle)350 void htc_update_rx_bundle_stats(void *ctx, uint8_t no_of_pkt_in_bundle) 351 { 352 HTC_TARGET *target = (HTC_TARGET *)ctx; 353 354 no_of_pkt_in_bundle--; 355 if (target && (no_of_pkt_in_bundle < HTC_MAX_MSG_PER_BUNDLE_RX)) 356 target->rx_bundle_stats[no_of_pkt_in_bundle]++; 357 } 358 #else 359 static htc_update_rx_bundle_stats(void * ctx,uint8_t no_of_pkt_in_bundle)360 void htc_update_rx_bundle_stats(void *ctx, uint8_t no_of_pkt_in_bundle) 361 { 362 } 363 #endif 364 365 #ifdef WLAN_DEBUG_LINK_VOTE 366 static qdf_atomic_t htc_link_vote_ids[HTC_LINK_VOTE_INVALID_MAX_USER_ID]; 367 htc_init_link_vote_ids(void)368 static void htc_init_link_vote_ids(void) 369 { 370 uint32_t i; 371 372 for (i = HTC_LINK_VOTE_INVALID_MIN_USER_ID; 373 i < HTC_LINK_VOTE_INVALID_MAX_USER_ID; i++) 374 qdf_atomic_init(&htc_link_vote_ids[i]); 375 } 376 htc_log_link_user_votes(void)377 void htc_log_link_user_votes(void) 378 { 379 uint32_t i; 380 uint32_t link_vote; 381 382 for (i = HTC_LINK_VOTE_INVALID_MIN_USER_ID + 1; 383 i < HTC_LINK_VOTE_INVALID_MAX_USER_ID; i++) { 384 link_vote = qdf_atomic_read(&htc_link_vote_ids[i]); 385 if (link_vote) 386 HTC_NOFL_INFO("Link vote %d user id: %d", 387 link_vote, i); 388 } 389 } 390 htc_vote_link_down(HTC_HANDLE htc_handle,enum htc_link_vote_user_id id)391 void htc_vote_link_down(HTC_HANDLE htc_handle, enum htc_link_vote_user_id id) 392 { 393 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); 394 395 if (!target->hif_dev) 396 return; 397 if (id >= HTC_LINK_VOTE_INVALID_MAX_USER_ID || 398 id <= HTC_LINK_VOTE_INVALID_MIN_USER_ID) { 399 HTC_ERROR("invalid id: %d", id); 400 return; 401 } 402 403 hif_vote_link_down(target->hif_dev); 404 qdf_atomic_dec(&htc_link_vote_ids[id]); 405 } 406 htc_vote_link_up(HTC_HANDLE htc_handle,enum htc_link_vote_user_id id)407 void htc_vote_link_up(HTC_HANDLE htc_handle, enum htc_link_vote_user_id id) 408 { 409 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); 410 411 if (!target->hif_dev) 412 return; 413 if (id >= HTC_LINK_VOTE_INVALID_MAX_USER_ID || 414 id <= HTC_LINK_VOTE_INVALID_MIN_USER_ID) { 415 HTC_ERROR("invalid link vote user id: %d", id); 416 return; 417 } 418 419 hif_vote_link_up(target->hif_dev); 420 qdf_atomic_inc(&htc_link_vote_ids[id]); 421 } 422 #else 423 static inline htc_init_link_vote_ids(void)424 void htc_init_link_vote_ids(void) 425 { 426 } 427 #endif 428 429 /* registered target arrival callback from the HIF layer */ htc_create(void * ol_sc,struct htc_init_info * pInfo,qdf_device_t osdev,uint32_t con_mode)430 HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo, 431 qdf_device_t osdev, uint32_t con_mode) 432 { 433 struct hif_msg_callbacks htcCallbacks; 434 HTC_ENDPOINT *pEndpoint = NULL; 435 HTC_TARGET *target = NULL; 436 int i; 437 438 if (!ol_sc) { 439 HTC_ERROR("%s: ol_sc = NULL", __func__); 440 return NULL; 441 } 442 HTC_TRACE("+htc_create .. HIF :%pK", ol_sc); 443 444 A_REGISTER_MODULE_DEBUG_INFO(htc); 445 446 target = (HTC_TARGET *) qdf_mem_malloc(sizeof(HTC_TARGET)); 447 if (!target) 448 return NULL; 449 450 htc_runtime_pm_init(target); 451 htc_credit_history_init(); 452 qdf_spinlock_create(&target->HTCLock); 453 qdf_spinlock_create(&target->HTCRxLock); 454 qdf_spinlock_create(&target->HTCTxLock); 455 for (i = 0; i < ENDPOINT_MAX; i++) { 456 pEndpoint = &target->endpoint[i]; 457 qdf_spinlock_create(&pEndpoint->lookup_queue_lock); 458 } 459 target->is_nodrop_pkt = false; 460 target->htc_hdr_length_check = false; 461 target->wmi_ep_count = 1; 462 463 do { 464 qdf_mem_copy(&target->HTCInitInfo, pInfo, 465 sizeof(struct htc_init_info)); 466 target->host_handle = pInfo->pContext; 467 target->osdev = osdev; 468 target->con_mode = con_mode; 469 470 /* If htc_ready_timeout_ms is not configured from CFG, 471 * assign the default timeout value here. 472 */ 473 474 if (!target->HTCInitInfo.htc_ready_timeout_ms) 475 target->HTCInitInfo.htc_ready_timeout_ms = 476 HTC_CONTROL_RX_TIMEOUT; 477 478 reset_endpoint_states(target); 479 480 INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList); 481 482 for (i = 0; i < HTC_PACKET_CONTAINER_ALLOCATION; i++) { 483 HTC_PACKET *pPacket = (HTC_PACKET *) 484 qdf_mem_malloc(sizeof(HTC_PACKET)); 485 if (pPacket) 486 free_htc_packet_container(target, pPacket); 487 } 488 489 #ifdef TODO_FIXME 490 for (i = 0; i < NUM_CONTROL_TX_BUFFERS; i++) { 491 pPacket = build_htc_tx_ctrl_packet(); 492 if (!pPacket) 493 break; 494 htc_free_control_tx_packet(target, pPacket); 495 } 496 #endif 497 498 /* setup HIF layer callbacks */ 499 qdf_mem_zero(&htcCallbacks, sizeof(struct hif_msg_callbacks)); 500 htcCallbacks.Context = target; 501 htcCallbacks.rxCompletionHandler = htc_rx_completion_handler; 502 htcCallbacks.txCompletionHandler = htc_tx_completion_handler; 503 htcCallbacks.txResourceAvailHandler = 504 htc_tx_resource_avail_handler; 505 htcCallbacks.fwEventHandler = htc_fw_event_handler; 506 htcCallbacks.update_bundle_stats = htc_update_rx_bundle_stats; 507 target->hif_dev = ol_sc; 508 509 /* Get HIF default pipe for HTC message exchange */ 510 pEndpoint = &target->endpoint[ENDPOINT_0]; 511 512 hif_post_init(target->hif_dev, target, &htcCallbacks); 513 hif_get_default_pipe(target->hif_dev, &pEndpoint->UL_PipeID, 514 &pEndpoint->DL_PipeID); 515 hif_set_initial_wakeup_cb(target->hif_dev, 516 pInfo->target_initial_wakeup_cb, 517 pInfo->target_psoc); 518 519 } while (false); 520 521 htc_recv_init(target); 522 htc_init_htt_runtime_cnt(target); 523 htc_init_wmi_runtime_cnt(target); 524 525 HTC_TRACE("-htc_create: (0x%pK)", target); 526 527 htc_hang_event_notifier_register(target); 528 529 htc_init_link_vote_ids(); 530 531 hif_rtpm_register(HIF_RTPM_ID_WMI, NULL); 532 hif_rtpm_register(HIF_RTPM_ID_HTT, NULL); 533 534 return (HTC_HANDLE) target; 535 } 536 htc_destroy(HTC_HANDLE HTCHandle)537 void htc_destroy(HTC_HANDLE HTCHandle) 538 { 539 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 540 541 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, 542 ("+htc_destroy .. Destroying :0x%pK\n", target)); 543 544 htc_hang_event_notifier_unregister(); 545 546 if (target) { 547 hif_stop(htc_get_hif_device(HTCHandle)); 548 htc_cleanup(target); 549 hif_rtpm_deregister(HIF_RTPM_ID_HTT); 550 hif_rtpm_deregister(HIF_RTPM_ID_WMI); 551 } 552 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n")); 553 htc_credit_history_deinit(); 554 } 555 556 /* get the low level HIF device for the caller , the caller may wish to do low 557 * level HIF requests 558 */ htc_get_hif_device(HTC_HANDLE HTCHandle)559 void *htc_get_hif_device(HTC_HANDLE HTCHandle) 560 { 561 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 562 563 return target->hif_dev; 564 } 565 htc_control_tx_complete(void * Context,HTC_PACKET * pPacket)566 static void htc_control_tx_complete(void *Context, HTC_PACKET *pPacket) 567 { 568 HTC_TARGET *target = (HTC_TARGET *) Context; 569 570 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, 571 ("+-htc_control_tx_complete 0x%pK (l:%d)\n", pPacket, 572 pPacket->ActualLength)); 573 htc_free_control_tx_packet(target, pPacket); 574 } 575 576 /* TODO, this is just a temporary max packet size */ 577 #define MAX_MESSAGE_SIZE 1536 578 579 /** 580 * htc_setup_epping_credit_allocation() - allocate credits/HTC buffers to WMI 581 * @scn: pointer to hif_opaque_softc 582 * @pEntry: pointer to tx credit allocation entry 583 * @credits: number of credits 584 * 585 * Return: None 586 */ 587 static void htc_setup_epping_credit_allocation(struct hif_opaque_softc * scn,struct htc_service_tx_credit_allocation * pEntry,int credits)588 htc_setup_epping_credit_allocation(struct hif_opaque_softc *scn, 589 struct htc_service_tx_credit_allocation *pEntry, 590 int credits) 591 { 592 switch (hif_get_bus_type(scn)) { 593 case QDF_BUS_TYPE_PCI: 594 case QDF_BUS_TYPE_USB: 595 pEntry++; 596 pEntry->service_id = WMI_DATA_BE_SVC; 597 pEntry->CreditAllocation = (credits >> 1); 598 599 pEntry++; 600 pEntry->service_id = WMI_DATA_BK_SVC; 601 pEntry->CreditAllocation = (credits >> 1); 602 break; 603 case QDF_BUS_TYPE_SDIO: 604 pEntry++; 605 pEntry->service_id = WMI_DATA_BE_SVC; 606 pEntry->CreditAllocation = credits; 607 break; 608 default: 609 break; 610 } 611 } 612 613 /** 614 * htc_setup_target_buffer_assignments() - setup target buffer assignments 615 * @target: HTC Target Pointer 616 * 617 * Return: A_STATUS 618 */ 619 static htc_setup_target_buffer_assignments(HTC_TARGET * target)620 A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target) 621 { 622 struct htc_service_tx_credit_allocation *pEntry; 623 A_STATUS status; 624 int credits; 625 int creditsPerMaxMsg; 626 627 creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize; 628 if (MAX_MESSAGE_SIZE % target->TargetCreditSize) 629 creditsPerMaxMsg++; 630 631 /* TODO, this should be configured by the caller! */ 632 633 credits = target->TotalTransmitCredits; 634 pEntry = &target->ServiceTxAllocTable[0]; 635 636 status = A_OK; 637 /* 638 * Allocate all credits/HTC buffers to WMI. 639 * no buffers are used/required for data. data always 640 * remains on host. 641 */ 642 if (HTC_IS_EPPING_ENABLED(target->con_mode)) { 643 pEntry++; 644 pEntry->service_id = WMI_CONTROL_SVC; 645 pEntry->CreditAllocation = credits; 646 /* endpoint ping is a testing tool directly on top of HTC in 647 * both target and host sides. 648 * In target side, the endppint ping fw has no wlan stack and 649 * FW mboxping app directly sits on HTC and it simply drops 650 * or loops back TX packets. For rx perf, FW mboxping app 651 * generates packets and passes packets to HTC to send to host. 652 * There is no WMI message exchanges between host and target 653 * in endpoint ping case. 654 * In host side, the endpoint ping driver is a Ethernet driver 655 * and it directly sits on HTC. Only HIF, HTC, QDF, ADF are 656 * used by the endpoint ping driver. There is no wifi stack 657 * at all in host side also. For tx perf use case, 658 * the user space mboxping app sends the raw packets to endpoint 659 * ping driver and it directly forwards to HTC for transmission 660 * to stress the bus. For the rx perf, HTC passes the received 661 * packets to endpoint ping driver and it is passed to the user 662 * space through the Ethernet interface. 663 * For credit allocation, in SDIO bus case, only BE service is 664 * used for tx/rx perf testing so that all credits are given 665 * to BE service. In PCIe and USB bus case, endpoint ping uses 666 * both BE and BK services to stress the bus so that the total 667 * credits are equally distributed to BE and BK services. 668 */ 669 670 htc_setup_epping_credit_allocation(target->hif_dev, 671 pEntry, credits); 672 } else { 673 int i; 674 uint32_t max_wmi_svc = (sizeof(svc_id) / sizeof(uint32_t)); 675 676 if ((target->wmi_ep_count == 0) || 677 (target->wmi_ep_count > max_wmi_svc)) 678 return A_ERROR; 679 680 /* 681 * Divide credit among number of endpoints for WMI 682 */ 683 credits = credits / target->wmi_ep_count; 684 for (i = 0; i < target->wmi_ep_count; i++) { 685 status = A_OK; 686 pEntry++; 687 pEntry->service_id = svc_id[i]; 688 pEntry->CreditAllocation = credits; 689 } 690 } 691 692 if (A_SUCCESS(status)) { 693 int i; 694 695 for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) { 696 if (target->ServiceTxAllocTable[i].service_id != 0) { 697 AR_DEBUG_PRINTF(ATH_DEBUG_INIT, 698 ("SVS Index : %d TX : 0x%2.2X : alloc:%d", 699 i, 700 target->ServiceTxAllocTable[i]. 701 service_id, 702 target->ServiceTxAllocTable[i]. 703 CreditAllocation)); 704 } 705 } 706 } 707 708 return status; 709 } 710 htc_get_credit_allocation(HTC_TARGET * target,uint16_t service_id)711 uint8_t htc_get_credit_allocation(HTC_TARGET *target, uint16_t service_id) 712 { 713 uint8_t allocation = 0; 714 int i; 715 716 for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) { 717 if (target->ServiceTxAllocTable[i].service_id == service_id) { 718 allocation = 719 target->ServiceTxAllocTable[i].CreditAllocation; 720 } 721 } 722 723 if (0 == allocation) { 724 AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, 725 ("HTC Service TX : 0x%2.2X : allocation is zero!\n", 726 service_id)); 727 } 728 729 return allocation; 730 } 731 htc_wait_target(HTC_HANDLE HTCHandle)732 QDF_STATUS htc_wait_target(HTC_HANDLE HTCHandle) 733 { 734 QDF_STATUS status = QDF_STATUS_SUCCESS; 735 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 736 HTC_READY_EX_MSG *pReadyMsg; 737 struct htc_service_connect_req connect; 738 struct htc_service_connect_resp resp; 739 HTC_READY_MSG *rdy_msg; 740 uint16_t htc_rdy_msg_id; 741 uint8_t i = 0; 742 HTC_PACKET *rx_bundle_packet, *temp_bundle_packet; 743 744 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, 745 ("htc_wait_target - Enter (target:0x%pK)\n", HTCHandle)); 746 AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("+HWT\n")); 747 748 do { 749 750 status = hif_start(target->hif_dev); 751 if (QDF_IS_STATUS_ERROR(status)) { 752 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, 753 ("hif_start failed\n")); 754 break; 755 } 756 757 status = htc_wait_recv_ctrl_message(target); 758 759 if (QDF_IS_STATUS_ERROR(status)) 760 break; 761 762 if (target->CtrlResponseLength < (sizeof(HTC_READY_EX_MSG))) { 763 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 764 ("Invalid HTC Ready Msg Len:%d!\n", 765 target->CtrlResponseLength)); 766 status = QDF_STATUS_E_BADMSG; 767 break; 768 } 769 770 pReadyMsg = (HTC_READY_EX_MSG *) target->CtrlResponseBuffer; 771 772 rdy_msg = &pReadyMsg->Version2_0_Info; 773 htc_rdy_msg_id = 774 HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, MESSAGEID); 775 if (htc_rdy_msg_id != HTC_MSG_READY_ID) { 776 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 777 ("Invalid HTC Ready Msg : 0x%X!\n", 778 htc_rdy_msg_id)); 779 status = QDF_STATUS_E_BADMSG; 780 break; 781 } 782 783 target->TotalTransmitCredits = HTC_GET_FIELD(rdy_msg, 784 HTC_READY_MSG, CREDITCOUNT); 785 if (target->HTCInitInfo.cfg_wmi_credit_cnt && 786 (target->HTCInitInfo.cfg_wmi_credit_cnt < 787 target->TotalTransmitCredits)) 788 /* 789 * If INI configured value is less than FW advertised, 790 * then use INI configured value, otherwise use FW 791 * advertised. 792 */ 793 target->TotalTransmitCredits = 794 target->HTCInitInfo.cfg_wmi_credit_cnt; 795 796 target->TargetCreditSize = 797 (int)HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITSIZE); 798 target->MaxMsgsPerHTCBundle = 799 (uint8_t) pReadyMsg->MaxMsgsPerHTCBundle; 800 UPDATE_ALT_CREDIT(target, pReadyMsg->AltDataCreditSize); 801 /* for old fw this value is set to 0. But the minimum value 802 * should be 1, i.e., no bundling 803 */ 804 if (target->MaxMsgsPerHTCBundle < 1) 805 target->MaxMsgsPerHTCBundle = 1; 806 807 AR_DEBUG_PRINTF(ATH_DEBUG_INIT, 808 ("Target Ready! TX resource : %d size:%d, MaxMsgsPerHTCBundle = %d", 809 target->TotalTransmitCredits, 810 target->TargetCreditSize, 811 target->MaxMsgsPerHTCBundle)); 812 813 if ((0 == target->TotalTransmitCredits) 814 || (0 == target->TargetCreditSize)) { 815 status = QDF_STATUS_E_ABORTED; 816 break; 817 } 818 819 /* Allocate expected number of RX bundle buffer allocation */ 820 if (HTC_RX_BUNDLE_ENABLED(target)) { 821 temp_bundle_packet = NULL; 822 for (i = 0; i < MAX_HTC_RX_BUNDLE; i++) { 823 rx_bundle_packet = 824 allocate_htc_bundle_packet(target); 825 if (rx_bundle_packet) 826 rx_bundle_packet->ListLink.pNext = 827 (DL_LIST *)temp_bundle_packet; 828 else 829 break; 830 831 temp_bundle_packet = rx_bundle_packet; 832 } 833 LOCK_HTC_TX(target); 834 target->pBundleFreeList = temp_bundle_packet; 835 UNLOCK_HTC_TX(target); 836 } 837 838 /* done processing */ 839 target->CtrlResponseProcessing = false; 840 841 htc_setup_target_buffer_assignments(target); 842 843 /* setup our pseudo HTC control endpoint connection */ 844 qdf_mem_zero(&connect, sizeof(connect)); 845 qdf_mem_zero(&resp, sizeof(resp)); 846 connect.EpCallbacks.pContext = target; 847 connect.EpCallbacks.EpTxComplete = htc_control_tx_complete; 848 connect.EpCallbacks.EpRecv = htc_control_rx_complete; 849 connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS; 850 connect.service_id = HTC_CTRL_RSVD_SVC; 851 852 /* connect fake service */ 853 status = htc_connect_service((HTC_HANDLE) target, 854 &connect, &resp); 855 856 } while (false); 857 858 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_wait_target - Exit (%d)\n", 859 status)); 860 AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("-HWT\n")); 861 return status; 862 } 863 864 /* start HTC, this is called after all services are connected */ htc_config_target_hif_pipe(HTC_TARGET * target)865 static A_STATUS htc_config_target_hif_pipe(HTC_TARGET *target) 866 { 867 868 return A_OK; 869 } 870 reset_endpoint_states(HTC_TARGET * target)871 static void reset_endpoint_states(HTC_TARGET *target) 872 { 873 HTC_ENDPOINT *pEndpoint; 874 int i; 875 876 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { 877 pEndpoint = &target->endpoint[i]; 878 pEndpoint->service_id = 0; 879 pEndpoint->MaxMsgLength = 0; 880 pEndpoint->MaxTxQueueDepth = 0; 881 pEndpoint->Id = i; 882 INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue); 883 INIT_HTC_PACKET_QUEUE(&pEndpoint->TxLookupQueue); 884 INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBufferHoldQueue); 885 pEndpoint->target = target; 886 pEndpoint->TxCreditFlowEnabled = (bool)htc_credit_flow; 887 pEndpoint->num_requeues_warn = 0; 888 pEndpoint->total_num_requeues = 0; 889 qdf_atomic_init(&pEndpoint->TxProcessCount); 890 } 891 } 892 893 /** 894 * htc_start() - Main HTC function to trigger HTC start 895 * @HTCHandle: pointer to HTC handle 896 * 897 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error 898 */ htc_start(HTC_HANDLE HTCHandle)899 QDF_STATUS htc_start(HTC_HANDLE HTCHandle) 900 { 901 qdf_nbuf_t netbuf; 902 QDF_STATUS status = QDF_STATUS_SUCCESS; 903 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 904 HTC_SETUP_COMPLETE_EX_MSG *pSetupComp; 905 HTC_PACKET *pSendPacket; 906 907 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Enter\n")); 908 909 do { 910 911 htc_config_target_hif_pipe(target); 912 913 /* allocate a buffer to send */ 914 pSendPacket = htc_alloc_control_tx_packet(target); 915 if (!pSendPacket) { 916 AR_DEBUG_ASSERT(false); 917 qdf_print("%s: allocControlTxPacket failed", 918 __func__); 919 status = QDF_STATUS_E_NOMEM; 920 break; 921 } 922 923 netbuf = 924 (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); 925 /* assemble setup complete message */ 926 qdf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); 927 pSetupComp = 928 (HTC_SETUP_COMPLETE_EX_MSG *) qdf_nbuf_data(netbuf); 929 qdf_mem_zero(pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); 930 931 HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG, 932 MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID); 933 934 if (!htc_credit_flow) { 935 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, 936 ("HTC will not use TX credit flow control")); 937 pSetupComp->SetupFlags |= 938 HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW; 939 } else { 940 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, 941 ("HTC using TX credit flow control")); 942 } 943 944 if ((hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO) || 945 (hif_get_bus_type(target->hif_dev) == 946 QDF_BUS_TYPE_USB)) { 947 if (HTC_RX_BUNDLE_ENABLED(target)) 948 pSetupComp->SetupFlags |= 949 HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; 950 hif_set_bundle_mode(target->hif_dev, true, 951 HTC_MAX_MSG_PER_BUNDLE_RX); 952 pSetupComp->MaxMsgsPerBundledRecv = HTC_MAX_MSG_PER_BUNDLE_RX; 953 } 954 955 SET_HTC_PACKET_INFO_TX(pSendPacket, 956 NULL, 957 (uint8_t *) pSetupComp, 958 sizeof(HTC_SETUP_COMPLETE_EX_MSG), 959 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); 960 961 status = htc_send_pkt((HTC_HANDLE) target, pSendPacket); 962 if (QDF_IS_STATUS_ERROR(status)) 963 break; 964 } while (false); 965 966 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Exit\n")); 967 return status; 968 } 969 970 /*flush all queued buffers for surpriseremove case*/ htc_flush_surprise_remove(HTC_HANDLE HTCHandle)971 void htc_flush_surprise_remove(HTC_HANDLE HTCHandle) 972 { 973 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 974 int i; 975 HTC_ENDPOINT *pEndpoint; 976 #ifdef RX_SG_SUPPORT 977 qdf_nbuf_t netbuf; 978 qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; 979 #endif 980 981 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove\n")); 982 983 /* cleanup endpoints */ 984 for (i = 0; i < ENDPOINT_MAX; i++) { 985 pEndpoint = &target->endpoint[i]; 986 htc_flush_rx_hold_queue(target, pEndpoint); 987 htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL); 988 } 989 990 hif_flush_surprise_remove(target->hif_dev); 991 992 #ifdef RX_SG_SUPPORT 993 LOCK_HTC_RX(target); 994 while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL) 995 qdf_nbuf_free(netbuf); 996 RESET_RX_SG_CONFIG(target); 997 UNLOCK_HTC_RX(target); 998 #endif 999 1000 reset_endpoint_states(target); 1001 1002 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove\n")); 1003 } 1004 1005 /* stop HTC communications, i.e. stop interrupt reception, and flush all queued 1006 * buffers 1007 */ htc_stop(HTC_HANDLE HTCHandle)1008 void htc_stop(HTC_HANDLE HTCHandle) 1009 { 1010 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 1011 int i; 1012 HTC_ENDPOINT *endpoint; 1013 #ifdef RX_SG_SUPPORT 1014 qdf_nbuf_t netbuf; 1015 qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; 1016 #endif 1017 1018 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop\n")); 1019 1020 htc_runtime_pm_deinit(target); 1021 1022 HTC_INFO("%s: endpoints cleanup\n", __func__); 1023 /* cleanup endpoints */ 1024 for (i = 0; i < ENDPOINT_MAX; i++) { 1025 endpoint = &target->endpoint[i]; 1026 htc_flush_rx_hold_queue(target, endpoint); 1027 htc_flush_endpoint_tx(target, endpoint, HTC_TX_PACKET_TAG_ALL); 1028 if (endpoint->ul_is_polled) { 1029 qdf_timer_stop(&endpoint->ul_poll_timer); 1030 qdf_timer_free(&endpoint->ul_poll_timer); 1031 } 1032 } 1033 1034 /* Note: htc_flush_endpoint_tx for all endpoints should be called before 1035 * hif_stop - otherwise htc_tx_completion_handler called from 1036 * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer, 1037 * might queue the packet again to HIF Layer - which could cause tx 1038 * buffer leak 1039 */ 1040 1041 HTC_INFO("%s: stopping hif layer\n", __func__); 1042 hif_stop(target->hif_dev); 1043 1044 #ifdef RX_SG_SUPPORT 1045 LOCK_HTC_RX(target); 1046 while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL) 1047 qdf_nbuf_free(netbuf); 1048 RESET_RX_SG_CONFIG(target); 1049 UNLOCK_HTC_RX(target); 1050 #endif 1051 1052 /** 1053 * In SSR case, HTC tx completion callback for wmi will be blocked 1054 * by TARGET_STATUS_RESET and HTC packets will be left unfreed on 1055 * lookup queue. 1056 * 1057 * In case of target failing to send wmi_ready_event, the htc connect 1058 * msg buffer will be left unmapped and not freed. So calling the 1059 * completion handler for this buffer will handle this scenario. 1060 */ 1061 HTC_INFO("%s: flush endpoints Tx lookup queue\n", __func__); 1062 for (i = 0; i < ENDPOINT_MAX; i++) { 1063 endpoint = &target->endpoint[i]; 1064 if (endpoint->service_id == WMI_CONTROL_SVC) 1065 htc_flush_endpoint_txlookupQ(target, i, false); 1066 else if (endpoint->service_id == HTC_CTRL_RSVD_SVC || 1067 (endpoint->service_id == HTT_DATA_MSG_SVC && 1068 !endpoint->ul_is_polled)) 1069 htc_flush_endpoint_txlookupQ(target, i, true); 1070 } 1071 HTC_INFO("%s: resetting endpoints state\n", __func__); 1072 1073 reset_endpoint_states(target); 1074 1075 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop\n")); 1076 } 1077 htc_dump_credit_states(HTC_HANDLE HTCHandle)1078 void htc_dump_credit_states(HTC_HANDLE HTCHandle) 1079 { 1080 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 1081 HTC_ENDPOINT *pEndpoint; 1082 int i; 1083 1084 for (i = 0; i < ENDPOINT_MAX; i++) { 1085 pEndpoint = &target->endpoint[i]; 1086 if (0 == pEndpoint->service_id) 1087 continue; 1088 1089 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 1090 ("--- EP : %d service_id: 0x%X --------------\n", 1091 pEndpoint->Id, pEndpoint->service_id)); 1092 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 1093 (" TxCredits : %d\n", 1094 pEndpoint->TxCredits)); 1095 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 1096 (" TxCreditSize : %d\n", 1097 pEndpoint->TxCreditSize)); 1098 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 1099 (" TxCreditsPerMaxMsg : %d\n", 1100 pEndpoint->TxCreditsPerMaxMsg)); 1101 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 1102 (" TxQueueDepth : %d\n", 1103 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); 1104 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 1105 ("----------------------------------------\n")); 1106 } 1107 } 1108 htc_get_endpoint_statistics(HTC_HANDLE HTCHandle,HTC_ENDPOINT_ID Endpoint,enum htc_endpoint_stat_action Action,struct htc_endpoint_stats * pStats)1109 bool htc_get_endpoint_statistics(HTC_HANDLE HTCHandle, 1110 HTC_ENDPOINT_ID Endpoint, 1111 enum htc_endpoint_stat_action Action, 1112 struct htc_endpoint_stats *pStats) 1113 { 1114 #ifdef HTC_EP_STAT_PROFILING 1115 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 1116 bool clearStats = false; 1117 bool sample = false; 1118 1119 switch (Action) { 1120 case HTC_EP_STAT_SAMPLE: 1121 sample = true; 1122 break; 1123 case HTC_EP_STAT_SAMPLE_AND_CLEAR: 1124 sample = true; 1125 clearStats = true; 1126 break; 1127 case HTC_EP_STAT_CLEAR: 1128 clearStats = true; 1129 break; 1130 default: 1131 break; 1132 } 1133 1134 A_ASSERT(Endpoint < ENDPOINT_MAX); 1135 1136 /* lock out TX and RX while we sample and/or clear */ 1137 LOCK_HTC_TX(target); 1138 LOCK_HTC_RX(target); 1139 1140 if (sample) { 1141 A_ASSERT(pStats); 1142 /* return the stats to the caller */ 1143 qdf_mem_copy(pStats, &target->endpoint[Endpoint].endpoint_stats, 1144 sizeof(struct htc_endpoint_stats)); 1145 } 1146 1147 if (clearStats) { 1148 /* reset stats */ 1149 qdf_mem_zero(&target->endpoint[Endpoint].endpoint_stats, 1150 sizeof(struct htc_endpoint_stats)); 1151 } 1152 1153 UNLOCK_HTC_RX(target); 1154 UNLOCK_HTC_TX(target); 1155 1156 return true; 1157 #else 1158 return false; 1159 #endif 1160 } 1161 htc_get_targetdef(HTC_HANDLE htc_handle)1162 void *htc_get_targetdef(HTC_HANDLE htc_handle) 1163 { 1164 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); 1165 1166 return hif_get_targetdef(target->hif_dev); 1167 } 1168 1169 #ifdef IPA_OFFLOAD 1170 /** 1171 * htc_ipa_get_ce_resource() - get uc resource on lower layer 1172 * @htc_handle: htc context 1173 * @ce_sr: copyengine source ring base physical address 1174 * @ce_sr_ring_size: copyengine source ring size 1175 * @ce_reg_paddr: copyengine register physical address 1176 * 1177 * Return: None 1178 */ htc_ipa_get_ce_resource(HTC_HANDLE htc_handle,qdf_shared_mem_t ** ce_sr,uint32_t * ce_sr_ring_size,qdf_dma_addr_t * ce_reg_paddr)1179 void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle, 1180 qdf_shared_mem_t **ce_sr, 1181 uint32_t *ce_sr_ring_size, 1182 qdf_dma_addr_t *ce_reg_paddr) 1183 { 1184 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); 1185 1186 if (target->hif_dev) 1187 hif_ipa_get_ce_resource(target->hif_dev, 1188 ce_sr, ce_sr_ring_size, ce_reg_paddr); 1189 } 1190 #endif /* IPA_OFFLOAD */ 1191 1192 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) 1193 htc_dump_bundle_stats(HTC_HANDLE HTCHandle)1194 void htc_dump_bundle_stats(HTC_HANDLE HTCHandle) 1195 { 1196 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 1197 int total, i; 1198 1199 total = 0; 1200 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++) 1201 total += target->rx_bundle_stats[i]; 1202 1203 if (total) { 1204 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("RX Bundle stats:\n")); 1205 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total RX packets: %d\n", 1206 total)); 1207 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ( 1208 "Number of bundle: Number of packets\n")); 1209 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++) 1210 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 1211 ("%10d:%10d(%2d%s)\n", (i+1), 1212 target->rx_bundle_stats[i], 1213 ((target->rx_bundle_stats[i]*100)/ 1214 total), "%")); 1215 } 1216 1217 1218 total = 0; 1219 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++) 1220 total += target->tx_bundle_stats[i]; 1221 1222 if (total) { 1223 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("TX Bundle stats:\n")); 1224 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total TX packets: %d\n", 1225 total)); 1226 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 1227 ("Number of bundle: Number of packets\n")); 1228 for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++) 1229 AR_DEBUG_PRINTF(ATH_DEBUG_ANY, 1230 ("%10d:%10d(%2d%s)\n", (i+1), 1231 target->tx_bundle_stats[i], 1232 ((target->tx_bundle_stats[i]*100)/ 1233 total), "%")); 1234 } 1235 } 1236 htc_clear_bundle_stats(HTC_HANDLE HTCHandle)1237 void htc_clear_bundle_stats(HTC_HANDLE HTCHandle) 1238 { 1239 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 1240 1241 qdf_mem_zero(&target->rx_bundle_stats, sizeof(target->rx_bundle_stats)); 1242 qdf_mem_zero(&target->tx_bundle_stats, sizeof(target->tx_bundle_stats)); 1243 } 1244 #endif 1245 1246 /** 1247 * htc_can_suspend_link - API to query HIF for link status 1248 * @htc_handle: HTC Handle 1249 * 1250 * API for upper layers to call HIF to query if the link can suspend 1251 * 1252 * Return: void 1253 */ htc_can_suspend_link(HTC_HANDLE htc_handle)1254 bool htc_can_suspend_link(HTC_HANDLE htc_handle) 1255 { 1256 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); 1257 1258 if (!target->hif_dev) 1259 return false; 1260 1261 return hif_can_suspend_link(target->hif_dev); 1262 } 1263 1264 #ifdef FEATURE_RUNTIME_PM htc_pm_runtime_get(HTC_HANDLE htc_handle)1265 int htc_pm_runtime_get(HTC_HANDLE htc_handle) 1266 { 1267 return hif_rtpm_get(HIF_RTPM_GET_ASYNC, HIF_RTPM_ID_HTT); 1268 } 1269 htc_pm_runtime_put(HTC_HANDLE htc_handle)1270 int htc_pm_runtime_put(HTC_HANDLE htc_handle) 1271 { 1272 return hif_rtpm_put(HIF_RTPM_PUT_ASYNC, HIF_RTPM_ID_HTT); 1273 } 1274 #endif 1275 1276 /** 1277 * htc_set_wmi_endpoint_count: Set number of WMI endpoint 1278 * @htc_handle: HTC handle 1279 * @wmi_ep_count: WMI endpoint count 1280 * 1281 * return: None 1282 */ htc_set_wmi_endpoint_count(HTC_HANDLE htc_handle,uint8_t wmi_ep_count)1283 void htc_set_wmi_endpoint_count(HTC_HANDLE htc_handle, uint8_t wmi_ep_count) 1284 { 1285 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); 1286 1287 target->wmi_ep_count = wmi_ep_count; 1288 } 1289 1290 /** 1291 * htc_get_wmi_endpoint_count: Get number of WMI endpoint 1292 * @htc_handle: HTC handle 1293 * 1294 * return: WMI endpoint count 1295 */ htc_get_wmi_endpoint_count(HTC_HANDLE htc_handle)1296 uint8_t htc_get_wmi_endpoint_count(HTC_HANDLE htc_handle) 1297 { 1298 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); 1299 1300 return target->wmi_ep_count; 1301 } 1302