summaryrefslogtreecommitdiff
path: root/drivers/staging/ath6kl/htc2/htc_recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/ath6kl/htc2/htc_recv.c')
-rw-r--r--drivers/staging/ath6kl/htc2/htc_recv.c1572
1 files changed, 0 insertions, 1572 deletions
diff --git a/drivers/staging/ath6kl/htc2/htc_recv.c b/drivers/staging/ath6kl/htc2/htc_recv.c
deleted file mode 100644
index 974cc8cd6936..000000000000
--- a/drivers/staging/ath6kl/htc2/htc_recv.c
+++ /dev/null
@@ -1,1572 +0,0 @@
-//------------------------------------------------------------------------------
-// <copyright file="htc_recv.c" company="Atheros">
-// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
-//
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-//
-//------------------------------------------------------------------------------
-//==============================================================================
-// Author(s): ="Atheros"
-//==============================================================================
-#include "htc_internal.h"
-
-#define HTCIssueRecv(t, p) \
- DevRecvPacket(&(t)->Device, \
- (p), \
- (p)->ActualLength)
-
-#define DO_RCV_COMPLETION(e,q) DoRecvCompletion(e,q)
-
-#define DUMP_RECV_PKT_INFO(pP) \
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC RECV packet 0x%lX (%d bytes) (hdr:0x%X) on ep : %d \n", \
- (unsigned long)(pP), \
- (pP)->ActualLength, \
- (pP)->PktInfo.AsRx.ExpectedHdr, \
- (pP)->Endpoint))
-
-#define HTC_RX_STAT_PROFILE(t,ep,numLookAheads) \
-{ \
- INC_HTC_EP_STAT((ep), RxReceived, 1); \
- if ((numLookAheads) == 1) { \
- INC_HTC_EP_STAT((ep), RxLookAheads, 1); \
- } else if ((numLookAheads) > 1) { \
- INC_HTC_EP_STAT((ep), RxBundleLookAheads, 1); \
- } \
-}
-
-static void DoRecvCompletion(struct htc_endpoint *pEndpoint,
- struct 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 {
- struct htc_packet *pPacket;
- /* using legacy EpRecv */
- do {
- pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" HTC calling ep %d recv callback on packet 0x%lX \n", \
- pEndpoint->Id, (unsigned long)(pPacket)));
- pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket);
- } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));
- }
-
- } while (false);
-
-}
-
-static INLINE int HTCProcessTrailer(struct htc_target *target,
- u8 *pBuffer,
- int Length,
- u32 *pNextLookAheads,
- int *pNumLookAheads,
- HTC_ENDPOINT_ID FromEndpoint)
-{
- HTC_RECORD_HDR *pRecord;
- u8 *pRecordBuf;
- HTC_LOOKAHEAD_REPORT *pLookAhead;
- u8 *pOrigBuffer;
- int origLength;
- int status;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length));
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer");
- }
-
- pOrigBuffer = pBuffer;
- origLength = Length;
- status = 0;
-
- while (Length > 0) {
-
- if (Length < sizeof(HTC_RECORD_HDR)) {
- status = A_EPROTO;
- break;
- }
- /* these are byte aligned structs */
- pRecord = (HTC_RECORD_HDR *)pBuffer;
- Length -= sizeof(HTC_RECORD_HDR);
- pBuffer += sizeof(HTC_RECORD_HDR);
-
- if (pRecord->Length > Length) {
- /* no room left in buffer for record */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- (" invalid record length: %d (id:%d) buffer has: %d bytes left \n",
- pRecord->Length, pRecord->RecordID, Length));
- status = A_EPROTO;
- break;
- }
- /* start of record follows the header */
- pRecordBuf = pBuffer;
-
- switch (pRecord->RecordID) {
- case HTC_RECORD_CREDITS:
- AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_CREDIT_REPORT));
- HTCProcessCreditRpt(target,
- (HTC_CREDIT_REPORT *)pRecordBuf,
- pRecord->Length / (sizeof(HTC_CREDIT_REPORT)),
- FromEndpoint);
- break;
- case HTC_RECORD_LOOKAHEAD:
- AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_LOOKAHEAD_REPORT));
- pLookAhead = (HTC_LOOKAHEAD_REPORT *)pRecordBuf;
- if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) &&
- (pNextLookAheads != NULL)) {
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) \n",
- pLookAhead->PreValid,
- pLookAhead->PostValid));
-
- /* look ahead bytes are valid, copy them over */
- ((u8 *)(&pNextLookAheads[0]))[0] = pLookAhead->LookAhead[0];
- ((u8 *)(&pNextLookAheads[0]))[1] = pLookAhead->LookAhead[1];
- ((u8 *)(&pNextLookAheads[0]))[2] = pLookAhead->LookAhead[2];
- ((u8 *)(&pNextLookAheads[0]))[3] = pLookAhead->LookAhead[3];
-
-#ifdef ATH_DEBUG_MODULE
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- DebugDumpBytes((u8 *)pNextLookAheads,4,"Next Look Ahead");
- }
-#endif
- /* just one normal lookahead */
- *pNumLookAheads = 1;
- }
- break;
- case HTC_RECORD_LOOKAHEAD_BUNDLE:
- AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT));
- if (pRecord->Length >= sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT) &&
- (pNextLookAheads != NULL)) {
- HTC_BUNDLED_LOOKAHEAD_REPORT *pBundledLookAheadRpt;
- int i;
-
- pBundledLookAheadRpt = (HTC_BUNDLED_LOOKAHEAD_REPORT *)pRecordBuf;
-
-#ifdef ATH_DEBUG_MODULE
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- DebugDumpBytes(pRecordBuf,pRecord->Length,"Bundle LookAhead");
- }
-#endif
-
- if ((pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))) >
- HTC_HOST_MAX_MSG_PER_BUNDLE) {
- /* this should never happen, the target restricts the number
- * of messages per bundle configured by the host */
- A_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- for (i = 0; i < (int)(pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))); i++) {
- ((u8 *)(&pNextLookAheads[i]))[0] = pBundledLookAheadRpt->LookAhead[0];
- ((u8 *)(&pNextLookAheads[i]))[1] = pBundledLookAheadRpt->LookAhead[1];
- ((u8 *)(&pNextLookAheads[i]))[2] = pBundledLookAheadRpt->LookAhead[2];
- ((u8 *)(&pNextLookAheads[i]))[3] = pBundledLookAheadRpt->LookAhead[3];
- pBundledLookAheadRpt++;
- }
-
- *pNumLookAheads = i;
- }
- break;
- default:
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n",
- pRecord->RecordID, pRecord->Length));
- break;
- }
-
- if (status) {
- break;
- }
-
- /* advance buffer past this record for next time around */
- pBuffer += pRecord->Length;
- Length -= pRecord->Length;
- }
-
-#ifdef ATH_DEBUG_MODULE
- if (status) {
- DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer");
- }
-#endif
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n"));
- return status;
-
-}
-
-/* process a received message (i.e. strip off header, process any trailer data)
- * note : locks must be released when this function is called */
-static int HTCProcessRecvHeader(struct htc_target *target,
- struct htc_packet *pPacket,
- u32 *pNextLookAheads,
- int *pNumLookAheads)
-{
- u8 temp;
- u8 *pBuf;
- int status = 0;
- u16 payloadLen;
- u32 lookAhead;
-
- pBuf = pPacket->pBuffer;
-
- if (pNumLookAheads != NULL) {
- *pNumLookAheads = 0;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader \n"));
-
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- AR_DEBUG_PRINTBUF(pBuf,pPacket->ActualLength,"HTC Recv PKT");
- }
-
- do {
- /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to
- * retrieve 16 bit fields */
- payloadLen = A_GET_UINT16_FIELD(pBuf, struct htc_frame_hdr, PayloadLen);
-
- ((u8 *)&lookAhead)[0] = pBuf[0];
- ((u8 *)&lookAhead)[1] = pBuf[1];
- ((u8 *)&lookAhead)[2] = pBuf[2];
- ((u8 *)&lookAhead)[3] = pBuf[3];
-
- if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) {
- /* refresh expected hdr, since this was unknown at the time we grabbed the packets
- * as part of a bundle */
- pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead;
- /* refresh actual length since we now have the real header */
- pPacket->ActualLength = payloadLen + HTC_HDR_LENGTH;
-
- /* validate the actual header that was refreshed */
- if (pPacket->ActualLength > pPacket->BufferLength) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Refreshed HDR payload length (%d) in bundled RECV is invalid (hdr: 0x%X) \n",
- payloadLen, lookAhead));
- /* limit this to max buffer just to print out some of the buffer */
- pPacket->ActualLength = min(pPacket->ActualLength, pPacket->BufferLength);
- status = A_EPROTO;
- break;
- }
-
- if (pPacket->Endpoint != A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Refreshed HDR endpoint (%d) does not match expected endpoint (%d) \n",
- A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID), pPacket->Endpoint));
- status = A_EPROTO;
- break;
- }
- }
-
- if (lookAhead != pPacket->PktInfo.AsRx.ExpectedHdr) {
- /* somehow the lookahead that gave us the full read length did not
- * reflect the actual header in the pending message */
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("HTCProcessRecvHeader, lookahead mismatch! (pPkt:0x%lX flags:0x%X) \n",
- (unsigned long)pPacket, pPacket->PktInfo.AsRx.HTCRxFlags));
-#ifdef ATH_DEBUG_MODULE
- DebugDumpBytes((u8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead");
- DebugDumpBytes(pBuf,sizeof(struct htc_frame_hdr),"Current Frame Header");
-#ifdef HTC_CAPTURE_LAST_FRAME
- DebugDumpBytes((u8 *)&target->LastFrameHdr,sizeof(struct htc_frame_hdr),"Last Frame Header");
- if (target->LastTrailerLength != 0) {
- DebugDumpBytes(target->LastTrailer,
- target->LastTrailerLength,
- "Last trailer");
- }
-#endif
-#endif
- status = A_EPROTO;
- break;
- }
-
- /* get flags */
- temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, Flags);
-
- if (temp & HTC_FLAGS_RECV_TRAILER) {
- /* this packet has a trailer */
-
- /* extract the trailer length in control byte 0 */
- temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, ControlBytes[0]);
-
- if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("HTCProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n",
- payloadLen, temp));
- status = A_EPROTO;
- break;
- }
-
- if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
- /* this packet was fetched as part of an HTC bundle, the embedded lookahead is
- * not valid since the next packet may have already been fetched as part of the
- * bundle */
- pNextLookAheads = NULL;
- pNumLookAheads = NULL;
- }
-
- /* process trailer data that follows HDR + application payload */
- status = HTCProcessTrailer(target,
- (pBuf + HTC_HDR_LENGTH + payloadLen - temp),
- temp,
- pNextLookAheads,
- pNumLookAheads,
- pPacket->Endpoint);
-
- if (status) {
- break;
- }
-
-#ifdef HTC_CAPTURE_LAST_FRAME
- memcpy(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp);
- target->LastTrailerLength = temp;
-#endif
- /* trim length by trailer bytes */
- pPacket->ActualLength -= temp;
- }
-#ifdef HTC_CAPTURE_LAST_FRAME
- else {
- target->LastTrailerLength = 0;
- }
-#endif
-
- /* if we get to this point, the packet is good */
- /* remove header and adjust length */
- pPacket->pBuffer += HTC_HDR_LENGTH;
- pPacket->ActualLength -= HTC_HDR_LENGTH;
-
- } while (false);
-
- if (status) {
- /* dump the whole packet */
-#ifdef ATH_DEBUG_MODULE
- DebugDumpBytes(pBuf,pPacket->ActualLength < 256 ? pPacket->ActualLength : 256 ,"BAD HTC Recv PKT");
-#endif
- } else {
-#ifdef HTC_CAPTURE_LAST_FRAME
- memcpy(&target->LastFrameHdr,pBuf,sizeof(struct htc_frame_hdr));
-#endif
- if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
- if (pPacket->ActualLength > 0) {
- AR_DEBUG_PRINTBUF(pPacket->pBuffer,pPacket->ActualLength,"HTC - Application Msg");
- }
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessRecvHeader \n"));
- return status;
-}
-
-static INLINE void HTCAsyncRecvCheckMorePackets(struct htc_target *target,
- u32 NextLookAheads[],
- int NumLookAheads,
- bool CheckMoreMsgs)
-{
- /* was there a lookahead for the next packet? */
- if (NumLookAheads > 0) {
- int nextStatus;
- int fetched = 0;
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("HTCAsyncRecvCheckMorePackets - num lookaheads were non-zero : %d \n",
- NumLookAheads));
- /* force status re-check */
- REF_IRQ_STATUS_RECHECK(&target->Device);
- /* we have more packets, get the next packet fetch started */
- nextStatus = HTCRecvMessagePendingHandler(target, NextLookAheads, NumLookAheads, NULL, &fetched);
- if (A_EPROTO == nextStatus) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Next look ahead from recv header was INVALID\n"));
-#ifdef ATH_DEBUG_MODULE
- DebugDumpBytes((u8 *)NextLookAheads,
- NumLookAheads * (sizeof(u32)),
- "BAD lookaheads from lookahead report");
-#endif
- }
- if (!nextStatus && !fetched) {
- /* we could not fetch any more packets due to resources */
- DevAsyncIrqProcessComplete(&target->Device);
- }
- } else {
- if (CheckMoreMsgs) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("HTCAsyncRecvCheckMorePackets - rechecking for more messages...\n"));
- /* if we did not get anything on the look-ahead,
- * call device layer to asynchronously re-check for messages. If we can keep the async
- * processing going we get better performance. If there is a pending message we will keep processing
- * messages asynchronously which should pipeline things nicely */
- DevCheckPendingRecvMsgsAsync(&target->Device);
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("HTCAsyncRecvCheckMorePackets - no check \n"));
- }
- }
-
-
-}
-
- /* unload the recv completion queue */
-static INLINE void DrainRecvIndicationQueue(struct htc_target *target, struct htc_endpoint *pEndpoint)
-{
- struct htc_packet_queue recvCompletions;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+DrainRecvIndicationQueue \n"));
-
- INIT_HTC_PACKET_QUEUE(&recvCompletions);
-
- LOCK_HTC_RX(target);
-
- /* increment rx processing count on entry */
- pEndpoint->RxProcessCount++;
- if (pEndpoint->RxProcessCount > 1) {
- pEndpoint->RxProcessCount--;
- /* another thread or task is draining the RX completion queue on this endpoint
- * that thread will reset the rx processing count when the queue is drained */
- UNLOCK_HTC_RX(target);
- return;
- }
-
- /******* at this point only 1 thread may enter ******/
-
- while (true) {
-
- /* transfer items from main recv queue to the local one so we can release the lock */
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&recvCompletions, &pEndpoint->RecvIndicationQueue);
-
- if (HTC_QUEUE_EMPTY(&recvCompletions)) {
- /* all drained */
- break;
- }
-
- /* release lock while we do the recv completions
- * other threads can now queue more recv completions */
- UNLOCK_HTC_RX(target);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("DrainRecvIndicationQueue : completing %d RECV packets \n",
- HTC_PACKET_QUEUE_DEPTH(&recvCompletions)));
- /* do completion */
- DO_RCV_COMPLETION(pEndpoint,&recvCompletions);
-
- /* re-acquire lock to grab some more completions */
- LOCK_HTC_RX(target);
- }
-
- /* reset count */
- pEndpoint->RxProcessCount = 0;
- UNLOCK_HTC_RX(target);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-DrainRecvIndicationQueue \n"));
-
-}
-
- /* optimization for recv packets, we can indicate a "hint" that there are more
- * single-packets to fetch on this endpoint */
-#define SET_MORE_RX_PACKET_INDICATION_FLAG(L,N,E,P) \
- if ((N) > 0) { SetRxPacketIndicationFlags((L)[0],(E),(P)); }
-
- /* for bundled frames, we can force the flag to indicate there are more packets */
-#define FORCE_MORE_RX_PACKET_INDICATION_FLAG(P) \
- (P)->PktInfo.AsRx.IndicationFlags |= HTC_RX_FLAGS_INDICATE_MORE_PKTS;
-
- /* note: this function can be called with the RX lock held */
-static INLINE void SetRxPacketIndicationFlags(u32 LookAhead,
- struct htc_endpoint *pEndpoint,
- struct htc_packet *pPacket)
-{
- struct htc_frame_hdr *pHdr = (struct htc_frame_hdr *)&LookAhead;
- /* check to see if the "next" packet is from the same endpoint of the
- completing packet */
- if (pHdr->EndpointID == pPacket->Endpoint) {
- /* check that there is a buffer available to actually fetch it */
- if (!HTC_QUEUE_EMPTY(&pEndpoint->RxBuffers)) {
- /* provide a hint that there are more RX packets to fetch */
- FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket);
- }
- }
-}
-
-
-/* asynchronous completion handler for recv packet fetching, when the device layer
- * completes a read request, it will call this completion handler */
-void HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket)
-{
- struct htc_target *target = (struct htc_target *)Context;
- struct htc_endpoint *pEndpoint;
- u32 nextLookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
- int numLookAheads = 0;
- int status;
- bool checkMorePkts = true;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (pkt:0x%lX, status:%d, ep:%d) \n",
- (unsigned long)pPacket, pPacket->Status, pPacket->Endpoint));
-
- A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device));
- AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
- pEndpoint = &target->EndPoint[pPacket->Endpoint];
- pPacket->Completion = NULL;
-
- /* get completion status */
- status = pPacket->Status;
-
- do {
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRecvCompleteHandler: request failed (status:%d, ep:%d) \n",
- pPacket->Status, pPacket->Endpoint));
- break;
- }
- /* process the header for any trailer data */
- status = HTCProcessRecvHeader(target,pPacket,nextLookAheads,&numLookAheads);
-
- if (status) {
- break;
- }
-
- if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
- /* this packet was part of a bundle that had to be broken up.
- * It was fetched one message at a time. There may be other asynchronous reads queued behind this one.
- * Do no issue another check for more packets since the last one in the series of requests
- * will handle it */
- checkMorePkts = false;
- }
-
- DUMP_RECV_PKT_INFO(pPacket);
- LOCK_HTC_RX(target);
- SET_MORE_RX_PACKET_INDICATION_FLAG(nextLookAheads,numLookAheads,pEndpoint,pPacket);
- /* we have a good packet, queue it to the completion queue */
- HTC_PACKET_ENQUEUE(&pEndpoint->RecvIndicationQueue,pPacket);
- HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads);
- UNLOCK_HTC_RX(target);
-
- /* check for more recv packets before indicating */
- HTCAsyncRecvCheckMorePackets(target,nextLookAheads,numLookAheads,checkMorePkts);
-
- } while (false);
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n",
- status));
- /* recycle this packet */
- HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
- } else {
- /* a good packet was queued, drain the queue */
- DrainRecvIndicationQueue(target,pEndpoint);
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvCompleteHandler\n"));
-}
-
-/* synchronously wait for a control message from the target,
- * This function is used at initialization time ONLY. At init messages
- * on ENDPOINT 0 are expected. */
-int HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket)
-{
- int status;
- u32 lookAhead;
- struct htc_packet *pPacket = NULL;
- struct htc_frame_hdr *pHdr;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n"));
-
- do {
-
- *ppControlPacket = NULL;
-
- /* call the polling function to see if we have a message */
- status = DevPollMboxMsgRecv(&target->Device,
- &lookAhead,
- HTC_TARGET_RESPONSE_TIMEOUT);
-
- if (status) {
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead));
-
- /* check the lookahead */
- pHdr = (struct htc_frame_hdr *)&lookAhead;
-
- if (pHdr->EndpointID != ENDPOINT_0) {
- /* unexpected endpoint number, should be zero */
- AR_DEBUG_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- if (status) {
- /* bad message */
- AR_DEBUG_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- pPacket = HTC_ALLOC_CONTROL_RX(target);
-
- if (pPacket == NULL) {
- AR_DEBUG_ASSERT(false);
- status = A_NO_MEMORY;
- break;
- }
-
- pPacket->PktInfo.AsRx.HTCRxFlags = 0;
- pPacket->PktInfo.AsRx.ExpectedHdr = lookAhead;
- pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
-
- if (pPacket->ActualLength > pPacket->BufferLength) {
- AR_DEBUG_ASSERT(false);
- status = A_EPROTO;
- break;
- }
-
- /* we want synchronous operation */
- pPacket->Completion = NULL;
-
- /* get the message from the device, this will block */
- status = HTCIssueRecv(target, pPacket);
-
- if (status) {
- break;
- }
-
- /* process receive header */
- status = HTCProcessRecvHeader(target,pPacket,NULL,NULL);
-
- pPacket->Status = status;
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n",
- status));
- break;
- }
-
- /* give the caller this control message packet, they are responsible to free */
- *ppControlPacket = pPacket;
-
- } while (false);
-
- if (status) {
- if (pPacket != NULL) {
- /* cleanup buffer on error */
- HTC_FREE_CONTROL_RX(target,pPacket);
- }
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCWaitforControlMessage \n"));
-
- return status;
-}
-
-static int AllocAndPrepareRxPackets(struct htc_target *target,
- u32 LookAheads[],
- int Messages,
- struct htc_endpoint *pEndpoint,
- struct htc_packet_queue *pQueue)
-{
- int status = 0;
- struct htc_packet *pPacket;
- struct htc_frame_hdr *pHdr;
- int i,j;
- int numMessages;
- int fullLength;
- bool noRecycle;
-
- /* lock RX while we assemble the packet buffers */
- LOCK_HTC_RX(target);
-
- for (i = 0; i < Messages; i++) {
-
- pHdr = (struct htc_frame_hdr *)&LookAheads[i];
-
- if (pHdr->EndpointID >= ENDPOINT_MAX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID));
- /* invalid endpoint */
- status = A_EPROTO;
- break;
- }
-
- if (pHdr->EndpointID != pEndpoint->Id) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d should be : %d (index:%d)\n",
- pHdr->EndpointID, pEndpoint->Id, i));
- /* invalid endpoint */
- status = A_EPROTO;
- break;
- }
-
- if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n",
- pHdr->PayloadLen, (u32)HTC_MAX_PAYLOAD_LENGTH));
- status = A_EPROTO;
- break;
- }
-
- if (0 == pEndpoint->ServiceID) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Endpoint %d is not connected !\n",pHdr->EndpointID));
- /* endpoint isn't even connected */
- status = A_EPROTO;
- break;
- }
-
- if ((pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) == 0) {
- /* HTC header only indicates 1 message to fetch */
- numMessages = 1;
- } else {
- /* HTC header indicates that every packet to follow has the same padded length so that it can
- * be optimally fetched as a full bundle */
- numMessages = (pHdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) >> HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT;
- /* the count doesn't include the starter frame, just a count of frames to follow */
- numMessages++;
- A_ASSERT(numMessages <= target->MaxMsgPerBundle);
- INC_HTC_EP_STAT(pEndpoint, RxBundleIndFromHdr, 1);
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
- ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages));
- }
-
- fullLength = DEV_CALC_RECV_PADDED_LEN(&target->Device,pHdr->PayloadLen + sizeof(struct htc_frame_hdr));
-
- /* get packet buffers for each message, if there was a bundle detected in the header,
- * use pHdr as a template to fetch all packets in the bundle */
- for (j = 0; j < numMessages; j++) {
-
- /* reset flag, any packets allocated using the RecvAlloc() API cannot be recycled on cleanup,
- * they must be explicitly returned */
- noRecycle = false;
-
- if (pEndpoint->EpCallBacks.EpRecvAlloc != NULL) {
- UNLOCK_HTC_RX(target);
- noRecycle = true;
- /* user is using a per-packet allocation callback */
- pPacket = pEndpoint->EpCallBacks.EpRecvAlloc(pEndpoint->EpCallBacks.pContext,
- pEndpoint->Id,
- fullLength);
- LOCK_HTC_RX(target);
-
- } else if ((pEndpoint->EpCallBacks.EpRecvAllocThresh != NULL) &&
- (fullLength > pEndpoint->EpCallBacks.RecvAllocThreshold)) {
- INC_HTC_EP_STAT(pEndpoint,RxAllocThreshHit,1);
- INC_HTC_EP_STAT(pEndpoint,RxAllocThreshBytes,pHdr->PayloadLen);
- /* threshold was hit, call the special recv allocation callback */
- UNLOCK_HTC_RX(target);
- noRecycle = true;
- /* user wants to allocate packets above a certain threshold */
- pPacket = pEndpoint->EpCallBacks.EpRecvAllocThresh(pEndpoint->EpCallBacks.pContext,
- pEndpoint->Id,
- fullLength);
- LOCK_HTC_RX(target);
-
- } else {
- /* user is using a refill handler that can refill multiple HTC buffers */
-
- /* get a packet from the endpoint recv queue */
- pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
-
- if (NULL == pPacket) {
- /* check for refill handler */
- if (pEndpoint->EpCallBacks.EpRecvRefill != NULL) {
- UNLOCK_HTC_RX(target);
- /* call the re-fill handler */
- pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext,
- pEndpoint->Id);
- LOCK_HTC_RX(target);
- /* check if we have more buffers */
- pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
- /* fall through */
- }
- }
- }
-
- if (NULL == pPacket) {
- /* this is not an error, we simply need to mark that we are waiting for buffers.*/
- target->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS;
- target->EpWaitingForBuffers = pEndpoint->Id;
- status = A_NO_RESOURCE;
- break;
- }
-
- AR_DEBUG_ASSERT(pPacket->Endpoint == pEndpoint->Id);
- /* clear flags */
- pPacket->PktInfo.AsRx.HTCRxFlags = 0;
- pPacket->PktInfo.AsRx.IndicationFlags = 0;
- pPacket->Status = 0;
-
- if (noRecycle) {
- /* flag that these packets cannot be recycled, they have to be returned to the
- * user */
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_NO_RECYCLE;
- }
- /* add packet to queue (also incase we need to cleanup down below) */
- HTC_PACKET_ENQUEUE(pQueue,pPacket);
-
- if (HTC_STOPPING(target)) {
- status = A_ECANCELED;
- break;
- }
-
- /* make sure this message can fit in the endpoint buffer */
- if ((u32)fullLength > pPacket->BufferLength) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Payload Length Error : header reports payload of: %d (%d) endpoint buffer size: %d \n",
- pHdr->PayloadLen, fullLength, pPacket->BufferLength));
- status = A_EPROTO;
- break;
- }
-
- if (j > 0) {
- /* for messages fetched in a bundle the expected lookahead is unknown since we
- * are only using the lookahead of the first packet as a template of what to
- * expect for lengths */
- /* flag that once we get the real HTC header we need to refesh the information */
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_REFRESH_HDR;
- /* set it to something invalid */
- pPacket->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF;
- } else {
-
- pPacket->PktInfo.AsRx.ExpectedHdr = LookAheads[i]; /* set expected look ahead */
- }
- /* set the amount of data to fetch */
- pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
- }
-
- if (status) {
- if (A_NO_RESOURCE == status) {
- /* this is actually okay */
- status = 0;
- }
- break;
- }
-
- }
-
- UNLOCK_HTC_RX(target);
-
- if (status) {
- while (!HTC_QUEUE_EMPTY(pQueue)) {
- pPacket = HTC_PACKET_DEQUEUE(pQueue);
- /* recycle all allocated packets */
- HTC_RECYCLE_RX_PKT(target,pPacket,&target->EndPoint[pPacket->Endpoint]);
- }
- }
-
- return status;
-}
-
-static void HTCAsyncRecvScatterCompletion(struct hif_scatter_req *pScatterReq)
-{
- int i;
- struct htc_packet *pPacket;
- struct htc_endpoint *pEndpoint;
- u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
- int numLookAheads = 0;
- struct htc_target *target = (struct htc_target *)pScatterReq->Context;
- int status;
- bool partialBundle = false;
- struct htc_packet_queue localRecvQueue;
- bool procError = false;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCAsyncRecvScatterCompletion TotLen: %d Entries: %d\n",
- pScatterReq->TotalLength, pScatterReq->ValidScatterEntries));
-
- A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device));
-
- if (pScatterReq->CompletionStatus) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Recv Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));
- }
-
- if (pScatterReq->CallerFlags & HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE) {
- partialBundle = true;
- }
-
- DEV_FINISH_SCATTER_OPERATION(pScatterReq);
-
- INIT_HTC_PACKET_QUEUE(&localRecvQueue);
-
- pPacket = (struct htc_packet *)pScatterReq->ScatterList[0].pCallerContexts[0];
- /* note: all packets in a scatter req are for the same endpoint ! */
- pEndpoint = &target->EndPoint[pPacket->Endpoint];
-
- /* walk through the scatter list and process */
- /* **** NOTE: DO NOT HOLD ANY LOCKS here, HTCProcessRecvHeader can take the TX lock
- * as it processes credit reports */
- for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
- pPacket = (struct htc_packet *)pScatterReq->ScatterList[i].pCallerContexts[0];
- A_ASSERT(pPacket != NULL);
- /* reset count, we are only interested in the look ahead in the last packet when we
- * break out of this loop */
- numLookAheads = 0;
-
- if (!pScatterReq->CompletionStatus) {
- /* process header for each of the recv packets */
- status = HTCProcessRecvHeader(target,pPacket,lookAheads,&numLookAheads);
- } else {
- status = A_ERROR;
- }
-
- if (!status) {
- LOCK_HTC_RX(target);
- HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads);
- INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1);
- UNLOCK_HTC_RX(target);
- if (i == (pScatterReq->ValidScatterEntries - 1)) {
- /* last packet's more packets flag is set based on the lookahead */
- SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,numLookAheads,pEndpoint,pPacket);
- } else {
- /* packets in a bundle automatically have this flag set */
- FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket);
- }
-
- DUMP_RECV_PKT_INFO(pPacket);
- /* since we can't hold a lock in this loop, we insert into our local recv queue for
- * storage until we can transfer them to the recv completion queue */
- HTC_PACKET_ENQUEUE(&localRecvQueue,pPacket);
-
- } else {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Recv packet scatter entry %d failed (out of %d) \n",
- i, pScatterReq->ValidScatterEntries));
- /* recycle failed recv */
- HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
- /* set flag and continue processing the remaining scatter entries */
- procError = true;
- }
-
- }
-
- /* free scatter request */
- DEV_FREE_SCATTER_REQ(&target->Device,pScatterReq);
-
- LOCK_HTC_RX(target);
- /* transfer the packets in the local recv queue to the recv completion queue */
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RecvIndicationQueue, &localRecvQueue);
-
- UNLOCK_HTC_RX(target);
-
- if (!procError) {
- /* pipeline the next check (asynchronously) for more packets */
- HTCAsyncRecvCheckMorePackets(target,
- lookAheads,
- numLookAheads,
- partialBundle ? false : true);
- }
-
- /* now drain the indication queue */
- DrainRecvIndicationQueue(target,pEndpoint);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCAsyncRecvScatterCompletion \n"));
-}
-
-static int HTCIssueRecvPacketBundle(struct htc_target *target,
- struct htc_packet_queue *pRecvPktQueue,
- struct htc_packet_queue *pSyncCompletionQueue,
- int *pNumPacketsFetched,
- bool PartialBundle)
-{
- int status = 0;
- struct hif_scatter_req *pScatterReq;
- int i, totalLength;
- int pktsToScatter;
- struct htc_packet *pPacket;
- bool asyncMode = (pSyncCompletionQueue == NULL) ? true : false;
- int scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device);
-
- pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue);
- pktsToScatter = min(pktsToScatter, target->MaxMsgPerBundle);
-
- if ((HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue) - pktsToScatter) > 0) {
- /* we were forced to split this bundle receive operation
- * all packets in this partial bundle must have their lookaheads ignored */
- PartialBundle = true;
- /* this would only happen if the target ignored our max bundle limit */
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
- ("HTCIssueRecvPacketBundle : partial bundle detected num:%d , %d \n",
- HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter));
- }
-
- totalLength = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCIssueRecvPacketBundle (Numpackets: %d , actual : %d) \n",
- HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue), pktsToScatter));
-
- do {
-
- pScatterReq = DEV_ALLOC_SCATTER_REQ(&target->Device);
-
- if (pScatterReq == NULL) {
- /* no scatter resources left, just let caller handle it the legacy way */
- break;
- }
-
- pScatterReq->CallerFlags = 0;
-
- if (PartialBundle) {
- /* mark that this is a partial bundle, this has special ramifications to the
- * scatter completion routine */
- pScatterReq->CallerFlags |= HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE;
- }
-
- /* convert HTC packets to scatter list */
- for (i = 0; i < pktsToScatter; i++) {
- int paddedLength;
-
- pPacket = HTC_PACKET_DEQUEUE(pRecvPktQueue);
- A_ASSERT(pPacket != NULL);
-
- paddedLength = DEV_CALC_RECV_PADDED_LEN(&target->Device, pPacket->ActualLength);
-
- if ((scatterSpaceRemaining - paddedLength) < 0) {
- /* exceeds what we can transfer, put the packet back */
- HTC_PACKET_ENQUEUE_TO_HEAD(pRecvPktQueue,pPacket);
- break;
- }
-
- scatterSpaceRemaining -= paddedLength;
-
- if (PartialBundle || (i < (pktsToScatter - 1))) {
- /* packet 0..n-1 cannot be checked for look-aheads since we are fetching a bundle
- * the last packet however can have it's lookahead used */
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD;
- }
-
- /* note: 1 HTC packet per scatter entry */
- /* setup packet into */
- pScatterReq->ScatterList[i].pBuffer = pPacket->pBuffer;
- pScatterReq->ScatterList[i].Length = paddedLength;
-
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_PART_OF_BUNDLE;
-
- if (asyncMode) {
- /* save HTC packet for async completion routine */
- pScatterReq->ScatterList[i].pCallerContexts[0] = pPacket;
- } else {
- /* queue to caller's sync completion queue, caller will unload this when we return */
- HTC_PACKET_ENQUEUE(pSyncCompletionQueue,pPacket);
- }
-
- A_ASSERT(pScatterReq->ScatterList[i].Length);
- totalLength += pScatterReq->ScatterList[i].Length;
- }
-
- pScatterReq->TotalLength = totalLength;
- pScatterReq->ValidScatterEntries = i;
-
- if (asyncMode) {
- pScatterReq->CompletionRoutine = HTCAsyncRecvScatterCompletion;
- pScatterReq->Context = target;
- }
-
- status = DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_READ, asyncMode);
-
- if (!status) {
- *pNumPacketsFetched = i;
- }
-
- if (!asyncMode) {
- /* free scatter request */
- DEV_FREE_SCATTER_REQ(&target->Device, pScatterReq);
- }
-
- } while (false);
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCIssueRecvPacketBundle (status:%d) (fetched:%d) \n",
- status,*pNumPacketsFetched));
-
- return status;
-}
-
-static INLINE void CheckRecvWaterMark(struct htc_endpoint *pEndpoint)
-{
- /* see if endpoint is using a refill watermark
- * ** no need to use a lock here, since we are only inspecting...
- * caller may must not hold locks when calling this function */
- if (pEndpoint->EpCallBacks.RecvRefillWaterMark > 0) {
- if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBuffers) < pEndpoint->EpCallBacks.RecvRefillWaterMark) {
- /* call the re-fill handler before we continue */
- pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext,
- pEndpoint->Id);
- }
- }
-}
-
-/* callback when device layer or lookahead report parsing detects a pending message */
-int HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched)
-{
- struct htc_target *target = (struct htc_target *)Context;
- int status = 0;
- struct htc_packet *pPacket;
- struct htc_endpoint *pEndpoint;
- bool asyncProc = false;
- u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
- int pktsFetched;
- struct htc_packet_queue recvPktQueue, syncCompletedPktsQueue;
- bool partialBundle;
- HTC_ENDPOINT_ID id;
- int totalFetched = 0;
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCRecvMessagePendingHandler NumLookAheads: %d \n",NumLookAheads));
-
- if (pNumPktsFetched != NULL) {
- *pNumPktsFetched = 0;
- }
-
- if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(&target->Device)) {
- /* We use async mode to get the packets if the device layer supports it.
- * The device layer interfaces with HIF in which HIF may have restrictions on
- * how interrupts are processed */
- asyncProc = true;
- }
-
- if (pAsyncProc != NULL) {
- /* indicate to caller how we decided to process this */
- *pAsyncProc = asyncProc;
- }
-
- if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
- A_ASSERT(false);
- return A_EPROTO;
- }
-
- /* on first entry copy the lookaheads into our temp array for processing */
- memcpy(lookAheads, MsgLookAheads, (sizeof(u32)) * NumLookAheads);
-
- while (true) {
-
- /* reset packets queues */
- INIT_HTC_PACKET_QUEUE(&recvPktQueue);
- INIT_HTC_PACKET_QUEUE(&syncCompletedPktsQueue);
-
- if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
- status = A_EPROTO;
- A_ASSERT(false);
- break;
- }
-
- /* first lookahead sets the expected endpoint IDs for all packets in a bundle */
- id = ((struct htc_frame_hdr *)&lookAheads[0])->EndpointID;
- pEndpoint = &target->EndPoint[id];
-
- if (id >= ENDPOINT_MAX) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MsgPend, Invalid Endpoint in look-ahead: %d \n",id));
- status = A_EPROTO;
- break;
- }
-
- /* try to allocate as many HTC RX packets indicated by the lookaheads
- * these packets are stored in the recvPkt queue */
- status = AllocAndPrepareRxPackets(target,
- lookAheads,
- NumLookAheads,
- pEndpoint,
- &recvPktQueue);
- if (status) {
- break;
- }
-
- if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) >= 2) {
- /* a recv bundle was detected, force IRQ status re-check again */
- REF_IRQ_STATUS_RECHECK(&target->Device);
- }
-
- totalFetched += HTC_PACKET_QUEUE_DEPTH(&recvPktQueue);
-
- /* we've got packet buffers for all we can currently fetch,
- * this count is not valid anymore */
- NumLookAheads = 0;
- partialBundle = false;
-
- /* now go fetch the list of HTC packets */
- while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {
-
- pktsFetched = 0;
-
- if (target->RecvBundlingEnabled && (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 1)) {
- /* there are enough packets to attempt a bundle transfer and recv bundling is allowed */
- status = HTCIssueRecvPacketBundle(target,
- &recvPktQueue,
- asyncProc ? NULL : &syncCompletedPktsQueue,
- &pktsFetched,
- partialBundle);
- if (status) {
- break;
- }
-
- if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) != 0) {
- /* we couldn't fetch all packets at one time, this creates a broken
- * bundle */
- partialBundle = true;
- }
- }
-
- /* see if the previous operation fetched any packets using bundling */
- if (0 == pktsFetched) {
- /* dequeue one packet */
- pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue);
- A_ASSERT(pPacket != NULL);
-
- if (asyncProc) {
- /* we use async mode to get the packet if the device layer supports it
- * set our callback and context */
- pPacket->Completion = HTCRecvCompleteHandler;
- pPacket->pContext = target;
- } else {
- /* fully synchronous */
- pPacket->Completion = NULL;
- }
-
- if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) > 0) {
- /* lookaheads in all packets except the last one in the bundle must be ignored */
- pPacket->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_IGNORE_LOOKAHEAD;
- }
-
- /* go fetch the packet */
- status = HTCIssueRecv(target, pPacket);
- if (status) {
- break;
- }
-
- if (!asyncProc) {
- /* sent synchronously, queue this packet for synchronous completion */
- HTC_PACKET_ENQUEUE(&syncCompletedPktsQueue,pPacket);
- }
-
- }
-
- }
-
- if (!status) {
- CheckRecvWaterMark(pEndpoint);
- }
-
- if (asyncProc) {
- /* we did this asynchronously so we can get out of the loop, the asynch processing
- * creates a chain of requests to continue processing pending messages in the
- * context of callbacks */
- break;
- }
-
- /* synchronous handling */
- if (target->Device.DSRCanYield) {
- /* for the SYNC case, increment count that tracks when the DSR should yield */
- target->Device.CurrentDSRRecvCount++;
- }
-
- /* in the sync case, all packet buffers are now filled,
- * we can process each packet, check lookaheads and then repeat */
-
- /* unload sync completion queue */
- while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
- struct htc_packet_queue container;
-
- pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue);
- A_ASSERT(pPacket != NULL);
-
- pEndpoint = &target->EndPoint[pPacket->Endpoint];
- /* reset count on each iteration, we are only interested in the last packet's lookahead
- * information when we break out of this loop */
- NumLookAheads = 0;
- /* process header for each of the recv packets
- * note: the lookahead of the last packet is useful for us to continue in this loop */
- status = HTCProcessRecvHeader(target,pPacket,lookAheads,&NumLookAheads);
- if (status) {
- break;
- }
-
- if (HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
- /* last packet's more packets flag is set based on the lookahead */
- SET_MORE_RX_PACKET_INDICATION_FLAG(lookAheads,NumLookAheads,pEndpoint,pPacket);
- } else {
- /* packets in a bundle automatically have this flag set */
- FORCE_MORE_RX_PACKET_INDICATION_FLAG(pPacket);
- }
- /* good packet, indicate it */
- HTC_RX_STAT_PROFILE(target,pEndpoint,NumLookAheads);
-
- if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_PART_OF_BUNDLE) {
- INC_HTC_EP_STAT(pEndpoint, RxPacketsBundled, 1);
- }
-
- INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
- DO_RCV_COMPLETION(pEndpoint,&container);
- }
-
- if (status) {
- break;
- }
-
- if (NumLookAheads == 0) {
- /* no more look aheads */
- break;
- }
-
- /* when we process recv synchronously we need to check if we should yield and stop
- * fetching more packets indicated by the embedded lookaheads */
- if (target->Device.DSRCanYield) {
- if (DEV_CHECK_RECV_YIELD(&target->Device)) {
- /* break out, don't fetch any more packets */
- break;
- }
- }
-
-
- /* check whether other OS contexts have queued any WMI command/data for WLAN.
- * This check is needed only if WLAN Tx and Rx happens in same thread context */
- A_CHECK_DRV_TX();
-
- /* for SYNCH processing, if we get here, we are running through the loop again due to a detected lookahead.
- * Set flag that we should re-check IRQ status registers again before leaving IRQ processing,
- * this can net better performance in high throughput situations */
- REF_IRQ_STATUS_RECHECK(&target->Device);
- }
-
- if (status) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
- ("Failed to get pending recv messages (%d) \n",status));
- /* cleanup any packets we allocated but didn't use to actually fetch any packets */
- while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {
- pPacket = HTC_PACKET_DEQUEUE(&recvPktQueue);
- /* clean up packets */
- HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]);
- }
- /* cleanup any packets in sync completion queue */
- while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
- pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue);
- /* clean up packets */
- HTC_RECYCLE_RX_PKT(target, pPacket, &target->EndPoint[pPacket->Endpoint]);
- }
- if (HTC_STOPPING(target)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
- (" Host is going to stop. blocking receiver for HTCStop.. \n"));
- DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC);
- }
- }
- /* before leaving, check to see if host ran out of buffers and needs to stop the
- * receiver */
- if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
- (" Host has no RX buffers, blocking receiver to prevent overrun.. \n"));
- /* try to stop receive at the device layer */
- DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC);
- }
-
- if (pNumPktsFetched != NULL) {
- *pNumPktsFetched = totalFetched;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCRecvMessagePendingHandler \n"));
-
- return status;
-}
-
-int HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- struct htc_endpoint *pEndpoint;
- bool unblockRecv = false;
- int status = 0;
- struct htc_packet *pFirstPacket;
-
- 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));
-
- do {
-
- pEndpoint = &target->EndPoint[pFirstPacket->Endpoint];
-
- LOCK_HTC_RX(target);
-
- if (HTC_STOPPING(target)) {
- struct htc_packet *pPacket;
-
- UNLOCK_HTC_RX(target);
-
- /* 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;
-
- DO_RCV_COMPLETION(pEndpoint,pPktQueue);
- break;
- }
-
- /* store receive packets */
- HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBuffers, pPktQueue);
-
- /* check if we are blocked waiting for a new buffer */
- if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) {
- if (target->EpWaitingForBuffers == pFirstPacket->Endpoint) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" receiver was blocked on ep:%d, unblocking.. \n",
- target->EpWaitingForBuffers));
- target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
- target->EpWaitingForBuffers = ENDPOINT_MAX;
- unblockRecv = true;
- }
- }
-
- UNLOCK_HTC_RX(target);
-
- if (unblockRecv && !HTC_STOPPING(target)) {
- /* TODO : implement a buffer threshold count? */
- DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
- }
-
- } while (false);
-
- return status;
-}
-
-/* Makes a buffer available to the HTC module */
-int HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket)
-{
- struct htc_packet_queue queue;
- INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
- return HTCAddReceivePktMultiple(HTCHandle, &queue);
-}
-
-void HTCUnblockRecv(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- bool unblockRecv = false;
-
- LOCK_HTC_RX(target);
-
- /* check if we are blocked waiting for a new buffer */
- if (target->RecvStateFlags & HTC_RECV_WAIT_BUFFERS) {
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HTCUnblockRx : receiver was blocked on ep:%d, unblocking.. \n",
- target->EpWaitingForBuffers));
- target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
- target->EpWaitingForBuffers = ENDPOINT_MAX;
- unblockRecv = true;
- }
-
- UNLOCK_HTC_RX(target);
-
- if (unblockRecv && !HTC_STOPPING(target)) {
- /* re-enable */
- DevEnableRecv(&target->Device,DEV_ENABLE_RECV_ASYNC);
- }
-}
-
-static void HTCFlushRxQueue(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet_queue *pQueue)
-{
- struct htc_packet *pPacket;
- struct htc_packet_queue container;
-
- LOCK_HTC_RX(target);
-
- while (1) {
- pPacket = HTC_PACKET_DEQUEUE(pQueue);
- if (NULL == pPacket) {
- break;
- }
- UNLOCK_HTC_RX(target);
- pPacket->Status = A_ECANCELED;
- pPacket->ActualLength = 0;
- AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" Flushing RX packet:0x%lX, length:%d, ep:%d \n",
- (unsigned long)pPacket, pPacket->BufferLength, pPacket->Endpoint));
- INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
- /* give the packet back */
- DO_RCV_COMPLETION(pEndpoint,&container);
- LOCK_HTC_RX(target);
- }
-
- UNLOCK_HTC_RX(target);
-}
-
-static void HTCFlushEndpointRX(struct htc_target *target, struct htc_endpoint *pEndpoint)
-{
- /* flush any recv indications not already made */
- HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RecvIndicationQueue);
- /* flush any rx buffers */
- HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RxBuffers);
-}
-
-void HTCFlushRecvBuffers(struct htc_target *target)
-{
- struct htc_endpoint *pEndpoint;
- int i;
-
- for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
- pEndpoint = &target->EndPoint[i];
- if (pEndpoint->ServiceID == 0) {
- /* not in use.. */
- continue;
- }
- HTCFlushEndpointRX(target,pEndpoint);
- }
-}
-
-
-void HTCEnableRecv(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-
- if (!HTC_STOPPING(target)) {
- /* re-enable */
- DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
- }
-}
-
-void HTCDisableRecv(HTC_HANDLE HTCHandle)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-
- if (!HTC_STOPPING(target)) {
- /* disable */
- DevStopRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
- }
-}
-
-int HTCGetNumRecvBuffers(HTC_HANDLE HTCHandle,
- HTC_ENDPOINT_ID Endpoint)
-{
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
- return HTC_PACKET_QUEUE_DEPTH(&(target->EndPoint[Endpoint].RxBuffers));
-}
-
-int HTCWaitForPendingRecv(HTC_HANDLE HTCHandle,
- u32 TimeoutInMs,
- bool *pbIsRecvPending)
-{
- int status = 0;
- struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-
- status = DevWaitForPendingRecv(&target->Device,
- TimeoutInMs,
- pbIsRecvPending);
-
- return status;
-}