Пример #1
0
void HTCFlushRxHoldQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
{
    HTC_PACKET       *pPacket;
    HTC_PACKET_QUEUE container;

    LOCK_HTC_RX(target);

    while (1) {
        pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBufferHoldQueue);
        if (NULL == pPacket) {
            break;
        }
        UNLOCK_HTC_RX(target);
        pPacket->Status = A_ECANCELED;
        pPacket->ActualLength = 0;
        AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("  Flushing RX packet:%p, length:%d, ep:%d \n",
                pPacket, pPacket->BufferLength, pPacket->Endpoint));
        INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
            /* give the packet back */
        DoRecvCompletion(pEndpoint,&container);
        LOCK_HTC_RX(target);
    }

    UNLOCK_HTC_RX(target);
}
Пример #2
0
static void HTCFlushEndpointRX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
{
    HTC_PACKET  *pPacket;

    LOCK_HTC_RX(target);

    while (1) {
        pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
        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%X, length:%d, ep:%d \n",
                (A_UINT32)pPacket, pPacket->BufferLength, pPacket->Endpoint));
            /* give the packet back */
        pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext,
                                      pPacket);
        LOCK_HTC_RX(target);
    }

    UNLOCK_HTC_RX(target);


}
Пример #3
0
/*flush all queued buffers for surpriseremove case*/
void htc_flush_surprise_remove(HTC_HANDLE HTCHandle)
{
	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
	int i;
	HTC_ENDPOINT *pEndpoint;
#ifdef RX_SG_SUPPORT
	cdf_nbuf_t netbuf;
	cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
#endif

	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove \n"));

	/* cleanup endpoints */
	for (i = 0; i < ENDPOINT_MAX; i++) {
		pEndpoint = &target->EndPoint[i];
		htc_flush_rx_hold_queue(target, pEndpoint);
		htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
	}

	hif_flush_surprise_remove(target->hif_dev);

#ifdef RX_SG_SUPPORT
	LOCK_HTC_RX(target);
	while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) {
		cdf_nbuf_free(netbuf);
	}
	RESET_RX_SG_CONFIG(target);
	UNLOCK_HTC_RX(target);
#endif

	reset_endpoint_states(target);

	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove \n"));
}
Пример #4
0
    /* polling routine to wait for a control packet to be received */
A_STATUS HTCWaitRecvCtrlMessage(HTC_TARGET *target)
{
//    int count = HTC_TARGET_MAX_RESPONSE_POLL;

    AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HTCWaitCtrlMessageRecv\n"));

    /* Wait for BMI request/response transaction to complete */
    while (adf_os_mutex_acquire(target->osdev, &target->CtrlResponseValid)) {
    }

    LOCK_HTC_RX(target);
    /* caller will clear this flag */
    target->CtrlResponseProcessing = TRUE;

    UNLOCK_HTC_RX(target);

#if 0
    while (count > 0) {

        LOCK_HTC_RX(target);

        if (target->CtrlResponseValid) {
            target->CtrlResponseValid = FALSE;
                /* caller will clear this flag */
            target->CtrlResponseProcessing = TRUE;
            UNLOCK_HTC_RX(target);
            break;
        }

        UNLOCK_HTC_RX(target);

        count--;
        A_MSLEEP(HTC_TARGET_RESPONSE_POLL_MS);
    }

    if (count <= 0) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("-HTCWaitCtrlMessageRecv: Timeout!\n"));
        return A_ECOMM;
    }
#endif

    AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HTCWaitCtrlMessageRecv success\n"));
    return A_OK;
}
Пример #5
0
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;
}
Пример #6
0
A_BOOL htc_get_endpoint_statistics(HTC_HANDLE HTCHandle,
				   HTC_ENDPOINT_ID Endpoint,
				   HTC_ENDPOINT_STAT_ACTION Action,
				   HTC_ENDPOINT_STATS *pStats)
{
#ifdef HTC_EP_STAT_PROFILING
	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
	A_BOOL clearStats = false;
	A_BOOL sample = false;

	switch (Action) {
	case HTC_EP_STAT_SAMPLE:
		sample = true;
		break;
	case HTC_EP_STAT_SAMPLE_AND_CLEAR:
		sample = true;
		clearStats = true;
		break;
	case HTC_EP_STAT_CLEAR:
		clearStats = true;
		break;
	default:
		break;
	}

	A_ASSERT(Endpoint < ENDPOINT_MAX);

	/* lock out TX and RX while we sample and/or clear */
	LOCK_HTC_TX(target);
	LOCK_HTC_RX(target);

	if (sample) {
		A_ASSERT(pStats != NULL);
		/* return the stats to the caller */
		A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats,
			 sizeof(HTC_ENDPOINT_STATS));
	}

	if (clearStats) {
		/* reset stats */
		A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats,
			  sizeof(HTC_ENDPOINT_STATS));
	}

	UNLOCK_HTC_RX(target);
	UNLOCK_HTC_TX(target);

	return true;
