A_STATUS HTCStart(HTC_HANDLE HTCHandle) { adf_nbuf_t netbuf; A_STATUS status = A_OK; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_SETUP_COMPLETE_MSG *SetupComp; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); do { HTCConfigTargetHIFPipe(HTCHandle); #ifdef HTC_HOST_CREDIT_DIST adf_os_assert(target->InitCredits != NULL); adf_os_assert(target->EpCreditDistributionListHead != NULL); adf_os_assert(target->EpCreditDistributionListHead->pNext != NULL); /* call init credits callback to do the distribution , * NOTE: the first entry in the distribution list is ENDPOINT_0, so * we pass the start of the list after this one. */ target->InitCredits(target->pCredDistContext, target->EpCreditDistributionListHead->pNext, target->TargetCredits); #if 1 adf_os_timer_init(target->os_handle, &target->host_htc_credit_debug_timer, host_htc_credit_show, target); adf_os_timer_start(&target->host_htc_credit_debug_timer, 10000); #endif #endif /* allocate a buffer to send */ //netbuf = adf_nbuf_alloc(anet, sizeof(HTC_SETUP_COMPLETE_MSG), HTC_HDR_LENGTH, 0); netbuf = adf_nbuf_alloc(50, HTC_HDR_LENGTH, 0); if (netbuf == ADF_NBUF_NULL) { status = A_NO_MEMORY; break; } /* assemble setup complete message */ SetupComp = (HTC_SETUP_COMPLETE_MSG *)adf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_MSG)); SetupComp->MessageID = adf_os_htons(HTC_MSG_SETUP_COMPLETE_ID); /* assemble the HTC header and send to HIF layer */ status = HTCIssueSend(target, ADF_NBUF_NULL, netbuf, 0, sizeof(HTC_SETUP_COMPLETE_MSG), ENDPOINT0); if (A_FAILED(status)) { break; } } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); return status; }
A_STATUS ConfigPipeCredits(HTC_TARGET *target, a_uint8_t pipeID, a_uint8_t credits) { A_STATUS status = A_OK; adf_nbuf_t netbuf; HTC_CONFIG_PIPE_MSG *CfgPipeCdt; do { /* allocate a buffer to send */ //netbuf = adf_nbuf_alloc(anet, sizeof(HTC_CONFIG_PIPE_MSG), HTC_HDR_LENGTH, 0); netbuf = adf_nbuf_alloc(50, HTC_HDR_LENGTH, 0); if (netbuf == ADF_NBUF_NULL) { status = A_NO_MEMORY; break; } /* assemble config pipe message */ CfgPipeCdt = (HTC_CONFIG_PIPE_MSG *)adf_nbuf_put_tail(netbuf, sizeof(HTC_CONFIG_PIPE_MSG)); CfgPipeCdt->MessageID = adf_os_htons(HTC_MSG_CONFIG_PIPE_ID); CfgPipeCdt->PipeID = pipeID; CfgPipeCdt->CreditCount = credits; /* assemble the HTC header and send to HIF layer */ #ifndef MAGPIE_SINGLE_CPU_CASE htc_spin_prep(&target->spin); #endif status = HTCIssueSend(target, ADF_NBUF_NULL, netbuf, 0, sizeof(HTC_CONFIG_PIPE_MSG), ENDPOINT0); if (A_FAILED(status)) { break; } htc_spin( &target->spin ); if (target->cfg_pipe_rsp_stat == HTC_CONFIGPIPE_SUCCESS) { status = A_OK; } else { status = A_ERROR; } } while(FALSE); return status; }
A_STATUS HTCSendSetupComplete(HTC_TARGET *target) { HTC_PACKET *pSendPacket = NULL; A_STATUS status; HTC_SETUP_COMPLETE_MSG *pSetupComplete; do { /* allocate a packet to send to the target */ pSendPacket = HTC_ALLOC_CONTROL_TX(target); if (NULL == pSendPacket) { status = A_NO_MEMORY; break; } /* assemble setup complete message */ pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer; A_MEMZERO(pSetupComplete,sizeof(HTC_SETUP_COMPLETE_MSG)); pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID; SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); /* we want synchronous operation */ pSendPacket->Completion = NULL; /* send the message */ status = HTCIssueSend(target,pSendPacket,0); } while (FALSE); if (pSendPacket != NULL) { HTC_FREE_CONTROL_TX(target,pSendPacket); } return status; }
A_STATUS HTCSendSetupComplete(HTC_TARGET *target) { HTC_PACKET *pSendPacket = NULL; A_STATUS status; do { /* allocate a packet to send to the target */ pSendPacket = HTC_ALLOC_CONTROL_TX(target); if (NULL == pSendPacket) { status = A_NO_MEMORY; break; } if (target->HTCTargetVersion >= HTC_VERSION_2P1) { HTC_SETUP_COMPLETE_EX_MSG *pSetupCompleteEx; A_UINT32 setupFlags = 0; pSetupCompleteEx = (HTC_SETUP_COMPLETE_EX_MSG *)pSendPacket->pBuffer; A_MEMZERO(pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); pSetupCompleteEx->MessageID = HTC_MSG_SETUP_COMPLETE_EX_ID; if (target->MaxMsgPerBundle > 0) { /* host can do HTC bundling, indicate this to the target */ setupFlags |= HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; pSetupCompleteEx->MaxMsgsPerBundledRecv = target->MaxMsgPerBundle; } A_MEMCPY(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags)); SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); } else { HTC_SETUP_COMPLETE_MSG *pSetupComplete; /* assemble setup complete message */ pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer; A_MEMZERO(pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG)); pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID; SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); } /* we want synchronous operation */ pSendPacket->Completion = NULL; HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0); /* send the message */ status = HTCIssueSend(target,pSendPacket); } while (FALSE); if (pSendPacket != NULL) { HTC_FREE_CONTROL_TX(target,pSendPacket); } return status; }
A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, HTC_SERVICE_CONNECT_REQ *pConnectReq, HTC_SERVICE_CONNECT_RESP *pConnectResp) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); A_STATUS status = A_OK; HTC_PACKET *pRecvPacket = NULL; HTC_PACKET *pSendPacket = NULL; HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg; HTC_CONNECT_SERVICE_MSG *pConnectMsg; HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX; HTC_ENDPOINT *pEndpoint; unsigned int maxMsgSize = 0; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%X SvcID:0x%X \n", (A_UINT32)target, pConnectReq->ServiceID)); do { AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0); if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) { /* special case for pseudo control service */ assignedEndpoint = ENDPOINT_0; maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH; } else { /* allocate a packet to send to the target */ pSendPacket = HTC_ALLOC_CONTROL_TX(target); if (NULL == pSendPacket) { AR_DEBUG_ASSERT(FALSE); status = A_NO_MEMORY; break; } /* assemble connect service message */ pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)pSendPacket->pBuffer; AR_DEBUG_ASSERT(pConnectMsg != NULL); A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG)); pConnectMsg->MessageID = HTC_MSG_CONNECT_SERVICE_ID; pConnectMsg->ServiceID = pConnectReq->ServiceID; pConnectMsg->ConnectionFlags = pConnectReq->ConnectionFlags; /* check caller if it wants to transfer meta data */ if ((pConnectReq->pMetaData != NULL) && (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { /* copy meta data into message buffer (after header ) */ A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG), pConnectReq->pMetaData, pConnectReq->MetaDataLength); pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength; } SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pConnectMsg, sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength, ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); /* we want synchronous operation */ pSendPacket->Completion = NULL; HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0); status = HTCIssueSend(target,pSendPacket); if (A_FAILED(status)) { break; } /* wait for response */ status = HTCWaitforControlMessage(target, &pRecvPacket); if (A_FAILED(status)) { break; } /* we controlled the buffer creation so it has to be properly aligned */ pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer; if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) || (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) { /* this message is not valid */ AR_DEBUG_ASSERT(FALSE); status = A_EPROTO; break; } pConnectResp->ConnectRespCode = pResponseMsg->Status; /* check response status */ if (pResponseMsg->Status != HTC_SERVICE_SUCCESS) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target failed service 0x%X connect request (status:%d)\n", pResponseMsg->ServiceID, pResponseMsg->Status)); status = A_EPROTO; break; } assignedEndpoint = (HTC_ENDPOINT_ID) pResponseMsg->EndpointID; maxMsgSize = pResponseMsg->MaxMsgSize; if ((pConnectResp->pMetaData != NULL) && (pResponseMsg->ServiceMetaLength > 0) && (pResponseMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { /* caller supplied a buffer and the target responded with data */ int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength); /* copy the meta data */ A_MEMCPY(pConnectResp->pMetaData, ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG), copyLength); pConnectResp->ActualLength = copyLength; } } /* the rest of these are parameter checks so set the error status */ status = A_EPROTO; if (assignedEndpoint >= ENDPOINT_MAX) { AR_DEBUG_ASSERT(FALSE); break; } if (0 == maxMsgSize) { AR_DEBUG_ASSERT(FALSE); break; } pEndpoint = &target->EndPoint[assignedEndpoint]; pEndpoint->Id = assignedEndpoint; if (pEndpoint->ServiceID != 0) { /* endpoint already in use! */ AR_DEBUG_ASSERT(FALSE); break; } /* return assigned endpoint to caller */ pConnectResp->Endpoint = assignedEndpoint; pConnectResp->MaxMsgLength = maxMsgSize; /* setup the endpoint */ pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */ pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth; pEndpoint->MaxMsgLength = maxMsgSize; /* copy all the callbacks */ pEndpoint->EpCallBacks = pConnectReq->EpCallbacks; /* set the credit distribution info for this endpoint, this information is * passed back to the credit distribution callback function */ pEndpoint->CreditDist.ServiceID = pConnectReq->ServiceID; pEndpoint->CreditDist.pHTCReserved = pEndpoint; pEndpoint->CreditDist.Endpoint = assignedEndpoint; pEndpoint->CreditDist.TxCreditSize = target->TargetCreditSize; if (pConnectReq->MaxSendMsgSize != 0) { /* override TxCreditsPerMaxMsg calculation, this optimizes the credit-low indications * since the host will actually issue smaller messages in the Send path */ if (pConnectReq->MaxSendMsgSize > maxMsgSize) { /* can't be larger than the maximum the target can support */ AR_DEBUG_ASSERT(FALSE); break; } pEndpoint->CreditDist.TxCreditsPerMaxMsg = pConnectReq->MaxSendMsgSize / target->TargetCreditSize; } else { pEndpoint->CreditDist.TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize; } if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) { pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1; } /* save local connection flags */ pEndpoint->LocalConnectionFlags = pConnectReq->LocalConnectionFlags; status = A_OK; } while (FALSE); if (pSendPacket != NULL) { HTC_FREE_CONTROL_TX(target,pSendPacket); } if (pRecvPacket != NULL) { HTC_FREE_CONTROL_RX(target,pRecvPacket); } AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n")); return status; }
A_STATUS HTCSendPkt(HTC_HANDLE hHTC, adf_nbuf_t hdr_buf, adf_nbuf_t buf, HTC_ENDPOINT_ID Ep) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(hHTC); A_STATUS status = A_OK; HTC_ENDPOINT *pEndpoint; #ifndef ATH_HTC_TX_SCHED do { if (Ep >= ENDPOINT_MAX) { adf_os_print("Ep %u is invalid!\n", Ep); if (hdr_buf) { adf_nbuf_free(hdr_buf); } if (buf) { adf_nbuf_free(buf); } status = A_EPROTO; break; } pEndpoint = &target->EndPoint[Ep]; #if 0 LOCK_HTC_TX(target); /* record number of buffers in corresponding endpoint */ if ((pAggrNumRec = HTC_AGGRNUMREC_DEQUEUE(&target->FreeAggrNumRecQueue)) == NULL) { adf_os_print("%s no more free aggr record\n", __FUNCTION__); status = A_NO_RESOURCE; UNLOCK_HTC_TX(target); break; } pAggrNumRec->AggrNum = num; pAggrNumRec->bufArray = bufArray; /* buffers were supplied to be queued */ HTC_AGGRNUMREC_ENQUEUE(&pEndpoint->AggrNumRecQueue, pAggrNumRec); UNLOCK_HTC_TX(target); #endif status = HTCTrySend(target, pEndpoint, hdr_buf, buf); // adf_os_print("return value of HTCTrySend: %u\n", status); } while(FALSE); #else a_uint16_t payloadLen; a_uint8_t SendFlags = 0; pEndpoint = &target->EndPoint[Ep]; if ( HIFGetFreeQueueNumber(target->hif_dev, pEndpoint->UL_PipeID) == 0 ) return -1 ; if(hdr_buf != NULL) payloadLen = (a_uint16_t) (adf_nbuf_len(hdr_buf) + adf_nbuf_len(buf)); else payloadLen = (a_uint16_t) adf_nbuf_len(buf) ; #ifdef HTC_HOST_CREDIT_DIST /* check if credits are enough for sending this packet */ #ifdef WMI_RETRY if((Ep != 1 ) && (Ep != 2)) #endif { status = HTCCheckCredits(target, HTC_HDR_LENGTH + payloadLen, pEndpoint, &SendFlags); if (A_FAILED(status)) { //adf_os_print("credits are not enough for sending the message!\n"); return status; } } #endif status = HTCIssueSend(target, hdr_buf, buf, SendFlags, payloadLen, Ep); if (A_FAILED(status)) { HTCReclaimCredits(target, HTC_HDR_LENGTH + payloadLen, pEndpoint); return -1 ; } #endif return status; }
A_STATUS HTCTrySend(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, adf_nbuf_t hdr_buf, adf_nbuf_t buf) { a_uint8_t SendFlags = 0; a_uint16_t payloadLen; a_uint8_t EpID; A_STATUS status = A_OK; #if 0 a_uint32_t creditsRequired, remainder; #endif a_int32_t i; if ( (pEndpoint) && (buf != ADF_NBUF_NULL) ) { /* packet was supplied to be queued */ status = HTCTxEnqueuePkts(target, pEndpoint, hdr_buf, buf); if (A_FAILED(status)) { if (buf) { adf_nbuf_free(buf); } if (hdr_buf) { adf_nbuf_free(hdr_buf); } //adf_os_print("%s: Not enough queue spaces for enqueuing, epid = %d, enqueue fail cnt = %d\n", // __func__, // pEndpoint->CreditDist.Endpoint, ++(pEndpoint->stat_enqfail)); } } /* now drain the TX queue for transmission as long as we have enough credits */ LOCK_HTC_TX(target); for (i = ENDPOINT_MAX - 1; i >= 0; i--) { a_uint32_t availableTxCnt = 0xFFFFFFFF; a_uint8_t isDataService = 0; pEndpoint = &target->EndPoint[i]; EpID = pEndpoint->CreditDist.Endpoint; if (pEndpoint->ServiceID == 0) continue; /* calculate available tx count base on the de-queue level */ if ((pEndpoint->ServiceID == WMI_DATA_BE_SVC) || (pEndpoint->ServiceID == WMI_DATA_BK_SVC) || (pEndpoint->ServiceID == WMI_DATA_VI_SVC) || (pEndpoint->ServiceID == WMI_DATA_VO_SVC)) { isDataService = 1; if (pEndpoint->tqi_dqlevel < 4) { availableTxCnt = 4- pEndpoint->tqi_dqlevel; } else { availableTxCnt = 1; } //adf_os_print("%s: epid = %d, i = %d, dqlevel = %d, txcnt = %d\n", __FUNCTION__, EpID, i, pEndpoint->tqi_dqlevel, availableTxCnt); } while (availableTxCnt-- > 0) { adf_nbuf_t tmpbuf, tmp_hdr_buf; a_uint16_t tmplen, tmp_hdr_len; a_uint16_t freeQNum, maxQNum, toNext; if (pEndpoint->TxBufCnt == 0) { break; } if ( (freeQNum = HIFGetFreeQueueNumber(target->hif_dev, pEndpoint->UL_PipeID)) == 0 ) { //adf_os_print("%s: USB TxQ full, epid = %d, pipe id = %d, count = %d\n", // __func__, EpID, pEndpoint->UL_PipeID, ++(pEndpoint->stat_usbqfull)); break; } if (isDataService) { toNext = 0; maxQNum = HIFGetMaxQueueNumber(target->hif_dev, pEndpoint->UL_PipeID); //adf_os_print("%s: epid = %d, freeQNum = %d, maxQNum = %d, availableTxCnt = %d\n", __FUNCTION__, EpID, freeQNum, maxQNum, availableTxCnt); switch (pEndpoint->tqi_dqlevel) { case 0: if (freeQNum == 0) {toNext = 1;} break; case 1: if (freeQNum <= maxQNum/2) {toNext = 1;} //4/8 break; case 2: if (freeQNum <= (maxQNum*5)/8) {toNext = 1;} //5/8 break; case 3: default: if (freeQNum <= (maxQNum*3)/4) {toNext = 1;} //6/8 break; } if (toNext == 1) { // adf_os_print("%s: To Next Endpoint, epid = %d, freeQNum = %d, maxQNum = %d\n", __FUNCTION__, EpID, freeQNum, maxQNum); break; } } /* get packet at head, but don't remove it */ tmp_hdr_buf = pEndpoint->HtcTxQueue[pEndpoint->TxQHead].hdr_buf; tmp_hdr_len = pEndpoint->HtcTxQueue[pEndpoint->TxQHead].hdr_bufLen; tmpbuf = pEndpoint->HtcTxQueue[pEndpoint->TxQHead].buf; tmplen = pEndpoint->HtcTxQueue[pEndpoint->TxQHead].bufLen; #if 0 /* figure out how many credits this message requires */ creditsRequired = (tmplen + tmp_hdr_len + HTC_HDR_LENGTH) / target->TargetCreditSize; remainder = (tmplen + tmp_hdr_len + HTC_HDR_LENGTH) % target->TargetCreditSize; if (remainder) { creditsRequired++; } adf_os_print("creditsRequired: %u, tmplen + HTC_HDR_LENGTH: %u, target->TargetCreditSize: %u, pEndpoint->CreditDist.TxCredits: %u\n", creditsRequired, tmplen + HTC_HDR_LENGTH, target->TargetCreditSize, pEndpoint->CreditDist.TxCredits); /* not enough credits */ if (pEndpoint->CreditDist.TxCredits < creditsRequired) { /* set how many credits we need */ pEndpoint->CreditDist.TxCreditsSeek = creditsRequired - pEndpoint->CreditDist.TxCredits; DO_DISTRIBUTION(target, HTC_CREDIT_DIST_SEEK_CREDITS, "Seek Credits", &pEndpoint->CreditDist); pEndpoint->CreditDist.TxCreditsSeek = 0; if (pEndpoint->CreditDist.TxCredits < creditsRequired) { /* still not enough credits to send, leave packet in the queue */ status = A_CREDIT_UNAVAILABLE; break; } } pEndpoint->CreditDist.TxCredits -= creditsRequired; //adf_os_print("pEndpoint->CreditDist.TxCreditsPerMaxMsg: %u\n", pEndpoint->CreditDist.TxCreditsPerMaxMsg); /* check if we need credits back from the target */ if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) { /* we are getting low on credits, see if we can ask for more from the distribution function */ pEndpoint->CreditDist.TxCreditsSeek = pEndpoint->CreditDist.TxCreditsPerMaxMsg - pEndpoint->CreditDist.TxCredits; DO_DISTRIBUTION(target, HTC_CREDIT_DIST_SEEK_CREDITS, "Seek Credits", &pEndpoint->CreditDist); pEndpoint->CreditDist.TxCreditsSeek = 0; if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) { /* tell the target we need credits ASAP! */ SendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE; adf_os_print("SendFlags: %u\n", SendFlags); } #endif payloadLen = tmp_hdr_len + tmplen; /* now we can fully dequeue */ pEndpoint->TxQHead = (pEndpoint->TxQHead + 1) % HTC_TX_QUEUE_SIZE; pEndpoint->TxBufCnt--; UNLOCK_HTC_TX(target); status = HTCIssueSend(target, tmp_hdr_buf, tmpbuf, SendFlags, payloadLen, EpID); LOCK_HTC_TX(target); if (A_FAILED(status)) { adf_os_print("%s: Fail to send pkt to HIF, cnt = %d, usesendfail = %d\n", __func__, EpID, ++(pEndpoint->stat_usbsendfail)); #if 0 /* reclaim the credit due to failure to send */ HTCReclaimCredits(target, HTC_HDR_LENGTH + payloadLen, pEndpoint); #endif if (tmpbuf) { adf_nbuf_free(tmpbuf); } if (tmp_hdr_buf) { adf_nbuf_free(tmp_hdr_buf); } break; } #if 0 } #endif } } /* for (i = ENDPOINT_MAX - 1; i >= 0; i--) */ UNLOCK_HTC_TX(target); #if 0 return status; #else return A_OK; #endif }