1 /* 2 * Copyright (c) 2013-2019 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 #include "htc_debug.h" 20 #include "htc_internal.h" 21 #include "htc_credit_history.h" 22 #include <qdf_mem.h> /* qdf_mem_malloc */ 23 #include <qdf_nbuf.h> /* qdf_nbuf_t */ 24 #include "qdf_module.h" 25 26 /* #define USB_HIF_SINGLE_PIPE_DATA_SCHED */ 27 /* #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED */ 28 #define DATA_EP_SIZE 4 29 /* #endif */ 30 #define HTC_DATA_RESOURCE_THRS 256 31 #define HTC_DATA_MINDESC_PERPACKET 2 32 33 enum HTC_SEND_QUEUE_RESULT { 34 HTC_SEND_QUEUE_OK = 0, /* packet was queued */ 35 HTC_SEND_QUEUE_DROP = 1, /* this packet should be dropped */ 36 }; 37 38 #ifndef DEBUG_CREDIT 39 #define DEBUG_CREDIT 0 40 #endif 41 42 #if DEBUG_CREDIT 43 /* bit mask to enable debug certain endpoint */ 44 static unsigned int ep_debug_mask = 45 (1 << ENDPOINT_0) | (1 << ENDPOINT_1) | (1 << ENDPOINT_2); 46 #endif 47 48 #ifdef QCA_WIFI_NAPIER_EMULATION 49 #define HTC_EMULATION_DELAY_IN_MS 20 50 /** 51 * htc_add_delay(): Adds a delay in before proceeding, only for emulation 52 * 53 * Return: None 54 */ 55 static inline void htc_add_emulation_delay(void) 56 { 57 qdf_mdelay(HTC_EMULATION_DELAY_IN_MS); 58 } 59 #else 60 static inline void htc_add_emulation_delay(void) 61 { 62 } 63 #endif 64 65 void htc_dump_counter_info(HTC_HANDLE HTCHandle) 66 { 67 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 68 69 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 70 ("\n%s: ce_send_cnt = %d, TX_comp_cnt = %d\n", 71 __func__, target->ce_send_cnt, target->TX_comp_cnt)); 72 } 73 74 int htc_get_tx_queue_depth(HTC_HANDLE htc_handle, HTC_ENDPOINT_ID endpoint_id) 75 { 76 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle); 77 HTC_ENDPOINT *endpoint = &target->endpoint[endpoint_id]; 78 79 return HTC_PACKET_QUEUE_DEPTH(&endpoint->TxQueue); 80 } 81 qdf_export_symbol(htc_get_tx_queue_depth); 82 83 void htc_get_control_endpoint_tx_host_credits(HTC_HANDLE HTCHandle, 84 int *credits) 85 { 86 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 87 HTC_ENDPOINT *pEndpoint; 88 int i; 89 90 if (!credits || !target) { 91 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: invalid args", __func__)); 92 return; 93 } 94 95 *credits = 0; 96 LOCK_HTC_TX(target); 97 for (i = 0; i < ENDPOINT_MAX; i++) { 98 pEndpoint = &target->endpoint[i]; 99 if (pEndpoint->service_id == WMI_CONTROL_SVC) { 100 *credits = pEndpoint->TxCredits; 101 break; 102 } 103 } 104 UNLOCK_HTC_TX(target); 105 } 106 107 static inline void restore_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket) 108 { 109 qdf_nbuf_t netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 110 111 if (pPacket->PktInfo.AsTx.Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) { 112 qdf_nbuf_unmap(target->osdev, netbuf, QDF_DMA_TO_DEVICE); 113 pPacket->PktInfo.AsTx.Flags &= ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF; 114 } 115 if (pPacket->PktInfo.AsTx.Flags & 116 HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA) { 117 qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR)); 118 } 119 } 120 121 static void send_packet_completion(HTC_TARGET *target, HTC_PACKET *pPacket) 122 { 123 HTC_ENDPOINT *pEndpoint = &target->endpoint[pPacket->Endpoint]; 124 HTC_EP_SEND_PKT_COMPLETE EpTxComplete; 125 126 restore_tx_packet(target, pPacket); 127 128 /* do completion */ 129 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 130 ("HTC calling ep %d send complete callback on packet %pK\n", 131 pEndpoint->Id, pPacket)); 132 133 EpTxComplete = pEndpoint->EpCallBacks.EpTxComplete; 134 if (EpTxComplete) 135 EpTxComplete(pEndpoint->EpCallBacks.pContext, pPacket); 136 else 137 qdf_nbuf_free(pPacket->pPktContext); 138 139 140 } 141 142 #ifdef FEATURE_RUNTIME_PM 143 /** 144 * log_packet_info() - Log HTC packet information 145 * 146 * @target: handle of HTC context 147 * @pPacket: handle of HTC packet 148 * 149 * Return: None 150 */ 151 static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket) 152 { 153 HTC_ENDPOINT *pEndpoint = &target->endpoint[pPacket->Endpoint]; 154 HTC_EP_LOG_PKT ep_log_pkt; 155 qdf_nbuf_t netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 156 157 ep_log_pkt = pEndpoint->EpCallBacks.ep_log_pkt; 158 if (ep_log_pkt) { 159 qdf_nbuf_pull_head(netbuf, sizeof(HTC_FRAME_HDR)); 160 ep_log_pkt(pEndpoint->EpCallBacks.pContext, pPacket); 161 qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR)); 162 } 163 } 164 #else 165 static void log_packet_info(HTC_TARGET *target, HTC_PACKET *pPacket) 166 { 167 } 168 #endif 169 170 void htc_send_complete_check_cleanup(void *context) 171 { 172 HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *) context; 173 174 htc_send_complete_check(pEndpoint, 1); 175 } 176 177 HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target) 178 { 179 HTC_PACKET *pPacket; 180 HTC_PACKET_QUEUE *pQueueSave; 181 qdf_nbuf_t netbuf; 182 183 LOCK_HTC_TX(target); 184 if (!target->pBundleFreeList) { 185 UNLOCK_HTC_TX(target); 186 netbuf = qdf_nbuf_alloc(NULL, 187 target->MaxMsgsPerHTCBundle * 188 target->TargetCreditSize, 0, 4, false); 189 AR_DEBUG_ASSERT(netbuf); 190 if (!netbuf) 191 return NULL; 192 pPacket = qdf_mem_malloc(sizeof(HTC_PACKET)); 193 AR_DEBUG_ASSERT(pPacket); 194 if (!pPacket) { 195 qdf_nbuf_free(netbuf); 196 return NULL; 197 } 198 pQueueSave = qdf_mem_malloc(sizeof(HTC_PACKET_QUEUE)); 199 AR_DEBUG_ASSERT(pQueueSave); 200 if (!pQueueSave) { 201 qdf_nbuf_free(netbuf); 202 qdf_mem_free(pPacket); 203 return NULL; 204 } 205 INIT_HTC_PACKET_QUEUE(pQueueSave); 206 pPacket->pContext = pQueueSave; 207 SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf); 208 pPacket->pBuffer = qdf_nbuf_data(netbuf); 209 pPacket->BufferLength = qdf_nbuf_len(netbuf); 210 211 /* store the original head room so that we can restore this 212 * when we "free" the packet. 213 * free packet puts the packet back on the free list 214 */ 215 pPacket->netbufOrigHeadRoom = qdf_nbuf_headroom(netbuf); 216 return pPacket; 217 } 218 /* already done malloc - restore from free list */ 219 pPacket = target->pBundleFreeList; 220 AR_DEBUG_ASSERT(pPacket); 221 if (!pPacket) { 222 UNLOCK_HTC_TX(target); 223 return NULL; 224 } 225 target->pBundleFreeList = (HTC_PACKET *) pPacket->ListLink.pNext; 226 UNLOCK_HTC_TX(target); 227 pPacket->ListLink.pNext = NULL; 228 229 return pPacket; 230 } 231 232 void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket) 233 { 234 uint32_t curentHeadRoom; 235 qdf_nbuf_t netbuf; 236 HTC_PACKET_QUEUE *pQueueSave; 237 238 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 239 AR_DEBUG_ASSERT(netbuf); 240 if (!netbuf) { 241 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 242 ("\n%s: Invalid netbuf in HTC Packet\n", 243 __func__)); 244 return; 245 } 246 /* HIF adds data to the headroom section of the nbuf, restore thei 247 * original size. If this is not done, headroom keeps shrinking with 248 * every HIF send and eventually HIF ends up doing another malloc big 249 * enough to store the data + its header 250 */ 251 252 curentHeadRoom = qdf_nbuf_headroom(netbuf); 253 qdf_nbuf_pull_head(netbuf, 254 pPacket->netbufOrigHeadRoom - curentHeadRoom); 255 qdf_nbuf_trim_tail(netbuf, qdf_nbuf_len(netbuf)); 256 257 /* restore the pBuffer pointer. HIF changes this */ 258 pPacket->pBuffer = qdf_nbuf_data(netbuf); 259 pPacket->BufferLength = qdf_nbuf_len(netbuf); 260 261 /* restore queue */ 262 pQueueSave = (HTC_PACKET_QUEUE *) pPacket->pContext; 263 if (qdf_unlikely(!pQueueSave)) { 264 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 265 ("\n%s: Invalid pQueueSave in HTC Packet\n", 266 __func__)); 267 AR_DEBUG_ASSERT(pQueueSave); 268 } else 269 INIT_HTC_PACKET_QUEUE(pQueueSave); 270 271 LOCK_HTC_TX(target); 272 if (!target->pBundleFreeList) { 273 target->pBundleFreeList = pPacket; 274 pPacket->ListLink.pNext = NULL; 275 } else { 276 pPacket->ListLink.pNext = (DL_LIST *) target->pBundleFreeList; 277 target->pBundleFreeList = pPacket; 278 } 279 UNLOCK_HTC_TX(target); 280 } 281 282 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) 283 284 /** 285 * htc_send_update_tx_bundle_stats() - update tx bundle stats depends 286 * on max bundle size 287 * @target: hif context 288 * @data_len: tx data len 289 * @TxCreditSize: endpoint tx credit size 290 * 291 * Return: None 292 */ 293 static inline void 294 htc_send_update_tx_bundle_stats(HTC_TARGET *target, 295 qdf_size_t data_len, 296 int TxCreditSize) 297 { 298 if ((data_len / TxCreditSize) <= HTC_MAX_MSG_PER_BUNDLE_TX) 299 target->tx_bundle_stats[(data_len / TxCreditSize) - 1]++; 300 } 301 302 /** 303 * htc_issue_tx_bundle_stats_inc() - increment in tx bundle stats 304 * on max bundle size 305 * @target: hif context 306 * 307 * Return: None 308 */ 309 static inline void 310 htc_issue_tx_bundle_stats_inc(HTC_TARGET *target) 311 { 312 target->tx_bundle_stats[0]++; 313 } 314 #else 315 316 static inline void 317 htc_send_update_tx_bundle_stats(HTC_TARGET *target, 318 qdf_size_t data_len, 319 int TxCreditSize) 320 { 321 } 322 323 static inline void 324 htc_issue_tx_bundle_stats_inc(HTC_TARGET *target) 325 { 326 } 327 #endif 328 329 #if defined(HIF_USB) || defined(HIF_SDIO) 330 #ifdef ENABLE_BUNDLE_TX 331 static QDF_STATUS htc_send_bundled_netbuf(HTC_TARGET *target, 332 HTC_ENDPOINT *pEndpoint, 333 unsigned char *pBundleBuffer, 334 HTC_PACKET *pPacketTx) 335 { 336 qdf_size_t data_len; 337 QDF_STATUS status; 338 qdf_nbuf_t bundleBuf; 339 uint32_t data_attr = 0; 340 341 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx); 342 data_len = pBundleBuffer - qdf_nbuf_data(bundleBuf); 343 qdf_nbuf_put_tail(bundleBuf, data_len); 344 SET_HTC_PACKET_INFO_TX(pPacketTx, 345 target, 346 pBundleBuffer, 347 data_len, 348 pEndpoint->Id, HTC_TX_PACKET_TAG_BUNDLED); 349 LOCK_HTC_TX(target); 350 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacketTx); 351 pEndpoint->ul_outstanding_cnt++; 352 UNLOCK_HTC_TX(target); 353 #if DEBUG_BUNDLE 354 qdf_print(" Send bundle EP%d buffer size:0x%x, total:0x%x, count:%d.", 355 pEndpoint->Id, 356 pEndpoint->TxCreditSize, 357 data_len, data_len / pEndpoint->TxCreditSize); 358 #endif 359 360 htc_send_update_tx_bundle_stats(target, data_len, 361 pEndpoint->TxCreditSize); 362 363 status = hif_send_head(target->hif_dev, 364 pEndpoint->UL_PipeID, 365 pEndpoint->Id, data_len, 366 bundleBuf, data_attr); 367 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) { 368 HTC_PACKET_QUEUE requeue; 369 370 qdf_print("hif_send_head failed(len=%zu).", data_len); 371 INIT_HTC_PACKET_QUEUE(&requeue); 372 LOCK_HTC_TX(target); 373 pEndpoint->ul_outstanding_cnt--; 374 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacketTx); 375 376 if (pPacketTx->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) { 377 HTC_PACKET *temp_packet; 378 HTC_PACKET_QUEUE *packet_queue = 379 (HTC_PACKET_QUEUE *)pPacketTx->pContext; 380 381 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(packet_queue, 382 temp_packet) { 383 HTC_PACKET_ENQUEUE(&requeue, temp_packet); 384 } HTC_PACKET_QUEUE_ITERATE_END; 385 386 UNLOCK_HTC_TX(target); 387 free_htc_bundle_packet(target, pPacketTx); 388 LOCK_HTC_TX(target); 389 390 } else { 391 HTC_PACKET_ENQUEUE(&requeue, pPacketTx); 392 } 393 394 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, 395 &requeue); 396 UNLOCK_HTC_TX(target); 397 } 398 return status; 399 } 400 401 #ifdef QCA_TX_PADDING_CREDIT_SUPPORT 402 #define SDIO_BLOCK_SIZE 512 403 static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep) 404 { 405 int ret = 0; 406 407 if (!ep || !ep->EpCallBacks.pContext || 408 !ep->EpCallBacks.ep_padding_credit_update) 409 return 1; 410 411 ret = ep->EpCallBacks.ep_padding_credit_update(ep->EpCallBacks.pContext, 412 0); 413 414 if (ret < 2) 415 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s ret %d\n", __func__, ret)); 416 417 return ret; 418 } 419 420 static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep, 421 HTC_PACKET *p_last_htc_pkt, 422 unsigned char *p_last_pkt_bundle_buffer, 423 unsigned char **p_bundle_buffer, 424 int tot_data_len) 425 { 426 bool extra_tx_credit = FALSE; 427 HTC_FRAME_HDR *p_htc_hdr; 428 int first_buf_bundled_len = 0, last_buf_len = 0; 429 int sdio_pad = 0, free_space = 0; 430 int (*update_ep_padding_credit)(void *, int); 431 432 update_ep_padding_credit = ep->EpCallBacks.ep_padding_credit_update; 433 434 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 435 ("%s Tot data_len = %d\n", __func__, tot_data_len)); 436 437 if (!p_last_htc_pkt) 438 return extra_tx_credit; 439 440 last_buf_len = (p_last_htc_pkt->ActualLength + HTC_HDR_LENGTH); 441 if (tot_data_len != last_buf_len) { 442 first_buf_bundled_len = tot_data_len - ep->TxCreditSize; 443 free_space = tot_data_len - 444 (first_buf_bundled_len + last_buf_len); 445 } else { 446 free_space = ep->TxCreditSize - tot_data_len; 447 } 448 449 sdio_pad = SDIO_BLOCK_SIZE - ((first_buf_bundled_len + last_buf_len) % 450 SDIO_BLOCK_SIZE); 451 452 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 453 ("%s first_buf_bundled_len = %d last_buf_len = %d\n", 454 __func__, first_buf_bundled_len, last_buf_len)); 455 456 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 457 ("%s sdio_pad = %d free_space = %d\n", __func__, 458 sdio_pad, free_space)); 459 460 if (sdio_pad <= free_space) { 461 if (p_bundle_buffer && *p_bundle_buffer) { 462 /* Align Tx bundled buf to avoid a extra Padding buf */ 463 *p_bundle_buffer -= (free_space - sdio_pad); 464 } 465 } else { 466 /* Extra Padding Buffer needed, consume extra tx credit */ 467 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 468 ("%s Used a Tx credit for Padding Buffer\n", 469 __func__)); 470 p_htc_hdr = (HTC_FRAME_HDR *)(p_last_pkt_bundle_buffer); 471 p_htc_hdr->Flags |= HTC_FLAGS_PADDING_CHECK; 472 extra_tx_credit = TRUE; 473 if (ep->EpCallBacks.ep_padding_credit_update) { 474 /* Decrement 1 credit at host, 475 * due to extra tx credit consumed by padding buffer 476 */ 477 update_ep_padding_credit(ep->EpCallBacks.pContext, -1); 478 } 479 } 480 return extra_tx_credit; 481 } 482 #else 483 static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep) 484 { 485 return 1; 486 } 487 488 static bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep, 489 HTC_PACKET *p_last_htc_pkt, 490 unsigned char *p_last_pkt_bundle_buffer, 491 unsigned char **p_bundle_buffer, 492 int tot_data_len) 493 { 494 return FALSE; 495 } 496 #endif 497 498 /** 499 * htc_issue_packets_bundle() - HTC function to send bundle packets from a queue 500 * @target: HTC target on which packets need to be sent 501 * @pEndpoint: logical endpoint on which packets needs to be sent 502 * @pPktQueue: HTC packet queue containing the list of packets to be sent 503 * 504 * Return: void 505 */ 506 static void htc_issue_packets_bundle(HTC_TARGET *target, 507 HTC_ENDPOINT *pEndpoint, 508 HTC_PACKET_QUEUE *pPktQueue) 509 { 510 int i, frag_count, nbytes; 511 qdf_nbuf_t netbuf, bundleBuf; 512 unsigned char *pBundleBuffer = NULL; 513 HTC_PACKET *pPacket = NULL, *pPacketTx = NULL; 514 HTC_FRAME_HDR *pHtcHdr; 515 int last_credit_pad = 0; 516 int creditPad, creditRemainder, transferLength, bundlesSpaceRemaining = 517 0; 518 HTC_PACKET_QUEUE *pQueueSave = NULL; 519 HTC_PACKET *p_last_htc_pkt = NULL; 520 unsigned char *p_last_pkt_bundle_buffer = NULL; 521 522 bundlesSpaceRemaining = 523 target->MaxMsgsPerHTCBundle * pEndpoint->TxCreditSize; 524 pPacketTx = allocate_htc_bundle_packet(target); 525 if (!pPacketTx) { 526 /* good time to panic */ 527 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 528 ("allocate_htc_bundle_packet failed\n")); 529 AR_DEBUG_ASSERT(false); 530 return; 531 } 532 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx); 533 pBundleBuffer = qdf_nbuf_data(bundleBuf); 534 pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext; 535 while (1) { 536 if (pEndpoint->EpCallBacks.ep_padding_credit_update) { 537 if (htc_tx_pad_credit_avail(pEndpoint) < 1) 538 break; 539 } 540 pPacket = htc_packet_dequeue(pPktQueue); 541 if (!pPacket) 542 break; 543 creditPad = 0; 544 transferLength = pPacket->ActualLength + HTC_HDR_LENGTH; 545 creditRemainder = transferLength % pEndpoint->TxCreditSize; 546 if (creditRemainder != 0) { 547 if (transferLength < pEndpoint->TxCreditSize) { 548 creditPad = pEndpoint->TxCreditSize - 549 transferLength; 550 } else { 551 creditPad = creditRemainder; 552 } 553 transferLength += creditPad; 554 } 555 556 if (bundlesSpaceRemaining < transferLength) { 557 htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt, 558 p_last_pkt_bundle_buffer, 559 &pBundleBuffer, 560 pBundleBuffer - 561 qdf_nbuf_data(bundleBuf)); 562 563 /* send out previous buffer */ 564 htc_send_bundled_netbuf(target, pEndpoint, 565 pBundleBuffer - last_credit_pad, 566 pPacketTx); 567 /* One packet has been dequeued from sending queue when enter 568 * this loop, so need to add 1 back for this checking. 569 */ 570 if ((HTC_PACKET_QUEUE_DEPTH(pPktQueue) + 1) < 571 HTC_MIN_MSG_PER_BUNDLE) { 572 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket); 573 return; 574 } 575 bundlesSpaceRemaining = 576 target->MaxMsgsPerHTCBundle * 577 pEndpoint->TxCreditSize; 578 pPacketTx = allocate_htc_bundle_packet(target); 579 if (!pPacketTx) { 580 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket); 581 /* good time to panic */ 582 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 583 ("allocate_htc_bundle_packet failed\n")); 584 AR_DEBUG_ASSERT(false); 585 return; 586 } 587 bundleBuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacketTx); 588 pBundleBuffer = qdf_nbuf_data(bundleBuf); 589 pQueueSave = (HTC_PACKET_QUEUE *) pPacketTx->pContext; 590 } 591 592 p_last_htc_pkt = pPacket; 593 p_last_pkt_bundle_buffer = pBundleBuffer; 594 595 bundlesSpaceRemaining -= transferLength; 596 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 597 598 if (hif_get_bus_type(target->hif_dev) != QDF_BUS_TYPE_USB) { 599 pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr( 600 netbuf, 0); 601 HTC_WRITE32(pHtcHdr, 602 SM(pPacket->ActualLength, 603 HTC_FRAME_HDR_PAYLOADLEN) | 604 SM(pPacket->PktInfo.AsTx.SendFlags | 605 HTC_FLAGS_SEND_BUNDLE, 606 HTC_FRAME_HDR_FLAGS) | 607 SM(pPacket->Endpoint, 608 HTC_FRAME_HDR_ENDPOINTID)); 609 HTC_WRITE32((uint32_t *) pHtcHdr + 1, 610 SM(pPacket->PktInfo.AsTx.SeqNo, 611 HTC_FRAME_HDR_CONTROLBYTES1) | SM(creditPad, 612 HTC_FRAME_HDR_RESERVED)); 613 pHtcHdr->reserved = creditPad; 614 } 615 frag_count = qdf_nbuf_get_num_frags(netbuf); 616 nbytes = pPacket->ActualLength + HTC_HDR_LENGTH; 617 for (i = 0; i < frag_count && nbytes > 0; i++) { 618 int frag_len = qdf_nbuf_get_frag_len(netbuf, i); 619 unsigned char *frag_addr = 620 qdf_nbuf_get_frag_vaddr(netbuf, i); 621 if (frag_len > nbytes) 622 frag_len = nbytes; 623 qdf_mem_copy(pBundleBuffer, frag_addr, frag_len); 624 nbytes -= frag_len; 625 pBundleBuffer += frag_len; 626 } 627 HTC_PACKET_ENQUEUE(pQueueSave, pPacket); 628 pBundleBuffer += creditPad; 629 630 /* last one can't be packed. */ 631 if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB) 632 last_credit_pad = creditPad; 633 } 634 /* send out remaining buffer */ 635 if (pBundleBuffer != qdf_nbuf_data(bundleBuf)) { 636 htc_handle_extra_tx_credit(pEndpoint, p_last_htc_pkt, 637 p_last_pkt_bundle_buffer, 638 &pBundleBuffer, 639 pBundleBuffer - 640 qdf_nbuf_data(bundleBuf)); 641 642 htc_send_bundled_netbuf(target, pEndpoint, 643 pBundleBuffer - last_credit_pad, 644 pPacketTx); 645 } else { 646 free_htc_bundle_packet(target, pPacketTx); 647 } 648 } 649 #endif /* ENABLE_BUNDLE_TX */ 650 #else 651 static int htc_tx_pad_credit_avail(HTC_ENDPOINT *ep) 652 { 653 return 1; 654 } 655 656 bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep, 657 HTC_PACKET *p_last_htc_pkt, 658 unsigned char *p_last_pkt_bundle_buffer, 659 unsigned char **p_bundle_buffer, 660 int tot_data_len); 661 bool htc_handle_extra_tx_credit(HTC_ENDPOINT *ep, 662 HTC_PACKET *p_last_htc_pkt, 663 unsigned char *p_last_pkt_bundle_buffer, 664 unsigned char **p_bundle_buffer, 665 int tot_data_len) 666 { 667 return FALSE; 668 } 669 670 static void htc_issue_packets_bundle(HTC_TARGET *target, 671 HTC_ENDPOINT *pEndpoint, 672 HTC_PACKET_QUEUE *pPktQueue) 673 { 674 } 675 #endif 676 677 /** 678 * htc_issue_packets() - HTC function to send packets from a queue 679 * @target: HTC target on which packets need to be sent 680 * @pEndpoint: logical endpoint on which packets needs to be sent 681 * @pPktQueue: HTC packet queue containing the list of packets to be sent 682 * 683 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure 684 */ 685 static QDF_STATUS htc_issue_packets(HTC_TARGET *target, 686 HTC_ENDPOINT *pEndpoint, 687 HTC_PACKET_QUEUE *pPktQueue) 688 { 689 QDF_STATUS status = QDF_STATUS_SUCCESS; 690 qdf_nbuf_t netbuf; 691 HTC_PACKET *pPacket = NULL; 692 uint16_t payloadLen; 693 HTC_FRAME_HDR *pHtcHdr; 694 uint32_t data_attr = 0; 695 enum qdf_bus_type bus_type; 696 QDF_STATUS ret; 697 bool rt_put = false; 698 bool used_extra_tx_credit = false; 699 uint8_t *buf = NULL; 700 int (*update_ep_padding_credit)(void *, int); 701 void *ctx = NULL; 702 703 update_ep_padding_credit = 704 pEndpoint->EpCallBacks.ep_padding_credit_update; 705 706 bus_type = hif_get_bus_type(target->hif_dev); 707 708 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 709 ("+htc_issue_packets: Queue: %pK, Pkts %d\n", pPktQueue, 710 HTC_PACKET_QUEUE_DEPTH(pPktQueue))); 711 while (true) { 712 if (HTC_TX_BUNDLE_ENABLED(target) && 713 HTC_PACKET_QUEUE_DEPTH(pPktQueue) >= 714 HTC_MIN_MSG_PER_BUNDLE) { 715 switch (bus_type) { 716 case QDF_BUS_TYPE_SDIO: 717 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) 718 break; 719 if (update_ep_padding_credit) { 720 if (htc_tx_pad_credit_avail 721 (pEndpoint) < 1) 722 break; 723 } 724 case QDF_BUS_TYPE_USB: 725 htc_issue_packets_bundle(target, 726 pEndpoint, 727 pPktQueue); 728 break; 729 default: 730 break; 731 } 732 } 733 /* if not bundling or there was a packet that could not be 734 * placed in a bundle, and send it by normal way 735 */ 736 if (pEndpoint->EpCallBacks.ep_padding_credit_update) { 737 if (htc_tx_pad_credit_avail(pEndpoint) < 1) { 738 status = QDF_STATUS_E_FAILURE; 739 break; 740 } 741 } 742 743 pPacket = htc_packet_dequeue(pPktQueue); 744 if (!pPacket) { 745 /* local queue is fully drained */ 746 break; 747 } 748 749 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 750 AR_DEBUG_ASSERT(netbuf); 751 /* Non-credit enabled endpoints have been mapped and setup by 752 * now, so no need to revisit the HTC headers 753 */ 754 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { 755 756 payloadLen = pPacket->ActualLength; 757 /* setup HTC frame header */ 758 759 pHtcHdr = (HTC_FRAME_HDR *) 760 qdf_nbuf_get_frag_vaddr(netbuf, 0); 761 if (qdf_unlikely(!pHtcHdr)) { 762 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 763 ("%s Invalid pHtcHdr\n", 764 __func__)); 765 AR_DEBUG_ASSERT(pHtcHdr); 766 status = QDF_STATUS_E_FAILURE; 767 break; 768 } 769 770 HTC_WRITE32(pHtcHdr, 771 SM(payloadLen, 772 HTC_FRAME_HDR_PAYLOADLEN) | 773 SM(pPacket->PktInfo.AsTx.SendFlags, 774 HTC_FRAME_HDR_FLAGS) | 775 SM(pPacket->Endpoint, 776 HTC_FRAME_HDR_ENDPOINTID)); 777 HTC_WRITE32(((uint32_t *) pHtcHdr) + 1, 778 SM(pPacket->PktInfo.AsTx.SeqNo, 779 HTC_FRAME_HDR_CONTROLBYTES1)); 780 781 /* 782 * Now that the HTC frame header has been added, the 783 * netbuf can be mapped. This only applies to non-data 784 * frames, since data frames were already mapped as they 785 * entered into the driver. 786 */ 787 pPacket->PktInfo.AsTx.Flags |= 788 HTC_TX_PACKET_FLAG_FIXUP_NETBUF; 789 790 ret = qdf_nbuf_map(target->osdev, 791 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket), 792 QDF_DMA_TO_DEVICE); 793 if (ret != QDF_STATUS_SUCCESS) { 794 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 795 ("%s nbuf Map Fail Endpnt %pK\n", 796 __func__, pEndpoint)); 797 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket); 798 status = QDF_STATUS_E_FAILURE; 799 break; 800 } 801 } 802 803 if (!pEndpoint->async_update) { 804 LOCK_HTC_TX(target); 805 } 806 /* store in look up queue to match completions */ 807 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket); 808 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1); 809 pEndpoint->ul_outstanding_cnt++; 810 if (!pEndpoint->async_update) { 811 UNLOCK_HTC_TX(target); 812 hif_send_complete_check(target->hif_dev, 813 pEndpoint->UL_PipeID, false); 814 } 815 816 htc_packet_set_magic_cookie(pPacket, HTC_PACKET_MAGIC_COOKIE); 817 /* 818 * For HTT messages without a response from fw, 819 * do the runtime put here. 820 * otherwise runtime put will be done when the fw response comes 821 */ 822 if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_RUNTIME_PUT) 823 rt_put = true; 824 #if DEBUG_BUNDLE 825 qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.", 826 pEndpoint->Id, 827 pEndpoint->TxCreditSize, 828 HTC_HDR_LENGTH + pPacket->ActualLength); 829 #endif 830 buf = (uint8_t *)qdf_nbuf_get_frag_vaddr(netbuf, 0); 831 used_extra_tx_credit = 832 htc_handle_extra_tx_credit(pEndpoint, pPacket, buf, 833 NULL, pPacket->ActualLength + 834 HTC_HDR_LENGTH); 835 836 status = hif_send_head(target->hif_dev, 837 pEndpoint->UL_PipeID, pEndpoint->Id, 838 HTC_HDR_LENGTH + pPacket->ActualLength, 839 netbuf, data_attr); 840 841 if (status != QDF_STATUS_SUCCESS) { 842 if (pEndpoint->EpCallBacks.ep_padding_credit_update) { 843 if (used_extra_tx_credit) { 844 ctx = pEndpoint->EpCallBacks.pContext; 845 update_ep_padding_credit(ctx, 1); 846 } 847 } 848 } 849 850 htc_issue_tx_bundle_stats_inc(target); 851 852 target->ce_send_cnt++; 853 854 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) { 855 if (status != QDF_STATUS_E_RESOURCES) { 856 /* TODO : if more than 1 endpoint maps to the 857 * same PipeID it is possible to run out of 858 * resources in the HIF layer. Don't emit the 859 * error 860 */ 861 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 862 ("hif_send Failed status:%d\n", 863 status)); 864 } 865 866 /* only unmap if we mapped in this function */ 867 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { 868 qdf_nbuf_unmap(target->osdev, 869 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket), 870 QDF_DMA_TO_DEVICE); 871 pPacket->PktInfo.AsTx.Flags &= 872 ~HTC_TX_PACKET_FLAG_FIXUP_NETBUF; 873 } 874 875 if (!pEndpoint->async_update) { 876 LOCK_HTC_TX(target); 877 } 878 target->ce_send_cnt--; 879 pEndpoint->ul_outstanding_cnt--; 880 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket); 881 htc_packet_set_magic_cookie(pPacket, 0); 882 /* put it back into the callers queue */ 883 HTC_PACKET_ENQUEUE_TO_HEAD(pPktQueue, pPacket); 884 /* reclaim credits */ 885 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue, 886 pPacket) { 887 pEndpoint->TxCredits += 888 pPacket->PktInfo.AsTx.CreditsUsed; 889 } HTC_PACKET_QUEUE_ITERATE_END; 890 if (!pEndpoint->async_update) { 891 UNLOCK_HTC_TX(target); 892 } 893 break; 894 } 895 if (rt_put) { 896 hif_pm_runtime_put(target->hif_dev); 897 rt_put = false; 898 } 899 } 900 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) { 901 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 902 ("htc_issue_packets, failed pkt:0x%pK status:%d", 903 pPacket, status)); 904 } 905 906 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_issue_packets\n")); 907 908 return status; 909 } 910 911 #ifdef FEATURE_RUNTIME_PM 912 /** 913 * extract_htc_pm_packets(): move pm packets from endpoint into queue 914 * @endpoint: which enpoint to extract packets from 915 * @queue: a queue to store extracted packets in. 916 * 917 * remove pm packets from the endpoint's tx queue. 918 * queue them into a queue 919 */ 920 static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint, 921 HTC_PACKET_QUEUE *queue) 922 { 923 HTC_PACKET *packet; 924 925 /* only WMI endpoint has power management packets */ 926 if (endpoint->service_id != WMI_CONTROL_SVC) 927 return; 928 929 ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet, 930 HTC_PACKET, ListLink) { 931 if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_AUTO_PM) { 932 HTC_PACKET_REMOVE(&endpoint->TxQueue, packet); 933 HTC_PACKET_ENQUEUE(queue, packet); 934 } 935 } ITERATE_END 936 } 937 938 /** 939 * queue_htc_pm_packets(): queue pm packets with priority 940 * @endpoint: enpoint to queue packets to 941 * @queue: queue of pm packets to enque 942 * 943 * suspend resume packets get special treatment & priority. 944 * need to queue them at the front of the queue. 945 */ 946 static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint, 947 HTC_PACKET_QUEUE *queue) 948 { 949 if (endpoint->service_id != WMI_CONTROL_SVC) 950 return; 951 952 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&endpoint->TxQueue, queue); 953 } 954 #else 955 static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint, 956 HTC_PACKET_QUEUE *queue) 957 {} 958 959 static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint, 960 HTC_PACKET_QUEUE *queue) 961 {} 962 #endif 963 964 /** 965 * get_htc_send_packets_credit_based() - get packets based on available credits 966 * @target: HTC target on which packets need to be sent 967 * @pEndpoint: logical endpoint on which packets needs to be sent 968 * @pQueue: HTC packet queue containing the list of packets to be sent 969 * 970 * Get HTC send packets from TX queue on an endpoint based on available credits. 971 * The function moves the packets from TX queue of the endpoint to pQueue. 972 * 973 * Return: None 974 */ 975 static void get_htc_send_packets_credit_based(HTC_TARGET *target, 976 HTC_ENDPOINT *pEndpoint, 977 HTC_PACKET_QUEUE *pQueue) 978 { 979 int creditsRequired; 980 int remainder; 981 uint8_t sendFlags; 982 HTC_PACKET *pPacket; 983 unsigned int transferLength; 984 HTC_PACKET_QUEUE *tx_queue; 985 HTC_PACKET_QUEUE pm_queue; 986 bool do_pm_get = false; 987 int ret; 988 989 /*** NOTE : the TX lock is held when this function is called ***/ 990 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 991 ("+get_htc_send_packets_credit_based\n")); 992 993 INIT_HTC_PACKET_QUEUE(&pm_queue); 994 extract_htc_pm_packets(pEndpoint, &pm_queue); 995 if (HTC_QUEUE_EMPTY(&pm_queue)) { 996 tx_queue = &pEndpoint->TxQueue; 997 do_pm_get = true; 998 } else { 999 tx_queue = &pm_queue; 1000 } 1001 1002 /* loop until we can grab as many packets out of the queue as we can */ 1003 while (true) { 1004 if (do_pm_get) { 1005 ret = hif_pm_runtime_get(target->hif_dev); 1006 if (ret) { 1007 /* bus suspended, runtime resume issued */ 1008 QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0); 1009 if (ret == -EAGAIN) { 1010 pPacket = htc_get_pkt_at_head(tx_queue); 1011 if (!pPacket) 1012 break; 1013 log_packet_info(target, pPacket); 1014 } 1015 break; 1016 } 1017 } 1018 1019 sendFlags = 0; 1020 /* get packet at head, but don't remove it */ 1021 pPacket = htc_get_pkt_at_head(tx_queue); 1022 if (!pPacket) { 1023 if (do_pm_get) 1024 hif_pm_runtime_put(target->hif_dev); 1025 break; 1026 } 1027 1028 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1029 (" Got head packet:%pK , Queue Depth: %d\n", 1030 pPacket, 1031 HTC_PACKET_QUEUE_DEPTH(tx_queue))); 1032 1033 transferLength = pPacket->ActualLength + HTC_HDR_LENGTH; 1034 1035 if (transferLength <= pEndpoint->TxCreditSize) { 1036 creditsRequired = 1; 1037 } else { 1038 /* figure out how many credits this message requires */ 1039 creditsRequired = 1040 transferLength / pEndpoint->TxCreditSize; 1041 remainder = transferLength % pEndpoint->TxCreditSize; 1042 1043 if (remainder) 1044 creditsRequired++; 1045 } 1046 1047 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1048 (" Credits Required:%d Got:%d\n", 1049 creditsRequired, pEndpoint->TxCredits)); 1050 1051 if (pEndpoint->Id == ENDPOINT_0) { 1052 /* 1053 * endpoint 0 is special, it always has a credit and 1054 * does not require credit based flow control 1055 */ 1056 creditsRequired = 0; 1057 } else { 1058 1059 if (pEndpoint->TxCredits < creditsRequired) { 1060 #if DEBUG_CREDIT 1061 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 1062 ("EP%d,No Credit now.%d < %d\n", 1063 pEndpoint->Id, 1064 pEndpoint->TxCredits, 1065 creditsRequired)); 1066 #endif 1067 if (do_pm_get) 1068 hif_pm_runtime_put(target->hif_dev); 1069 break; 1070 } 1071 1072 pEndpoint->TxCredits -= creditsRequired; 1073 INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, 1074 creditsRequired); 1075 1076 /* check if we need credits back from the target */ 1077 if (pEndpoint->TxCredits <= 1078 pEndpoint->TxCreditsPerMaxMsg) { 1079 /* tell the target we need credits ASAP! */ 1080 sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE; 1081 if (pEndpoint->service_id == WMI_CONTROL_SVC) { 1082 htc_credit_record(HTC_REQUEST_CREDIT, 1083 pEndpoint->TxCredits, 1084 HTC_PACKET_QUEUE_DEPTH 1085 (tx_queue)); 1086 } 1087 INC_HTC_EP_STAT(pEndpoint, 1088 TxCreditLowIndications, 1); 1089 #if DEBUG_CREDIT 1090 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 1091 (" EP%d Needs Credits\n", 1092 pEndpoint->Id)); 1093 #endif 1094 } 1095 } 1096 1097 /* now we can fully dequeue */ 1098 pPacket = htc_packet_dequeue(tx_queue); 1099 if (pPacket) { 1100 /* save the number of credits this packet consumed */ 1101 pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired; 1102 /* save send flags */ 1103 pPacket->PktInfo.AsTx.SendFlags = sendFlags; 1104 1105 /* queue this packet into the caller's queue */ 1106 HTC_PACKET_ENQUEUE(pQueue, pPacket); 1107 } 1108 } 1109 1110 if (!HTC_QUEUE_EMPTY(&pm_queue)) 1111 queue_htc_pm_packets(pEndpoint, &pm_queue); 1112 1113 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1114 ("-get_htc_send_packets_credit_based\n")); 1115 1116 } 1117 1118 static void get_htc_send_packets(HTC_TARGET *target, 1119 HTC_ENDPOINT *pEndpoint, 1120 HTC_PACKET_QUEUE *pQueue, int Resources) 1121 { 1122 1123 HTC_PACKET *pPacket; 1124 HTC_PACKET_QUEUE *tx_queue; 1125 HTC_PACKET_QUEUE pm_queue; 1126 bool do_pm_get = false; 1127 int ret; 1128 1129 /*** NOTE : the TX lock is held when this function is called ***/ 1130 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1131 ("+get_htc_send_packets %d resources\n", Resources)); 1132 1133 INIT_HTC_PACKET_QUEUE(&pm_queue); 1134 extract_htc_pm_packets(pEndpoint, &pm_queue); 1135 if (HTC_QUEUE_EMPTY(&pm_queue)) { 1136 tx_queue = &pEndpoint->TxQueue; 1137 do_pm_get = true; 1138 } else { 1139 tx_queue = &pm_queue; 1140 } 1141 1142 /* loop until we can grab as many packets out of the queue as we can */ 1143 while (Resources > 0) { 1144 int num_frags; 1145 1146 if (do_pm_get) { 1147 ret = hif_pm_runtime_get(target->hif_dev); 1148 if (ret) { 1149 /* bus suspended, runtime resume issued */ 1150 QDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0); 1151 if (ret == -EAGAIN) { 1152 pPacket = htc_get_pkt_at_head(tx_queue); 1153 if (!pPacket) 1154 break; 1155 log_packet_info(target, pPacket); 1156 } 1157 break; 1158 } 1159 } 1160 1161 pPacket = htc_packet_dequeue(tx_queue); 1162 if (!pPacket) { 1163 if (do_pm_get) 1164 hif_pm_runtime_put(target->hif_dev); 1165 break; 1166 } 1167 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1168 (" Got packet:%pK , New Queue Depth: %d\n", 1169 pPacket, 1170 HTC_PACKET_QUEUE_DEPTH(tx_queue))); 1171 /* For non-credit path the sequence number is already embedded 1172 * in the constructed HTC header 1173 */ 1174 pPacket->PktInfo.AsTx.SendFlags = 0; 1175 pPacket->PktInfo.AsTx.CreditsUsed = 0; 1176 /* queue this packet into the caller's queue */ 1177 HTC_PACKET_ENQUEUE(pQueue, pPacket); 1178 1179 /* 1180 * FIX THIS: 1181 * For now, avoid calling qdf_nbuf_get_num_frags before calling 1182 * qdf_nbuf_map, because the MacOS version of qdf_nbuf_t doesn't 1183 * support qdf_nbuf_get_num_frags until after qdf_nbuf_map has 1184 * been done. 1185 * Assume that the non-data netbufs, i.e. WMI message netbufs, 1186 * consist of a single fragment. 1187 */ 1188 /* WMI messages are in a single-fragment network buf */ 1189 num_frags = 1190 (pPacket->PktInfo.AsTx. 1191 Flags & HTC_TX_PACKET_FLAG_FIXUP_NETBUF) ? 1 : 1192 qdf_nbuf_get_num_frags(GET_HTC_PACKET_NET_BUF_CONTEXT 1193 (pPacket)); 1194 Resources -= num_frags; 1195 } 1196 1197 if (!HTC_QUEUE_EMPTY(&pm_queue)) 1198 queue_htc_pm_packets(pEndpoint, &pm_queue); 1199 1200 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets\n")); 1201 1202 } 1203 1204 /** 1205 * htc_try_send() - Send packets in a queue on an endpoint 1206 * @target: HTC target on which packets need to be sent 1207 * @pEndpoint: logical endpoint on which packets needs to be sent 1208 * @pCallersSendQueue: packet queue containing the list of packets to be sent 1209 * 1210 * Return: enum HTC_SEND_QUEUE_RESULT indicates whether the packet was queued to 1211 * be sent or the packet should be dropped by the upper layer 1212 */ 1213 static enum HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target, 1214 HTC_ENDPOINT *pEndpoint, 1215 HTC_PACKET_QUEUE *pCallersSendQueue) 1216 { 1217 /* temp queue to hold packets at various stages */ 1218 HTC_PACKET_QUEUE sendQueue; 1219 HTC_PACKET *pPacket; 1220 int tx_resources; 1221 int overflow; 1222 enum HTC_SEND_QUEUE_RESULT result = HTC_SEND_QUEUE_OK; 1223 1224 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+htc_try_send (Queue:%pK Depth:%d)\n", 1225 pCallersSendQueue, 1226 (pCallersSendQueue == 1227 NULL) ? 0 : 1228 HTC_PACKET_QUEUE_DEPTH 1229 (pCallersSendQueue))); 1230 1231 /* init the local send queue */ 1232 INIT_HTC_PACKET_QUEUE(&sendQueue); 1233 1234 do { 1235 1236 /* caller didn't provide a queue, just wants us to check 1237 * queues and send 1238 */ 1239 if (!pCallersSendQueue) 1240 break; 1241 1242 if (HTC_QUEUE_EMPTY(pCallersSendQueue)) { 1243 /* empty queue */ 1244 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target, 1245 HTC_PKT_Q_EMPTY); 1246 result = HTC_SEND_QUEUE_DROP; 1247 break; 1248 } 1249 1250 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) >= 1251 pEndpoint->MaxTxQueueDepth) { 1252 /* we've already overflowed */ 1253 overflow = HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue); 1254 } else { 1255 /* figure out how much we will overflow by */ 1256 overflow = HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); 1257 overflow += HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue); 1258 /* get how much we will overflow the TX queue by */ 1259 overflow -= pEndpoint->MaxTxQueueDepth; 1260 } 1261 1262 /* if overflow is negative or zero, we are okay */ 1263 if (overflow > 0) { 1264 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1265 ("Endpoint %d, TX queue will overflow :%d , Tx Depth:%d, Max:%d\n", 1266 pEndpoint->Id, overflow, 1267 HTC_PACKET_QUEUE_DEPTH(&pEndpoint-> 1268 TxQueue), 1269 pEndpoint->MaxTxQueueDepth)); 1270 } 1271 if ((overflow <= 0) 1272 || (!pEndpoint->EpCallBacks.EpSendFull)) { 1273 /* all packets will fit or caller did not provide send 1274 * full indication handler 1275 * just move all of them to local sendQueue object 1276 */ 1277 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&sendQueue, 1278 pCallersSendQueue); 1279 } else { 1280 int i; 1281 int goodPkts = 1282 HTC_PACKET_QUEUE_DEPTH(pCallersSendQueue) - 1283 overflow; 1284 1285 A_ASSERT(goodPkts >= 0); 1286 /* we have overflowed and callback is provided. Dequeue 1287 * all non-overflow packets into the sendqueue 1288 */ 1289 for (i = 0; i < goodPkts; i++) { 1290 /* pop off caller's queue */ 1291 pPacket = htc_packet_dequeue(pCallersSendQueue); 1292 A_ASSERT(pPacket); 1293 if (pPacket) 1294 /* insert into local queue */ 1295 HTC_PACKET_ENQUEUE(&sendQueue, 1296 pPacket); 1297 } 1298 1299 /* the caller's queue has all the packets that won't fit 1300 * walk through the caller's queue and indicate each one 1301 * to the send full handler 1302 */ 1303 ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue-> 1304 QueueHead, pPacket, 1305 HTC_PACKET, ListLink) { 1306 1307 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1308 ("Indicating overflowed TX packet: %pK\n", 1309 pPacket)); 1310 /* 1311 * Remove headroom reserved for HTC_FRAME_HDR 1312 * before giving the packet back to the user via 1313 * the EpSendFull callback. 1314 */ 1315 restore_tx_packet(target, pPacket); 1316 1317 if (pEndpoint->EpCallBacks. 1318 EpSendFull(pEndpoint->EpCallBacks.pContext, 1319 pPacket) == HTC_SEND_FULL_DROP) { 1320 /* callback wants the packet dropped */ 1321 INC_HTC_EP_STAT(pEndpoint, TxDropped, 1322 1); 1323 /* leave this one in the caller's queue 1324 * for cleanup 1325 */ 1326 } else { 1327 /* callback wants to keep this packet, 1328 * remove from caller's queue 1329 */ 1330 HTC_PACKET_REMOVE(pCallersSendQueue, 1331 pPacket); 1332 /* put it in the send queue 1333 * add HTC_FRAME_HDR space reservation 1334 * again 1335 */ 1336 qdf_nbuf_push_head 1337 (GET_HTC_PACKET_NET_BUF_CONTEXT 1338 (pPacket), 1339 sizeof(HTC_FRAME_HDR)); 1340 1341 HTC_PACKET_ENQUEUE(&sendQueue, pPacket); 1342 } 1343 1344 } 1345 ITERATE_END; 1346 1347 if (HTC_QUEUE_EMPTY(&sendQueue)) { 1348 /* no packets made it in, caller will cleanup */ 1349 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target, 1350 HTC_SEND_Q_EMPTY); 1351 result = HTC_SEND_QUEUE_DROP; 1352 break; 1353 } 1354 } 1355 1356 } while (false); 1357 1358 if (result != HTC_SEND_QUEUE_OK) { 1359 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send: %d\n", 1360 result)); 1361 return result; 1362 } 1363 1364 LOCK_HTC_TX(target); 1365 1366 if (!HTC_QUEUE_EMPTY(&sendQueue)) { 1367 if (target->is_nodrop_pkt) { 1368 /* 1369 * nodrop pkts have higher priority than normal pkts, 1370 * insert nodrop pkt to head for proper 1371 * start/termination of test. 1372 */ 1373 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, 1374 &sendQueue); 1375 target->is_nodrop_pkt = false; 1376 } else { 1377 /* transfer packets to tail */ 1378 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->TxQueue, 1379 &sendQueue); 1380 A_ASSERT(HTC_QUEUE_EMPTY(&sendQueue)); 1381 INIT_HTC_PACKET_QUEUE(&sendQueue); 1382 } 1383 } 1384 1385 /* increment tx processing count on entry */ 1386 if (qdf_atomic_inc_return(&pEndpoint->TxProcessCount) > 1) { 1387 /* another thread or task is draining the TX queues on this 1388 * endpoint that thread will reset the tx processing count when 1389 * the queue is drained 1390 */ 1391 qdf_atomic_dec(&pEndpoint->TxProcessCount); 1392 UNLOCK_HTC_TX(target); 1393 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send (busy)\n")); 1394 return HTC_SEND_QUEUE_OK; 1395 } 1396 1397 /***** beyond this point only 1 thread may enter ******/ 1398 1399 /* now drain the endpoint TX queue for transmission as long as we have 1400 * enough transmit resources 1401 */ 1402 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { 1403 tx_resources = 1404 hif_get_free_queue_number(target->hif_dev, 1405 pEndpoint->UL_PipeID); 1406 } else { 1407 tx_resources = 0; 1408 } 1409 1410 while (true) { 1411 1412 if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) 1413 break; 1414 1415 if (pEndpoint->async_update && 1416 (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) && 1417 (!tx_resources)) 1418 break; 1419 1420 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { 1421 #if DEBUG_CREDIT 1422 int cred = pEndpoint->TxCredits; 1423 #endif 1424 /* credit based mechanism provides flow control based on 1425 * target transmit resource availability, we assume that 1426 * the HIF layer will always have bus resources greater 1427 * than target transmit resources 1428 */ 1429 get_htc_send_packets_credit_based(target, pEndpoint, 1430 &sendQueue); 1431 #if DEBUG_CREDIT 1432 if (ep_debug_mask & (1 << pEndpoint->Id)) { 1433 if (cred - pEndpoint->TxCredits > 0) { 1434 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 1435 (" <HTC> Decrease EP%d %d - %d = %d credits.\n", 1436 pEndpoint->Id, cred, 1437 cred - 1438 pEndpoint->TxCredits, 1439 pEndpoint->TxCredits)); 1440 } 1441 } 1442 #endif 1443 } else { 1444 1445 /* 1446 * Header and payload belongs to the different fragments and 1447 * consume 2 resource for one HTC package but USB combine into 1448 * one transfer.And one WMI message only consumes one single 1449 * resource. 1450 */ 1451 if (HTC_TX_BUNDLE_ENABLED(target) && tx_resources && 1452 hif_get_bus_type(target->hif_dev) == 1453 QDF_BUS_TYPE_USB) { 1454 if (pEndpoint->service_id == 1455 WMI_CONTROL_SVC) 1456 tx_resources = 1457 HTC_MAX_MSG_PER_BUNDLE_TX; 1458 else 1459 tx_resources = 1460 (HTC_MAX_MSG_PER_BUNDLE_TX * 2); 1461 } 1462 /* get all the packets for this endpoint that we can for 1463 * this pass 1464 */ 1465 get_htc_send_packets(target, pEndpoint, &sendQueue, 1466 tx_resources); 1467 } 1468 1469 if (HTC_PACKET_QUEUE_DEPTH(&sendQueue) == 0) { 1470 /* didn't get any packets due to a lack of resources or 1471 * TX queue was drained 1472 */ 1473 break; 1474 } 1475 1476 if (!pEndpoint->async_update) 1477 UNLOCK_HTC_TX(target); 1478 1479 /* send what we can */ 1480 if (htc_issue_packets(target, pEndpoint, &sendQueue)) { 1481 int i; 1482 1483 result = HTC_SEND_QUEUE_DROP; 1484 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 1485 ("htc_issue_packets, failed status:%d put it back to head of callersSendQueue", 1486 result)); 1487 1488 for (i = HTC_PACKET_QUEUE_DEPTH(&sendQueue); i > 0; i--) 1489 hif_pm_runtime_put(target->hif_dev); 1490 if (!pEndpoint->async_update) { 1491 LOCK_HTC_TX(target); 1492 } 1493 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, 1494 &sendQueue); 1495 break; 1496 } 1497 1498 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { 1499 tx_resources = 1500 hif_get_free_queue_number(target->hif_dev, 1501 pEndpoint->UL_PipeID); 1502 } 1503 1504 if (!pEndpoint->async_update) { 1505 LOCK_HTC_TX(target); 1506 } 1507 1508 } 1509 1510 /* done with this endpoint, we can clear the count */ 1511 qdf_atomic_init(&pEndpoint->TxProcessCount); 1512 1513 UNLOCK_HTC_TX(target); 1514 1515 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_try_send:\n")); 1516 1517 return HTC_SEND_QUEUE_OK; 1518 } 1519 1520 #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED 1521 static uint16_t htc_send_pkts_sched_check(HTC_HANDLE HTCHandle, 1522 HTC_ENDPOINT_ID id) 1523 { 1524 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 1525 HTC_ENDPOINT *pEndpoint; 1526 HTC_ENDPOINT_ID eid; 1527 HTC_PACKET_QUEUE *pTxQueue; 1528 uint16_t resources; 1529 uint16_t acQueueStatus[DATA_EP_SIZE] = { 0, 0, 0, 0 }; 1530 1531 if (id < ENDPOINT_2 || id > ENDPOINT_5) 1532 return 1; 1533 1534 for (eid = ENDPOINT_2; eid <= ENDPOINT_5; eid++) { 1535 pEndpoint = &target->endpoint[eid]; 1536 pTxQueue = &pEndpoint->TxQueue; 1537 1538 if (HTC_QUEUE_EMPTY(pTxQueue)) 1539 acQueueStatus[eid - 2] = 1; 1540 } 1541 1542 switch (id) { 1543 case ENDPOINT_2: /* BE */ 1544 return acQueueStatus[0] && acQueueStatus[2] 1545 && acQueueStatus[3]; 1546 case ENDPOINT_3: /* BK */ 1547 return acQueueStatus[0] && acQueueStatus[1] && acQueueStatus[2] 1548 && acQueueStatus[3]; 1549 case ENDPOINT_4: /* VI */ 1550 return acQueueStatus[2] && acQueueStatus[3]; 1551 case ENDPOINT_5: /* VO */ 1552 return acQueueStatus[3]; 1553 default: 1554 return 0; 1555 } 1556 1557 } 1558 1559 static A_STATUS htc_send_pkts_sched_queue(HTC_TARGET *target, 1560 HTC_PACKET_QUEUE *pPktQueue, 1561 HTC_ENDPOINT_ID eid) 1562 { 1563 HTC_ENDPOINT *pEndpoint; 1564 HTC_PACKET_QUEUE *pTxQueue; 1565 HTC_PACKET *pPacket; 1566 int goodPkts; 1567 1568 pEndpoint = &target->endpoint[eid]; 1569 pTxQueue = &pEndpoint->TxQueue; 1570 1571 LOCK_HTC_TX(target); 1572 1573 goodPkts = 1574 pEndpoint->MaxTxQueueDepth - 1575 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue); 1576 1577 if (goodPkts > 0) { 1578 while (!HTC_QUEUE_EMPTY(pPktQueue)) { 1579 pPacket = htc_packet_dequeue(pPktQueue); 1580 HTC_PACKET_ENQUEUE(pTxQueue, pPacket); 1581 goodPkts--; 1582 1583 if (goodPkts <= 0) 1584 break; 1585 } 1586 } 1587 1588 if (HTC_PACKET_QUEUE_DEPTH(pPktQueue)) { 1589 ITERATE_OVER_LIST_ALLOW_REMOVE(&pPktQueue->QueueHead, pPacket, 1590 HTC_PACKET, ListLink) { 1591 1592 if (pEndpoint->EpCallBacks. 1593 EpSendFull(pEndpoint->EpCallBacks.pContext, 1594 pPacket) == HTC_SEND_FULL_DROP) { 1595 INC_HTC_EP_STAT(pEndpoint, TxDropped, 1); 1596 } else { 1597 HTC_PACKET_REMOVE(pPktQueue, pPacket); 1598 HTC_PACKET_ENQUEUE(pTxQueue, pPacket); 1599 } 1600 } 1601 ITERATE_END; 1602 } 1603 1604 UNLOCK_HTC_TX(target); 1605 1606 return A_OK; 1607 } 1608 1609 #endif 1610 1611 static inline QDF_STATUS __htc_send_pkt(HTC_HANDLE HTCHandle, 1612 HTC_PACKET *pPacket) 1613 { 1614 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 1615 HTC_ENDPOINT *pEndpoint; 1616 HTC_PACKET_QUEUE pPktQueue; 1617 qdf_nbuf_t netbuf; 1618 HTC_FRAME_HDR *htc_hdr; 1619 QDF_STATUS status; 1620 1621 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1622 ("+__htc_send_pkt\n")); 1623 1624 /* get packet at head to figure out which endpoint these packets will 1625 * go into 1626 */ 1627 if (!pPacket) { 1628 OL_ATH_HTC_PKT_ERROR_COUNT_INCR(target, GET_HTC_PKT_Q_FAIL); 1629 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n")); 1630 return QDF_STATUS_E_INVAL; 1631 } 1632 1633 if ((pPacket->Endpoint >= ENDPOINT_MAX) || 1634 (pPacket->Endpoint <= ENDPOINT_UNUSED)) { 1635 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1636 ("%s endpoint is invalid\n", __func__)); 1637 AR_DEBUG_ASSERT(0); 1638 return QDF_STATUS_E_INVAL; 1639 } 1640 pEndpoint = &target->endpoint[pPacket->Endpoint]; 1641 1642 if (!pEndpoint->service_id) { 1643 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("%s service_id is invalid\n", 1644 __func__)); 1645 return QDF_STATUS_E_INVAL; 1646 } 1647 1648 #ifdef HTC_EP_STAT_PROFILING 1649 LOCK_HTC_TX(target); 1650 INC_HTC_EP_STAT(pEndpoint, TxPosted, 1); 1651 UNLOCK_HTC_TX(target); 1652 #endif 1653 1654 /* provide room in each packet's netbuf for the HTC frame header */ 1655 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 1656 AR_DEBUG_ASSERT(netbuf); 1657 if (!netbuf) 1658 return QDF_STATUS_E_INVAL; 1659 1660 qdf_nbuf_push_head(netbuf, sizeof(HTC_FRAME_HDR)); 1661 pPacket->PktInfo.AsTx.Flags |= 1662 HTC_TX_PACKET_FLAG_HTC_HEADER_IN_NETBUF_DATA; 1663 /* setup HTC frame header */ 1664 htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0); 1665 AR_DEBUG_ASSERT(htc_hdr); 1666 if (!htc_hdr) 1667 return QDF_STATUS_E_INVAL; 1668 1669 HTC_WRITE32(htc_hdr, 1670 SM(pPacket->ActualLength, 1671 HTC_FRAME_HDR_PAYLOADLEN) | 1672 SM(pPacket->Endpoint, 1673 HTC_FRAME_HDR_ENDPOINTID)); 1674 LOCK_HTC_TX(target); 1675 1676 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo; 1677 pEndpoint->SeqNo++; 1678 1679 HTC_WRITE32(((uint32_t *)htc_hdr) + 1, 1680 SM(pPacket->PktInfo.AsTx.SeqNo, 1681 HTC_FRAME_HDR_CONTROLBYTES1)); 1682 1683 UNLOCK_HTC_TX(target); 1684 1685 /* 1686 * For flow control enabled endpoints mapping is done in 1687 * htc_issue_packets and for non flow control enabled endpoints 1688 * its done here. 1689 */ 1690 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { 1691 pPacket->PktInfo.AsTx.Flags |= HTC_TX_PACKET_FLAG_FIXUP_NETBUF; 1692 status = qdf_nbuf_map(target->osdev, 1693 GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket), 1694 QDF_DMA_TO_DEVICE); 1695 if (status != QDF_STATUS_SUCCESS) { 1696 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 1697 ("%s: nbuf map failed, endpoint %pK, seq_no. %d\n", 1698 __func__, pEndpoint, pEndpoint->SeqNo)); 1699 return status; 1700 } 1701 } 1702 1703 INIT_HTC_PACKET_QUEUE_AND_ADD(&pPktQueue, pPacket); 1704 #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED 1705 if (!htc_send_pkts_sched_check(HTCHandle, pEndpoint->Id)) 1706 htc_send_pkts_sched_queue(HTCHandle, &pPktQueue, pEndpoint->Id); 1707 else 1708 htc_try_send(target, pEndpoint, &pPktQueue); 1709 #else 1710 htc_try_send(target, pEndpoint, &pPktQueue); 1711 #endif 1712 1713 /* do completion on any packets that couldn't get in */ 1714 while (!HTC_QUEUE_EMPTY(&pPktQueue)) { 1715 pPacket = htc_packet_dequeue(&pPktQueue); 1716 1717 if (HTC_STOPPING(target)) 1718 pPacket->Status = QDF_STATUS_E_CANCELED; 1719 else 1720 pPacket->Status = QDF_STATUS_E_RESOURCES; 1721 1722 send_packet_completion(target, pPacket); 1723 } 1724 1725 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-__htc_send_pkt\n")); 1726 1727 return QDF_STATUS_SUCCESS; 1728 } 1729 1730 /* HTC API - htc_send_pkt */ 1731 QDF_STATUS htc_send_pkt(HTC_HANDLE htc_handle, HTC_PACKET *htc_packet) 1732 { 1733 if (!htc_handle) { 1734 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 1735 ("%s: HTCHandle is NULL \n", __func__)); 1736 return QDF_STATUS_E_FAILURE; 1737 } 1738 1739 if (!htc_packet) { 1740 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 1741 ("%s: pPacket is NULL \n", __func__)); 1742 return QDF_STATUS_E_FAILURE; 1743 } 1744 1745 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1746 ("+-htc_send_pkt: Enter endPointId: %d, buffer: %pK, length: %d\n", 1747 htc_packet->Endpoint, htc_packet->pBuffer, 1748 htc_packet->ActualLength)); 1749 return __htc_send_pkt(htc_handle, htc_packet); 1750 } 1751 qdf_export_symbol(htc_send_pkt); 1752 1753 #ifdef ATH_11AC_TXCOMPACT 1754 /** 1755 * htc_send_data_pkt() - send single data packet on an endpoint 1756 * @HTCHandle: pointer to HTC handle 1757 * @netbuf: network buffer containing the data to be sent 1758 * @ActualLength: length of data that needs to be transmitted 1759 * 1760 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error 1761 */ 1762 QDF_STATUS htc_send_data_pkt(HTC_HANDLE htc_hdl, qdf_nbuf_t netbuf, int ep_id, 1763 int actual_length) 1764 { 1765 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl); 1766 HTC_ENDPOINT *pEndpoint; 1767 HTC_FRAME_HDR *p_htc_hdr; 1768 QDF_STATUS status = QDF_STATUS_SUCCESS; 1769 int tx_resources; 1770 uint32_t data_attr = 0; 1771 int htc_payload_len = actual_length; 1772 1773 pEndpoint = &target->endpoint[ep_id]; 1774 1775 tx_resources = hif_get_free_queue_number(target->hif_dev, 1776 pEndpoint->UL_PipeID); 1777 1778 if (tx_resources < HTC_DATA_RESOURCE_THRS) { 1779 if (pEndpoint->ul_is_polled) { 1780 hif_send_complete_check(pEndpoint->target->hif_dev, 1781 pEndpoint->UL_PipeID, 1); 1782 tx_resources = 1783 hif_get_free_queue_number(target->hif_dev, 1784 pEndpoint->UL_PipeID); 1785 } 1786 if (tx_resources < HTC_DATA_MINDESC_PERPACKET) 1787 return QDF_STATUS_E_FAILURE; 1788 } 1789 1790 if (hif_pm_runtime_get(target->hif_dev)) 1791 return QDF_STATUS_E_FAILURE; 1792 1793 p_htc_hdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0); 1794 AR_DEBUG_ASSERT(p_htc_hdr); 1795 1796 data_attr = qdf_nbuf_data_attr_get(netbuf); 1797 1798 if (target->htc_hdr_length_check) 1799 htc_payload_len = actual_length - HTC_HEADER_LEN; 1800 1801 HTC_WRITE32(p_htc_hdr, SM(htc_payload_len, HTC_FRAME_HDR_PAYLOADLEN) 1802 | SM(ep_id, HTC_FRAME_HDR_ENDPOINTID)); 1803 /* 1804 * If the HIF pipe for the data endpoint is polled rather than 1805 * interrupt-driven, this is a good point to check whether any 1806 * data previously sent through the HIF pipe have finished being 1807 * sent. 1808 * Since this may result in callbacks to htc_tx_completion_handler, 1809 * which can take the HTC tx lock, make the hif_send_complete_check 1810 * call before acquiring the HTC tx lock. 1811 * Call hif_send_complete_check directly, rather than calling 1812 * htc_send_complete_check, and call the PollTimerStart separately 1813 * after calling hif_send_head, so the timer will be started to 1814 * check for completion of the new outstanding download (in the 1815 * unexpected event that other polling calls don't catch it). 1816 */ 1817 1818 LOCK_HTC_TX(target); 1819 1820 HTC_WRITE32(((uint32_t *)p_htc_hdr) + 1, 1821 SM(pEndpoint->SeqNo, HTC_FRAME_HDR_CONTROLBYTES1)); 1822 1823 pEndpoint->SeqNo++; 1824 1825 QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC); 1826 DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD, 1827 QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf), 1828 sizeof(qdf_nbuf_data(netbuf)), QDF_TX)); 1829 status = hif_send_head(target->hif_dev, 1830 pEndpoint->UL_PipeID, 1831 pEndpoint->Id, actual_length, netbuf, data_attr); 1832 1833 UNLOCK_HTC_TX(target); 1834 return status; 1835 } 1836 #else /*ATH_11AC_TXCOMPACT */ 1837 1838 /** 1839 * htc_send_data_pkt() - htc_send_data_pkt 1840 * @HTCHandle: pointer to HTC handle 1841 * @pPacket: pointer to HTC_PACKET 1842 * @more_data: indicates whether more data is to follow 1843 * 1844 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error 1845 */ 1846 QDF_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket, 1847 uint8_t more_data) 1848 { 1849 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 1850 HTC_ENDPOINT *pEndpoint; 1851 HTC_FRAME_HDR *pHtcHdr; 1852 HTC_PACKET_QUEUE sendQueue; 1853 qdf_nbuf_t netbuf = NULL; 1854 int tx_resources; 1855 QDF_STATUS status = QDF_STATUS_SUCCESS; 1856 uint32_t data_attr = 0; 1857 bool used_extra_tx_credit = false; 1858 1859 if (pPacket) { 1860 if ((pPacket->Endpoint >= ENDPOINT_MAX) || 1861 (pPacket->Endpoint <= ENDPOINT_UNUSED)) { 1862 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 1863 ("%s endpoint is invalid\n", __func__)); 1864 AR_DEBUG_ASSERT(0); 1865 return QDF_STATUS_E_INVAL; 1866 } 1867 pEndpoint = &target->endpoint[pPacket->Endpoint]; 1868 1869 /* add HTC_FRAME_HDR in the initial fragment */ 1870 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 1871 pHtcHdr = (HTC_FRAME_HDR *) qdf_nbuf_get_frag_vaddr(netbuf, 0); 1872 AR_DEBUG_ASSERT(pHtcHdr); 1873 1874 HTC_WRITE32(pHtcHdr, 1875 SM(pPacket->ActualLength, 1876 HTC_FRAME_HDR_PAYLOADLEN) | 1877 SM(pPacket->PktInfo.AsTx.SendFlags, 1878 HTC_FRAME_HDR_FLAGS) | 1879 SM(pPacket->Endpoint, 1880 HTC_FRAME_HDR_ENDPOINTID)); 1881 /* 1882 * If the HIF pipe for the data endpoint is polled rather than 1883 * interrupt-driven, this is a good point to check whether any 1884 * data previously sent through the HIF pipe have finished being 1885 * sent. Since this may result in callbacks to 1886 * htc_tx_completion_handler, which can take the HTC tx lock, 1887 * make the hif_send_complete_check call before acquiring the 1888 * HTC tx lock. 1889 * Call hif_send_complete_check directly, rather than calling 1890 * htc_send_complete_check, and call the PollTimerStart 1891 * separately after calling hif_send_head, so the timer will be 1892 * started to check for completion of the new outstanding 1893 * download (in the unexpected event that other polling calls 1894 * don't catch it). 1895 */ 1896 if (pEndpoint->ul_is_polled) { 1897 htc_send_complete_poll_timer_stop(pEndpoint); 1898 hif_send_complete_check(pEndpoint->target->hif_dev, 1899 pEndpoint->UL_PipeID, 0); 1900 } 1901 1902 LOCK_HTC_TX(target); 1903 1904 pPacket->PktInfo.AsTx.SeqNo = pEndpoint->SeqNo; 1905 pEndpoint->SeqNo++; 1906 1907 HTC_WRITE32(((uint32_t *) pHtcHdr) + 1, 1908 SM(pPacket->PktInfo.AsTx.SeqNo, 1909 HTC_FRAME_HDR_CONTROLBYTES1)); 1910 1911 /* append new packet to pEndpoint->TxQueue */ 1912 HTC_PACKET_ENQUEUE(&pEndpoint->TxQueue, pPacket); 1913 if (HTC_TX_BUNDLE_ENABLED(target) && (more_data)) { 1914 UNLOCK_HTC_TX(target); 1915 return QDF_STATUS_SUCCESS; 1916 } 1917 1918 QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_HTC); 1919 DPTRACE(qdf_dp_trace(netbuf, QDF_DP_TRACE_HTC_PACKET_PTR_RECORD, 1920 QDF_TRACE_DEFAULT_PDEV_ID, qdf_nbuf_data_addr(netbuf), 1921 sizeof(qdf_nbuf_data(netbuf)), QDF_TX)); 1922 } else { 1923 LOCK_HTC_TX(target); 1924 pEndpoint = &target->endpoint[1]; 1925 } 1926 1927 /* increment tx processing count on entry */ 1928 qdf_atomic_inc(&pEndpoint->TxProcessCount); 1929 if (qdf_atomic_read(&pEndpoint->TxProcessCount) > 1) { 1930 /* 1931 * Another thread or task is draining the TX queues on this 1932 * endpoint. That thread will reset the tx processing count when 1933 * the queue is drained. 1934 */ 1935 qdf_atomic_dec(&pEndpoint->TxProcessCount); 1936 UNLOCK_HTC_TX(target); 1937 return QDF_STATUS_SUCCESS; 1938 } 1939 1940 /***** beyond this point only 1 thread may enter ******/ 1941 1942 INIT_HTC_PACKET_QUEUE(&sendQueue); 1943 if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { 1944 #if DEBUG_CREDIT 1945 int cred = pEndpoint->TxCredits; 1946 #endif 1947 get_htc_send_packets_credit_based(target, pEndpoint, 1948 &sendQueue); 1949 #if DEBUG_CREDIT 1950 if (ep_debug_mask & (1 << pEndpoint->Id)) { 1951 if (cred - pEndpoint->TxCredits > 0) { 1952 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 1953 (" <HTC> Decrease EP%d %d - %d = %d credits.\n", 1954 pEndpoint->Id, cred, 1955 cred - pEndpoint->TxCredits, 1956 pEndpoint->TxCredits)); 1957 } 1958 } 1959 #endif 1960 UNLOCK_HTC_TX(target); 1961 } 1962 1963 else if (HTC_TX_BUNDLE_ENABLED(target)) { 1964 if (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB) { 1965 if (hif_get_free_queue_number(target->hif_dev, 1966 pEndpoint->UL_PipeID)) 1967 /* 1968 * Header and payload belongs to the different 1969 * fragments and consume 2 resource for one HTC 1970 * package but USB combine into one transfer. 1971 */ 1972 get_htc_send_packets(target, pEndpoint, 1973 &sendQueue, 1974 HTC_MAX_MSG_PER_BUNDLE_TX 1975 * 2); 1976 } else { 1977 /* Dequeue max packets from endpoint tx queue */ 1978 get_htc_send_packets(target, pEndpoint, &sendQueue, 1979 HTC_MAX_TX_BUNDLE_SEND_LIMIT); 1980 } 1981 UNLOCK_HTC_TX(target); 1982 } else { 1983 /* 1984 * Now drain the endpoint TX queue for transmission as long as 1985 * we have enough transmit resources 1986 */ 1987 tx_resources = 1988 hif_get_free_queue_number(target->hif_dev, 1989 pEndpoint->UL_PipeID); 1990 get_htc_send_packets(target, pEndpoint, &sendQueue, 1991 tx_resources); 1992 UNLOCK_HTC_TX(target); 1993 } 1994 1995 /* send what we can */ 1996 while (true) { 1997 if (HTC_TX_BUNDLE_ENABLED(target) && 1998 (HTC_PACKET_QUEUE_DEPTH(&sendQueue) >= 1999 HTC_MIN_MSG_PER_BUNDLE) && 2000 (hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO || 2001 hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_USB)) { 2002 if (pEndpoint->EpCallBacks.ep_padding_credit_update) { 2003 if (htc_tx_pad_credit_avail(pEndpoint) < 1) { 2004 status = QDF_STATUS_E_RESOURCES; 2005 /* put the sendQueue back at the front 2006 * of pEndpoint->TxQueue 2007 */ 2008 LOCK_HTC_TX(target); 2009 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD( 2010 &pEndpoint->TxQueue, 2011 &sendQueue); 2012 UNLOCK_HTC_TX(target); 2013 break; 2014 } 2015 } 2016 htc_issue_packets_bundle(target, pEndpoint, &sendQueue); 2017 } 2018 if (pEndpoint->EpCallBacks.ep_padding_credit_update) { 2019 if (htc_tx_pad_credit_avail(pEndpoint) < 1) { 2020 status = QDF_STATUS_E_RESOURCES; 2021 /* put the sendQueue back at the front 2022 * of pEndpoint->TxQueue 2023 */ 2024 LOCK_HTC_TX(target); 2025 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD( 2026 &pEndpoint->TxQueue, 2027 &sendQueue); 2028 UNLOCK_HTC_TX(target); 2029 break; 2030 } 2031 } 2032 pPacket = htc_packet_dequeue(&sendQueue); 2033 if (!pPacket) 2034 break; 2035 netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket); 2036 pHtcHdr = (HTC_FRAME_HDR *)qdf_nbuf_get_frag_vaddr(netbuf, 0); 2037 2038 LOCK_HTC_TX(target); 2039 /* store in look up queue to match completions */ 2040 HTC_PACKET_ENQUEUE(&pEndpoint->TxLookupQueue, pPacket); 2041 INC_HTC_EP_STAT(pEndpoint, TxIssued, 1); 2042 pEndpoint->ul_outstanding_cnt++; 2043 UNLOCK_HTC_TX(target); 2044 2045 used_extra_tx_credit = 2046 htc_handle_extra_tx_credit(pEndpoint, pPacket, 2047 (uint8_t *)pHtcHdr, 2048 NULL, 2049 pPacket->ActualLength 2050 + HTC_HDR_LENGTH); 2051 2052 status = hif_send_head(target->hif_dev, 2053 pEndpoint->UL_PipeID, 2054 pEndpoint->Id, 2055 HTC_HDR_LENGTH + pPacket->ActualLength, 2056 netbuf, data_attr); 2057 if (status != QDF_STATUS_SUCCESS) { 2058 if (pEndpoint->EpCallBacks.ep_padding_credit_update) { 2059 if (used_extra_tx_credit) { 2060 pEndpoint->EpCallBacks. 2061 ep_padding_credit_update 2062 (pEndpoint->EpCallBacks.pContext, 1); 2063 } 2064 } 2065 } 2066 #if DEBUG_BUNDLE 2067 qdf_print(" Send single EP%d buffer size:0x%x, total:0x%x.", 2068 pEndpoint->Id, 2069 pEndpoint->TxCreditSize, 2070 HTC_HDR_LENGTH + pPacket->ActualLength); 2071 #endif 2072 2073 htc_issue_tx_bundle_stats_inc(target); 2074 2075 if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) { 2076 LOCK_HTC_TX(target); 2077 pEndpoint->ul_outstanding_cnt--; 2078 /* remove this packet from the tx completion queue */ 2079 HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacket); 2080 2081 /* 2082 * Don't bother reclaiming credits - HTC flow control 2083 * is not applicable to tx data. 2084 * In LL systems, there is no download flow control, 2085 * since there's virtually no download delay. 2086 * In HL systems, the txrx SW explicitly performs the 2087 * tx flow control. 2088 */ 2089 /* pEndpoint->TxCredits += 2090 * pPacket->PktInfo.AsTx.CreditsUsed; 2091 */ 2092 2093 /* put this frame back at the front of the sendQueue */ 2094 HTC_PACKET_ENQUEUE_TO_HEAD(&sendQueue, pPacket); 2095 2096 /* put the sendQueue back at the front of 2097 * pEndpoint->TxQueue 2098 */ 2099 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue, 2100 &sendQueue); 2101 UNLOCK_HTC_TX(target); 2102 break; /* still need to reset TxProcessCount */ 2103 } 2104 } 2105 /* done with this endpoint, we can clear the count */ 2106 qdf_atomic_init(&pEndpoint->TxProcessCount); 2107 2108 if (pEndpoint->ul_is_polled) { 2109 /* 2110 * Start a cleanup timer to poll for download completion. 2111 * The download completion should be noticed promptly from 2112 * other polling calls, but the timer provides a safety net 2113 * in case other polling calls don't occur as expected. 2114 */ 2115 htc_send_complete_poll_timer_start(pEndpoint); 2116 } 2117 2118 return status; 2119 } 2120 #endif /*ATH_11AC_TXCOMPACT */ 2121 qdf_export_symbol(htc_send_data_pkt); 2122 2123 /* 2124 * In the adapted HIF layer, qdf_nbuf_t are passed between HIF and HTC, 2125 * since upper layers expects HTC_PACKET containers we use the completed netbuf 2126 * and lookup its corresponding HTC packet buffer from a lookup list. 2127 * This is extra overhead that can be fixed by re-aligning HIF interfaces 2128 * with HTC. 2129 * 2130 */ 2131 static HTC_PACKET *htc_lookup_tx_packet(HTC_TARGET *target, 2132 HTC_ENDPOINT *pEndpoint, 2133 qdf_nbuf_t netbuf) 2134 { 2135 HTC_PACKET *pPacket = NULL; 2136 HTC_PACKET *pFoundPacket = NULL; 2137 HTC_PACKET_QUEUE lookupQueue; 2138 2139 INIT_HTC_PACKET_QUEUE(&lookupQueue); 2140 LOCK_HTC_EP_TX_LOOKUP(pEndpoint); 2141 2142 LOCK_HTC_TX(target); 2143 2144 /* mark that HIF has indicated the send complete for another packet */ 2145 pEndpoint->ul_outstanding_cnt--; 2146 2147 /* Dequeue first packet directly because of in-order completion */ 2148 pPacket = htc_packet_dequeue(&pEndpoint->TxLookupQueue); 2149 if (qdf_unlikely(!pPacket)) { 2150 UNLOCK_HTC_TX(target); 2151 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint); 2152 return NULL; 2153 } 2154 if (netbuf == (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) { 2155 UNLOCK_HTC_TX(target); 2156 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint); 2157 return pPacket; 2158 } 2159 HTC_PACKET_ENQUEUE(&lookupQueue, pPacket); 2160 2161 /* 2162 * Move TX lookup queue to temp queue because most of packets that are 2163 * not index 0 are not top 10 packets. 2164 */ 2165 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&lookupQueue, 2166 &pEndpoint->TxLookupQueue); 2167 2168 ITERATE_OVER_LIST_ALLOW_REMOVE(&lookupQueue.QueueHead, pPacket, 2169 HTC_PACKET, ListLink) { 2170 2171 if (!pPacket) { 2172 pFoundPacket = pPacket; 2173 break; 2174 } 2175 /* check for removal */ 2176 if (netbuf == 2177 (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket)) { 2178 /* found it */ 2179 HTC_PACKET_REMOVE(&lookupQueue, pPacket); 2180 pFoundPacket = pPacket; 2181 break; 2182 } 2183 2184 } 2185 ITERATE_END; 2186 2187 HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxLookupQueue, 2188 &lookupQueue); 2189 UNLOCK_HTC_TX(target); 2190 UNLOCK_HTC_EP_TX_LOOKUP(pEndpoint); 2191 2192 return pFoundPacket; 2193 } 2194 2195 /** 2196 * htc_tx_completion_handler() - htc tx completion handler 2197 * @Context: pointer to HTC_TARGET structure 2198 * @netbuf: pointer to netbuf for which completion handler is being called 2199 * @EpID: end point Id on which the packet was sent 2200 * @toeplitz_hash_result: toeplitz hash result 2201 * 2202 * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error 2203 */ 2204 QDF_STATUS htc_tx_completion_handler(void *Context, 2205 qdf_nbuf_t netbuf, unsigned int EpID, 2206 uint32_t toeplitz_hash_result) 2207 { 2208 HTC_TARGET *target = (HTC_TARGET *) Context; 2209 HTC_ENDPOINT *pEndpoint; 2210 HTC_PACKET *pPacket; 2211 #ifdef USB_HIF_SINGLE_PIPE_DATA_SCHED 2212 HTC_ENDPOINT_ID eid[DATA_EP_SIZE] = { ENDPOINT_5, ENDPOINT_4, 2213 ENDPOINT_2, ENDPOINT_3 }; 2214 int epidIdx; 2215 uint16_t resourcesThresh[DATA_EP_SIZE]; /* urb resources */ 2216 uint16_t resources; 2217 uint16_t resourcesMax; 2218 #endif 2219 2220 pEndpoint = &target->endpoint[EpID]; 2221 target->TX_comp_cnt++; 2222 2223 do { 2224 pPacket = htc_lookup_tx_packet(target, pEndpoint, netbuf); 2225 if (!pPacket) { 2226 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 2227 ("HTC TX lookup failed!\n")); 2228 /* may have already been flushed and freed */ 2229 netbuf = NULL; 2230 break; 2231 } 2232 if (pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_AUTO_PM) 2233 hif_pm_runtime_put(target->hif_dev); 2234 2235 if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) { 2236 HTC_PACKET *pPacketTemp; 2237 HTC_PACKET_QUEUE *pQueueSave = 2238 (HTC_PACKET_QUEUE *) pPacket->pContext; 2239 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQueueSave, 2240 pPacketTemp) { 2241 pPacket->Status = QDF_STATUS_SUCCESS; 2242 send_packet_completion(target, pPacketTemp); 2243 } 2244 HTC_PACKET_QUEUE_ITERATE_END; 2245 free_htc_bundle_packet(target, pPacket); 2246 2247 if (hif_get_bus_type(target->hif_dev) == 2248 QDF_BUS_TYPE_USB) { 2249 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) 2250 htc_try_send(target, pEndpoint, NULL); 2251 } 2252 2253 return QDF_STATUS_SUCCESS; 2254 } 2255 /* will be giving this buffer back to upper layers */ 2256 netbuf = NULL; 2257 pPacket->Status = QDF_STATUS_SUCCESS; 2258 send_packet_completion(target, pPacket); 2259 2260 } while (false); 2261 2262 if (!IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { 2263 /* note: when using TX credit flow, the re-checking of queues 2264 * happens when credits flow back from the target. In the non-TX 2265 * credit case, we recheck after the packet completes 2266 */ 2267 if ((qdf_atomic_read(&pEndpoint->TxProcessCount) == 0) || 2268 (!pEndpoint->async_update)) { 2269 htc_try_send(target, pEndpoint, NULL); 2270 } 2271 } 2272 2273 return QDF_STATUS_SUCCESS; 2274 } 2275 2276 #ifdef WLAN_FEATURE_FASTPATH 2277 /** 2278 * htc_ctrl_msg_cmpl(): checks for tx completion for the endpoint specified 2279 * @HTC_HANDLE : pointer to the htc target context 2280 * @htc_ep_id : end point id 2281 * 2282 * checks HTC tx completion 2283 * 2284 * Return: none 2285 */ 2286 void htc_ctrl_msg_cmpl(HTC_HANDLE htc_pdev, HTC_ENDPOINT_ID htc_ep_id) 2287 { 2288 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_pdev); 2289 HTC_ENDPOINT *pendpoint = &target->endpoint[htc_ep_id]; 2290 2291 htc_send_complete_check(pendpoint, 1); 2292 } 2293 qdf_export_symbol(htc_ctrl_msg_cmpl); 2294 #endif 2295 2296 /* callback when TX resources become available */ 2297 void htc_tx_resource_avail_handler(void *context, uint8_t pipeID) 2298 { 2299 int i; 2300 HTC_TARGET *target = (HTC_TARGET *) context; 2301 HTC_ENDPOINT *pEndpoint = NULL; 2302 2303 for (i = 0; i < ENDPOINT_MAX; i++) { 2304 pEndpoint = &target->endpoint[i]; 2305 if (pEndpoint->service_id != 0) { 2306 if (pEndpoint->UL_PipeID == pipeID) 2307 break; 2308 } 2309 } 2310 2311 if (i >= ENDPOINT_MAX) { 2312 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 2313 ("Invalid pipe indicated for TX resource avail : %d!\n", 2314 pipeID)); 2315 return; 2316 } 2317 2318 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 2319 ("HIF indicated more resources for pipe:%d\n", 2320 pipeID)); 2321 2322 htc_try_send(target, pEndpoint, NULL); 2323 } 2324 2325 #ifdef FEATURE_RUNTIME_PM 2326 /** 2327 * htc_kick_queues(): resumes tx transactions of suspended endpoints 2328 * @context: pointer to the htc target context 2329 * 2330 * Iterates through the enpoints and provides a context to empty queues 2331 * int the hif layer when they are stalled due to runtime suspend. 2332 * 2333 * Return: none 2334 */ 2335 void htc_kick_queues(void *context) 2336 { 2337 int i; 2338 HTC_TARGET *target = (HTC_TARGET *)context; 2339 HTC_ENDPOINT *endpoint = NULL; 2340 2341 for (i = 0; i < ENDPOINT_MAX; i++) { 2342 endpoint = &target->endpoint[i]; 2343 2344 if (endpoint->service_id == 0) 2345 continue; 2346 2347 if (endpoint->EpCallBacks.ep_resume_tx_queue) 2348 endpoint->EpCallBacks.ep_resume_tx_queue( 2349 endpoint->EpCallBacks.pContext); 2350 2351 htc_try_send(target, endpoint, NULL); 2352 } 2353 2354 hif_fastpath_resume(target->hif_dev); 2355 } 2356 #endif 2357 2358 /* flush endpoint TX queue */ 2359 void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, 2360 HTC_TX_TAG Tag) 2361 { 2362 HTC_PACKET *pPacket; 2363 2364 LOCK_HTC_TX(target); 2365 while (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) { 2366 pPacket = htc_packet_dequeue(&pEndpoint->TxQueue); 2367 2368 if (pPacket) { 2369 /* let the sender know the packet was not delivered */ 2370 pPacket->Status = QDF_STATUS_E_CANCELED; 2371 send_packet_completion(target, pPacket); 2372 } 2373 } 2374 UNLOCK_HTC_TX(target); 2375 } 2376 2377 /* flush pending entries in endpoint TX Lookup queue */ 2378 void htc_flush_endpoint_txlookupQ(HTC_TARGET *target, 2379 HTC_ENDPOINT_ID endpoint_id, 2380 bool call_ep_callback) 2381 { 2382 HTC_PACKET *packet; 2383 HTC_ENDPOINT *endpoint; 2384 2385 endpoint = &target->endpoint[endpoint_id]; 2386 2387 if (!endpoint && endpoint->service_id == 0) 2388 return; 2389 2390 LOCK_HTC_TX(target); 2391 while (HTC_PACKET_QUEUE_DEPTH(&endpoint->TxLookupQueue)) { 2392 packet = htc_packet_dequeue(&endpoint->TxLookupQueue); 2393 2394 if (packet) { 2395 if (call_ep_callback == true) { 2396 packet->Status = QDF_STATUS_E_CANCELED; 2397 send_packet_completion(target, packet); 2398 } else { 2399 qdf_mem_free(packet); 2400 } 2401 } 2402 } 2403 UNLOCK_HTC_TX(target); 2404 } 2405 2406 /* HTC API to flush an endpoint's TX queue*/ 2407 void htc_flush_endpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, 2408 HTC_TX_TAG Tag) 2409 { 2410 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 2411 HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint]; 2412 2413 if (pEndpoint->service_id == 0) { 2414 AR_DEBUG_ASSERT(false); 2415 /* not in use.. */ 2416 return; 2417 } 2418 2419 htc_flush_endpoint_tx(target, pEndpoint, Tag); 2420 } 2421 2422 /* HTC API to indicate activity to the credit distribution function */ 2423 void htc_indicate_activity_change(HTC_HANDLE HTCHandle, 2424 HTC_ENDPOINT_ID Endpoint, bool Active) 2425 { 2426 /* TODO */ 2427 } 2428 2429 bool htc_is_endpoint_active(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint) 2430 { 2431 return true; 2432 } 2433 2434 void htc_set_nodrop_pkt(HTC_HANDLE HTCHandle, A_BOOL isNodropPkt) 2435 { 2436 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 2437 2438 target->is_nodrop_pkt = isNodropPkt; 2439 } 2440 2441 void htc_enable_hdr_length_check(HTC_HANDLE htc_hdl, bool htc_hdr_length_check) 2442 { 2443 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_hdl); 2444 2445 target->htc_hdr_length_check = htc_hdr_length_check; 2446 } 2447 2448 /** 2449 * htc_process_credit_rpt() - process credit report, call distribution function 2450 * @target: pointer to HTC_TARGET 2451 * @pRpt: pointer to HTC_CREDIT_REPORT 2452 * @NumEntries: number of entries in credit report 2453 * @FromEndpoint: endpoint for which credit report is received 2454 * 2455 * Return: A_OK for success or an appropriate A_STATUS error 2456 */ 2457 void htc_process_credit_rpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, 2458 int NumEntries, HTC_ENDPOINT_ID FromEndpoint) 2459 { 2460 int i; 2461 HTC_ENDPOINT *pEndpoint; 2462 int totalCredits = 0; 2463 uint8_t rpt_credits, rpt_ep_id; 2464 2465 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 2466 ("+htc_process_credit_rpt, Credit Report Entries:%d\n", 2467 NumEntries)); 2468 2469 /* lock out TX while we update credits */ 2470 LOCK_HTC_TX(target); 2471 2472 for (i = 0; i < NumEntries; i++, pRpt++) { 2473 2474 rpt_ep_id = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, ENDPOINTID); 2475 2476 if (rpt_ep_id >= ENDPOINT_MAX) { 2477 AR_DEBUG_ASSERT(false); 2478 break; 2479 } 2480 2481 rpt_credits = HTC_GET_FIELD(pRpt, HTC_CREDIT_REPORT, CREDITS); 2482 2483 pEndpoint = &target->endpoint[rpt_ep_id]; 2484 #if DEBUG_CREDIT 2485 if (ep_debug_mask & (1 << pEndpoint->Id)) { 2486 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 2487 (" <HTC> Increase EP%d %d + %d = %d credits\n", 2488 rpt_ep_id, pEndpoint->TxCredits, 2489 rpt_credits, 2490 pEndpoint->TxCredits + rpt_credits)); 2491 } 2492 #endif 2493 2494 #ifdef HTC_EP_STAT_PROFILING 2495 2496 INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1); 2497 INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, rpt_credits); 2498 2499 if (FromEndpoint == rpt_ep_id) { 2500 /* this credit report arrived on the same endpoint 2501 * indicating it arrived in an RX packet 2502 */ 2503 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, 2504 rpt_credits); 2505 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1); 2506 } else if (FromEndpoint == ENDPOINT_0) { 2507 /* this credit arrived on endpoint 0 as a NULL msg */ 2508 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, 2509 rpt_credits); 2510 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1); 2511 } else { 2512 /* arrived on another endpoint */ 2513 INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, 2514 rpt_credits); 2515 INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1); 2516 } 2517 2518 #endif 2519 2520 if (pEndpoint->service_id == WMI_CONTROL_SVC) { 2521 htc_credit_record(HTC_PROCESS_CREDIT_REPORT, 2522 pEndpoint->TxCredits + rpt_credits, 2523 HTC_PACKET_QUEUE_DEPTH(&pEndpoint-> 2524 TxQueue)); 2525 } 2526 2527 pEndpoint->TxCredits += rpt_credits; 2528 2529 if (pEndpoint->TxCredits 2530 && HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)) { 2531 UNLOCK_HTC_TX(target); 2532 #ifdef ATH_11AC_TXCOMPACT 2533 htc_try_send(target, pEndpoint, NULL); 2534 #else 2535 if (pEndpoint->service_id == HTT_DATA_MSG_SVC) 2536 htc_send_data_pkt((HTC_HANDLE)target, NULL, 0); 2537 else 2538 htc_try_send(target, pEndpoint, NULL); 2539 #endif 2540 LOCK_HTC_TX(target); 2541 } 2542 totalCredits += rpt_credits; 2543 } 2544 2545 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, 2546 (" Report indicated %d credits to distribute\n", 2547 totalCredits)); 2548 2549 UNLOCK_HTC_TX(target); 2550 2551 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-htc_process_credit_rpt\n")); 2552 } 2553 2554 /* function to fetch stats from htc layer*/ 2555 struct ol_ath_htc_stats *ieee80211_ioctl_get_htc_stats(HTC_HANDLE HTCHandle) 2556 { 2557 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); 2558 2559 return &(target->htc_pkt_stats); 2560 } 2561