#else
	return false;
#endif
}
Пример #7
0
/* Makes a buffer available to the HTC module */
A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
{
    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
    HTC_ENDPOINT *pEndpoint;
    A_BOOL       unblockRecv = FALSE;
    A_STATUS     status = A_OK;

    AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
                    ("+- HTCAddReceivePkt: endPointId: %d, buffer: 0x%X, length: %d\n",
                    pPacket->Endpoint, (A_UINT32)pPacket->pBuffer, pPacket->BufferLength));

    do {
        AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);

        pEndpoint = &target->EndPoint[pPacket->Endpoint];

        LOCK_HTC_RX(target);

        if (HTC_STOPPING(target)) {
            pPacket->Status = A_ECANCELED;
            status = A_ECANCELED;
            UNLOCK_HTC_RX(target);
            pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket);
            break;
        }

            /* store receive packet */
        HTC_PACKET_ENQUEUE(&pEndpoint->RxBuffers, pPacket);

            /* check if we are blocked waiting for a new buffer */
        if (target->HTCStateFlags & HTC_STATE_WAIT_BUFFERS) {
            if (target->EpWaitingForBuffers == pPacket->Endpoint) {
                AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" receiver was blocked on ep:%d, unblocking.. \n",
                    target->EpWaitingForBuffers));
                target->HTCStateFlags &= ~HTC_STATE_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;
}
Пример #8
0
void FreeHTCPacketContainer(HTC_TARGET *target, HTC_PACKET *pPacket)
{
    LOCK_HTC_RX(target);

    if (NULL == target->pHTCPacketStructPool) {
        target->pHTCPacketStructPool = pPacket;
        pPacket->ListLink.pNext = NULL;
    } else {
        pPacket->ListLink.pNext = (DL_LIST *)target->pHTCPacketStructPool;
        target->pHTCPacketStructPool = pPacket;
    }

    UNLOCK_HTC_RX(target);
}
Пример #9
0
/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
void htc_stop(HTC_HANDLE HTCHandle)
{
	HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
	int i;
	HTC_ENDPOINT *pEndpoint;
#ifdef RX_SG_SUPPORT
	cdf_nbuf_t netbuf;
	cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
#endif

	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop \n"));

	/* cleanup endpoints */
	for (i = 0; i < ENDPOINT_MAX; i++) {
		pEndpoint = &target->EndPoint[i];
		htc_flush_rx_hold_queue(target, pEndpoint);
		htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
		if (pEndpoint->ul_is_polled) {
			cdf_softirq_timer_cancel(&pEndpoint->ul_poll_timer);
			cdf_softirq_timer_free(&pEndpoint->ul_poll_timer);
		}
	}

	/* Note: htc_flush_endpoint_tx for all endpoints should be called before
	 * hif_stop - otherwise htc_tx_completion_handler called from
	 * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer,
	 * might queue the packet again to HIF Layer - which could cause tx
	 * buffer leak
	 */

	hif_stop(target->hif_dev);

#ifdef RX_SG_SUPPORT
	LOCK_HTC_RX(target);
	while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) {
		cdf_nbuf_free(netbuf);
	}
	RESET_RX_SG_CONFIG(target);
	UNLOCK_HTC_RX(target);
