static void DoRecvCompletion(HTC_ENDPOINT *pEndpoint, HTC_PACKET_QUEUE *pQueueToIndicate) { do { if (HTC_QUEUE_EMPTY(pQueueToIndicate)) { /* nothing to indicate */ break; } if (pEndpoint->EpCallBacks.EpRecvPktMultiple != NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d, recv multiple callback (%d pkts) \n", pEndpoint->Id, HTC_PACKET_QUEUE_DEPTH(pQueueToIndicate))); /* a recv multiple handler is being used, pass the queue to the handler */ pEndpoint->EpCallBacks.EpRecvPktMultiple(pEndpoint->EpCallBacks.pContext, pQueueToIndicate); INIT_HTC_PACKET_QUEUE(pQueueToIndicate); } else { HTC_PACKET *pPacket; /* using legacy EpRecv */ while (!HTC_QUEUE_EMPTY(pQueueToIndicate)) { pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate); AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d recv callback on packet %p \n", pEndpoint->Id, pPacket)); pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket); } } } while (FALSE); }
void htc_dump_credit_states(HTC_HANDLE HTCHandle) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_ENDPOINT *pEndpoint; int i; for (i = 0; i < ENDPOINT_MAX; i++) { pEndpoint = &target->EndPoint[i]; if (0 == pEndpoint->ServiceID) { continue; } AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n", pEndpoint->Id, pEndpoint->ServiceID)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEndpoint->TxCredits)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEndpoint->TxCreditSize)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEndpoint->TxCreditsPerMaxMsg)); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n", HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue))); AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n")); } }
int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint]; return HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBufferHoldQueue); }
A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_ENDPOINT *pEndpoint; HTC_PACKET *pFirstPacket; A_STATUS status = A_OK; HTC_PACKET *pPacket; pFirstPacket = HTC_GET_PKT_AT_HEAD(pPktQueue); if (NULL == pFirstPacket) { A_ASSERT(FALSE); return A_EINVAL; } AR_DEBUG_ASSERT(pFirstPacket->Endpoint < ENDPOINT_MAX); AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+- HTCAddReceivePktMultiple : endPointId: %d, cnt:%d, length: %d\n", pFirstPacket->Endpoint, HTC_PACKET_QUEUE_DEPTH(pPktQueue), pFirstPacket->BufferLength)); pEndpoint = &target->EndPoint[pFirstPacket->Endpoint]; LOCK_HTC_RX(target); do { if (HTC_STOPPING(target)) { status = A_ERROR; break; } /* store receive packets */ HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBufferHoldQueue,pPktQueue); } while (FALSE); UNLOCK_HTC_RX(target); if (A_FAILED(status)) { /* walk through queue and mark each one canceled */ HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue,pPacket) { pPacket->Status = A_ECANCELED; } HTC_PACKET_QUEUE_ITERATE_END; DoRecvCompletion(pEndpoint,pPktQueue); } return status; }
A_STATUS HTCRxCompletionHandler( void *Context, adf_nbuf_t netbuf, a_uint8_t pipeID) { A_STATUS status = A_OK; HTC_FRAME_HDR *HtcHdr; HTC_TARGET *target = (HTC_TARGET *)Context; a_uint8_t *netdata; a_uint32_t netlen; HTC_ENDPOINT *pEndpoint; HTC_PACKET *pPacket; A_UINT16 payloadLen; a_uint32_t trailerlen = 0; A_UINT8 htc_ep_id; #ifdef RX_SG_SUPPORT LOCK_HTC_RX(target); if (target->IsRxSgInprogress) { target->CurRxSgTotalLen += adf_nbuf_len(netbuf); adf_nbuf_queue_add(&target->RxSgQueue, netbuf); if (target->CurRxSgTotalLen == target->ExpRxSgTotalLen) { netbuf = RxSgToSingleNetbuf(target); if (netbuf == NULL) { UNLOCK_HTC_RX(target); goto _out; } } else { netbuf = NULL; UNLOCK_HTC_RX(target); goto _out; } } UNLOCK_HTC_RX(target); #endif netdata = adf_nbuf_data(netbuf); netlen = adf_nbuf_len(netbuf); HtcHdr = (HTC_FRAME_HDR *)netdata; do { htc_ep_id = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, ENDPOINTID); if (htc_ep_id >= ENDPOINT_MAX) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC Rx: invalid EndpointID=%d\n",htc_ep_id)); DebugDumpBytes((A_UINT8 *)HtcHdr,sizeof(HTC_FRAME_HDR),"BAD HTC Header"); status = A_ERROR; VOS_BUG(0); break; } pEndpoint = &target->EndPoint[htc_ep_id]; /* * If this endpoint that received a message from the target has * a to-target HIF pipe whose send completions are polled rather * than interrupt-driven, this is a good point to ask HIF to check * whether it has any completed sends to handle. */ if (pEndpoint->ul_is_polled) { HTCSendCompleteCheck(pEndpoint, 1); } payloadLen = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, PAYLOADLEN); if (netlen < (payloadLen + HTC_HDR_LENGTH)) { #ifdef RX_SG_SUPPORT LOCK_HTC_RX(target); target->IsRxSgInprogress = TRUE; adf_nbuf_queue_init(&target->RxSgQueue); adf_nbuf_queue_add(&target->RxSgQueue, netbuf); target->ExpRxSgTotalLen = (payloadLen + HTC_HDR_LENGTH); target->CurRxSgTotalLen += netlen; UNLOCK_HTC_RX(target); netbuf = NULL; break; #else AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC Rx: insufficient length, got:%d expected =%zu\n", netlen, payloadLen + HTC_HDR_LENGTH)); DebugDumpBytes((A_UINT8 *)HtcHdr,sizeof(HTC_FRAME_HDR),"BAD RX packet length"); status = A_ERROR; VOS_BUG(0); break; #endif } #ifdef HTC_EP_STAT_PROFILING LOCK_HTC_RX(target); INC_HTC_EP_STAT(pEndpoint,RxReceived,1); UNLOCK_HTC_RX(target); #endif //if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { { A_UINT8 temp; /* get flags to check for trailer */ temp = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, FLAGS); if (temp & HTC_FLAGS_RECV_TRAILER) { /* extract the trailer length */ temp = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, CONTROLBYTES0); if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRxCompletionHandler, invalid header (payloadlength should be :%d, CB[0] is:%d) \n", payloadLen, temp)); status = A_EPROTO; break; } trailerlen = temp; /* process trailer data that follows HDR + application payload */ status = HTCProcessTrailer(target, ((A_UINT8 *)HtcHdr + HTC_HDR_LENGTH + payloadLen - temp), temp, htc_ep_id); if (A_FAILED(status)) { break; } } } if (((int)payloadLen - (int)trailerlen) <= 0) { /* zero length packet with trailer data, just drop these */ break; } if (htc_ep_id == ENDPOINT_0) { A_UINT16 message_id; HTC_UNKNOWN_MSG *htc_msg; int wow_nack = 0; /* remove HTC header */ adf_nbuf_pull_head(netbuf, HTC_HDR_LENGTH); netdata = adf_nbuf_data(netbuf); netlen = adf_nbuf_len(netbuf); htc_msg = (HTC_UNKNOWN_MSG*)netdata; message_id = HTC_GET_FIELD(htc_msg, HTC_UNKNOWN_MSG, MESSAGEID); switch (message_id) { default: /* handle HTC control message */ if (target->CtrlResponseProcessing) { /* this is a fatal error, target should not be sending unsolicited messages * on the endpoint 0 */ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC Rx Ctrl still processing\n")); status = A_ERROR; VOS_BUG(FALSE); break; } LOCK_HTC_RX(target); target->CtrlResponseLength = min((int)netlen,HTC_MAX_CONTROL_MESSAGE_LENGTH); A_MEMCPY(target->CtrlResponseBuffer,netdata,target->CtrlResponseLength); /* Requester will clear this flag */ target->CtrlResponseProcessing = TRUE; UNLOCK_HTC_RX(target); adf_os_complete(&target->CtrlResponseValid); break; case HTC_MSG_SEND_SUSPEND_COMPLETE: wow_nack = 0; LOCK_HTC_CREDIT(target); htc_credit_record(HTC_SUSPEND_ACK, pEndpoint->TxCredits, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)); UNLOCK_HTC_CREDIT(target); target->HTCInitInfo.TargetSendSuspendComplete((void *)&wow_nack); HTCsuspendwow(target); break; case HTC_MSG_NACK_SUSPEND: wow_nack = 1; LOCK_HTC_CREDIT(target); htc_credit_record(HTC_SUSPEND_NACK, pEndpoint->TxCredits, HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)); UNLOCK_HTC_CREDIT(target); target->HTCInitInfo.TargetSendSuspendComplete((void *)&wow_nack); break; } adf_nbuf_free(netbuf); netbuf = NULL; break; } /* the current message based HIF architecture allocates net bufs for recv packets * since this layer bridges that HIF to upper layers , which expects HTC packets, * we form the packets here * TODO_FIXME */ pPacket = AllocateHTCPacketContainer(target); if (NULL == pPacket) { status = A_NO_RESOURCE; break; } pPacket->Status = A_OK; pPacket->Endpoint = htc_ep_id; pPacket->pPktContext = netbuf; pPacket->pBuffer = adf_nbuf_data(netbuf) + HTC_HDR_LENGTH; pPacket->ActualLength = netlen - HTC_HEADER_LEN - trailerlen; adf_nbuf_pull_head(netbuf, HTC_HEADER_LEN); adf_nbuf_set_pktlen(netbuf, pPacket->ActualLength); RecvPacketCompletion(target,pEndpoint,pPacket); /* recover the packet container */ FreeHTCPacketContainer(target,pPacket); netbuf = NULL; } while(FALSE); #ifdef RX_SG_SUPPORT _out: #endif if (netbuf != NULL) { adf_nbuf_free(netbuf); } return status; }