#endif

	reset_endpoint_states(target);

	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop \n"));
}
Пример #10
0
HTC_PACKET *AllocateHTCPacketContainer(HTC_TARGET *target)
{
    HTC_PACKET *pPacket;

    LOCK_HTC_RX(target);

    if (NULL == target->pHTCPacketStructPool) {
        UNLOCK_HTC_RX(target);
        return NULL;
    }

    pPacket = target->pHTCPacketStructPool;
    target->pHTCPacketStructPool = (HTC_PACKET *)pPacket->ListLink.pNext;

    UNLOCK_HTC_RX(target);

    pPacket->ListLink.pNext = NULL;
    return pPacket;
}
Пример #11
0
/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
void HTCStop(HTC_HANDLE HTCHandle)
{
    HTC_TARGET    *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
    int           i;
    HTC_ENDPOINT  *pEndpoint;
#ifdef RX_SG_SUPPORT
    adf_nbuf_t netbuf;
    adf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
#endif

    AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n"));

        /* cleanup endpoints */
    for (i = 0; i < ENDPOINT_MAX; i++) {
        pEndpoint = &target->EndPoint[i];
        HTCFlushRxHoldQueue(target,pEndpoint);
        HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL);
    }

    /* Note: HTCFlushEndpointTX for all endpoints should be called before
     * HIFStop - otherwise HTCTxCompletionHandler called from
     * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer,
     * might queue the packet again to HIF Layer - which could cause tx
     * buffer leak
     */

    HIFStop(target->hif_dev);

#ifdef RX_SG_SUPPORT
    LOCK_HTC_RX(target);
    while ((netbuf = adf_nbuf_queue_remove(rx_sg_queue)) != NULL) {
        adf_nbuf_free(netbuf);
    }
    RESET_RX_SG_CONFIG(target);
    UNLOCK_HTC_RX(target);
#endif

    ResetEndpointStates(target);

    AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
}
Пример #12
0
/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
void HTCStop(HTC_HANDLE HTCHandle)
{
    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
    AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n"));

    LOCK_HTC_RX(target);
        /* mark that we are shutting down .. */
    target->HTCStateFlags |= HTC_STATE_STOPPING;
    UNLOCK_HTC_RX(target);
    
        /* Masking interrupts is a synchronous operation, when this function returns
         * all pending HIF I/O has completed, we can safely flush the queues */
    DevMaskInterrupts(&target->Device);

        /* flush all send packets */
    HTCFlushSendPkts(target);
        /* flush all recv buffers */
    HTCFlushRecvBuffers(target);

    ResetEndpointStates(target);
   
    AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
}
Пример #13
0
void HTCUnblockRecv(HTC_HANDLE HTCHandle)
{
    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
    A_BOOL      unblockRecv = FALSE;

    LOCK_HTC_RX(target);

        /* check if we are blocked waiting for a new buffer */
    if (target->HTCStateFlags & HTC_STATE_WAIT_BUFFERS) {
        AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HTCUnblockRx : receiver was blocked on ep:%d, unblocking.. \n",
            target->EpWaitingForBuffers));
        target->HTCStateFlags &= ~HTC_STATE_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);
    }
}
Пример #14
0
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);
        pEndpoint = &target->EndPoint[htc_ep_id];

        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;
            break;
        }

        /*
         * 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 =%d\n",
                netlen, payloadLen + HTC_HDR_LENGTH));
            DebugDumpBytes((A_UINT8 *)HtcHdr,sizeof(HTC_FRAME_HDR),"BAD RX packet length");
            status = A_ERROR;
            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,
                        ("HTCProcessRecvHeader, 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;

                /* 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;
                    break;
                }

                LOCK_HTC_RX(target);
                target->CtrlResponseLength = min((int)netlen,HTC_MAX_CONTROL_MESSAGE_LENGTH);
                A_MEMCPY(target->CtrlResponseBuffer,netdata,target->CtrlResponseLength);
                UNLOCK_HTC_RX(target);

                adf_os_mutex_release(target->osdev, &target->CtrlResponseValid);
                break;
            case HTC_MSG_SEND_SUSPEND_COMPLETE:
                target->HTCInitInfo.TargetSendSuspendComplete(target->HTCInitInfo.pContext);
                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;

            /* TODO : this is a hack because the driver layer will set the actual length
             * of the skb again which will just double the length */
        //A_NETBUF_TRIM(netbuf,netlen);
        adf_nbuf_trim_tail(netbuf, netlen);

        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;

}
Пример #15
0
/* callback when device layer or lookahead report parsing detects a pending message */
A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 *LookAhead, A_BOOL *pAsyncProc)
{
    HTC_TARGET      *target = (HTC_TARGET *)Context;
    A_STATUS         status = A_OK;
    HTC_PACKET      *pPacket = NULL;
    HTC_FRAME_HDR   *pHdr = NULL;
    HTC_ENDPOINT    *pEndpoint = NULL;
    A_BOOL          asyncProc = FALSE;

    AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCRecvMessagePendingHandler LookAhead:0x%X \n", *LookAhead));
    
    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;
    }

    while (TRUE) {
        pHdr = (HTC_FRAME_HDR *)LookAhead;

        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->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n",
                    pHdr->PayloadLen, HTC_MAX_PAYLOAD_LENGTH));
            status = A_EPROTO;
            break;
        }

        pEndpoint = &target->EndPoint[pHdr->EndpointID];

        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 (pEndpoint->EpCallBacks.EpRecvAlloc != NULL) {
                /* user is using a per-packet allocation callback */
            pPacket = pEndpoint->EpCallBacks.EpRecvAlloc(pEndpoint->EpCallBacks.pContext,
                                                         (HTC_ENDPOINT_ID) pHdr->EndpointID,
                                                         pHdr->PayloadLen + sizeof(HTC_FRAME_HDR));

                /* lock RX, in case this allocation fails, we need to update internal state below */

            LOCK_HTC_RX(target);

        } else {
                /* user is using a refill handler that can refill multiple HTC buffers */
                /* lock RX to get a buffer */
            LOCK_HTC_RX(target);

                /* 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,
                                                        (HTC_ENDPOINT_ID) pHdr->EndpointID);
                    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->HTCStateFlags |= HTC_STATE_WAIT_BUFFERS;
            target->EpWaitingForBuffers = (HTC_ENDPOINT_ID) pHdr->EndpointID;
            status = A_NO_MEMORY;
        }

        if (HTC_STOPPING(target)) {
            status = A_ECANCELED;
        }

        UNLOCK_HTC_RX(target);

        if (A_FAILED(status)) {
            /* no buffers or stopping */
            break;
        }

        pPacket->PktInfo.AsRx.IndicationFlags = 0;

        AR_DEBUG_ASSERT(pPacket->Endpoint == pHdr->EndpointID);

            /* make sure this message can fit in the endpoint buffer */
        if ((pHdr->PayloadLen + HTC_HDR_LENGTH) > pPacket->BufferLength) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                    ("Payload Length Error : header reports payload of: %d, endpoint buffer size: %d \n",
                    pHdr->PayloadLen, pPacket->BufferLength));
            status = A_EPROTO;
            break;
        }

        pPacket->HTCReserved = *LookAhead; /* set expected look ahead */
            /* set the amount of data to fetch */
        pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;

        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;
        }

            /* go fetch the packet */
        status = HTCIssueRecv(target, pPacket);

        if (A_FAILED(status)) {
            break;
        }

        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;
        }

            /* in the sync case, we process the packet, check lookaheads and then repeat */

        *LookAhead = 0;
        status = HTCProcessRecvHeader(target,pPacket,LookAhead);

        if (A_FAILED(status)) {
            break;
        }

        HTC_RX_STAT_PROFILE(target,pEndpoint,*LookAhead);

            /* check lookahead to see if we can indicate next packet hint to recv callback */
        if (LookAhead != 0) {
            pHdr = (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
                     * NOTE: no need to lock RX here , since we are synchronously processing RX
                     * and we are only looking at the queue (not modifying it) */
                if (!HTC_QUEUE_EMPTY(&pEndpoint->RxBuffers)) {                        
                        /* provide a hint that there are more RX packets to fetch */
                    pPacket->PktInfo.AsRx.IndicationFlags |= HTC_RX_FLAGS_INDICATE_MORE_PKTS;        
                }             
            }                  
        }
        
        DO_RCV_COMPLETION(target,pPacket,pEndpoint);

        pPacket = NULL;

        if (0 == *LookAhead) {
            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();
    }

    if (A_NO_MEMORY == status) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                (" Endpoint :%d has no buffers, blocking receiver to prevent overrun.. \n",
                (pHdr != NULL) ? pHdr->EndpointID : 0xFFFF));
            /* try to stop receive at the device layer */
        DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC);
        status = A_OK;
    } else if (A_FAILED(status)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                        ("Failed to get pending message : LookAhead Value: 0x%X (status = %d) \n",
                        *LookAhead, status));
        if (pPacket != NULL) {
                /* clean up packet on error */
            HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
        }
    }

    AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCRecvMessagePendingHandler \n"));

    return status;
}