Example #1
0
    /* callback when a control message arrives on this endpoint */
void HTCControlRecv(void *Context, HTC_PACKET *pPacket)
{
    AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0);

    if (pPacket->Status == A_ECANCELED) {
        /* this is a flush operation, return the control packet back to the pool */
        HTC_FREE_CONTROL_RX((HTC_TARGET*)Context,pPacket);    
        return;
    }  
    
        /* the only control messages we are expecting are NULL messages (credit resports) */   
    if (pPacket->ActualLength > 0) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                        ("HTCControlRecv, got message with length:%d \n",
                        pPacket->ActualLength + (A_UINT32)HTC_HDR_LENGTH));

#ifdef ATH_DEBUG_MODULE
            /* dump header and message */
        DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH,
                       pPacket->ActualLength + HTC_HDR_LENGTH,
                       "Unexpected ENDPOINT 0 Message");
#endif
    }

    HTC_RECYCLE_RX_PKT((HTC_TARGET*)Context,pPacket,&((HTC_TARGET*)Context)->EndPoint[0]);
}
/****************************************************
 * Invoked from bluetooth stack via hdev->send()
 * to send the packet out via ar6k to PAL firmware.
 *
 * For HCI command packet wmi_send_hci_cmd() is invoked.
 * wmi_send_hci_cmd adds WMI_CMD_HDR and sends the packet
 * to PAL firmware.
 *
 * For HCI ACL data packet wmi_data_hdr_add is invoked
 * to add WMI_DATA_HDR to the packet.  ar6000_acl_data_tx
 * is then invoked to send the packet to PAL firmware.
 ******************************************************/
static int btpal_send_frame(struct sk_buff *skb)
{
	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
	HCI_TRANSPORT_PACKET_TYPE type;
	ar6k_hci_pal_info_t *pHciPalInfo;
	A_STATUS status = A_OK;
	struct sk_buff *txSkb = NULL;
	AR_SOFTC_DEV_T *ar;

	if (!hdev) {
		PRIN_LOG("HCI PAL: btpal_send_frame - no device\n");
		return -ENODEV;
	}

	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
		PRIN_LOG("HCI PAL: btpal_send_frame - not open\n");
		return -EBUSY;
	}

	pHciPalInfo = (ar6k_hci_pal_info_t *)hdev->driver_data;
	A_ASSERT(pHciPalInfo != NULL);
	ar = pHciPalInfo->ar;

	PRIN_LOG("+btpal_send_frame type: %d \n",bt_cb(skb)->pkt_type);
	type = HCI_COMMAND_TYPE;

	switch (bt_cb(skb)->pkt_type) {
		case HCI_COMMAND_PKT:
			type = HCI_COMMAND_TYPE;
			hdev->stat.cmd_tx++;
			break;

		case HCI_ACLDATA_PKT:
			type = HCI_ACL_TYPE;
			hdev->stat.acl_tx++;
			break;

		case HCI_SCODATA_PKT:
			/* we don't support SCO over the pal */
			kfree_skb(skb);
			return 0;
		default:
			A_ASSERT(FALSE);
			kfree_skb(skb);
			return 0;
	}

    	if(loghci) {
		A_PRINTF(">>> Send HCI %s packet len: %d\n",
				(type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL",
				skb->len);
		if (type == HCI_COMMAND_TYPE) {
			A_PRINTF("HCI Command: OGF:0x%X OCF:0x%X \r\n",
				(HCI_GET_OP_CODE(skb->data)) >> 10, 
				(HCI_GET_OP_CODE(skb->data)) & 0x3FF);
		}
		DebugDumpBytes(skb->data,skb->len,"BT HCI SEND Packet Dump");
	}
Example #3
0
static A_STATUS wmi_cmd_send(A_UINT8 *pBuffer, int Length, WMI_COMMAND_ID cmdId)
{
    WMI_CMD_HDR *cHdr;

    A_ASSERT(pBuffer != NULL);

    pBuffer -= sizeof(WMI_CMD_HDR); /* caller always provides headroom */
    Length += sizeof(WMI_CMD_HDR);
    cHdr = (WMI_CMD_HDR *)pBuffer;
    cHdr->commandId = cmdId;

    AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI Send Command : 0x%X (%d) len:%d \n",cmdId,cmdId, Length));
    
    if (g_WMIloggingReq) {
        DebugDumpBytes(pBuffer, Length, "WMI Send Buffer Dump");  
    }
    
    return HTCSendMsg(g_HTCHandle, 
                      g_WMIControlEp, 
                      pBuffer, 
                      Length);

}
Example #4
0
static int ProcessCreditCounterReadBuffer(u8 *pBuffer, int Length)
{
    int     credits = 0;
    
    /* theory of how this works:
     * We read the credit decrement register multiple times on a byte-wide basis. 
     * The number of times (32) aligns the I/O operation to be a multiple of 4 bytes and provides a 
     * reasonable chance to acquire "all" pending credits in a single I/O operation. 
     * 
     * Once we obtain the filled buffer, we can walk through it looking for credit decrement transitions.
     * Each non-zero byte represents a single credit decrement (which is a credit given back to the host)
     * For example if the target provides 3 credits and added 4 more during the 32-byte read operation the following
     * pattern "could" appear:
     * 
     *    0x3 0x2 0x1 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x1 0x0 0x1 0x0 0x1 0x0 ......rest zeros
     *    <--------->                     <----------------------------->
     *         \_ credits aleady there              \_ target adding 4 more credits
     * 
     *    The total available credits would be 7, since there are 7 non-zero bytes in the buffer.
     * 
     * */
    
    if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
        DebugDumpBytes(pBuffer, Length, "GMBOX Credit read buffer");
    } 
        
    while (Length) {
        if (*pBuffer != 0) {
            credits++;    
        }
        Length--;
        pBuffer++;   
    }  
    
    return credits;
}
Example #5
0
static A_STATUS HTCProcessTrailer(HTC_TARGET     *target,
                                  A_UINT8        *pBuffer,
                                  int             Length,
                                  HTC_ENDPOINT_ID FromEndpoint)
{
    HTC_RECORD_HDR          *pRecord;
    A_UINT8                 htc_rec_id;
    A_UINT8                 htc_rec_len;
    A_UINT8                 *pRecordBuf;
    A_UINT8                 *pOrigBuffer;
    int                     origLength;
    A_STATUS                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 = A_OK;

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

        htc_rec_len = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, LENGTH);
        htc_rec_id = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, RECORDID);

        if (htc_rec_len > 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",
                        htc_rec_len, htc_rec_id, Length));
            status = A_EPROTO;
            break;
        }
            /* start of record follows the header */
        pRecordBuf = pBuffer;

        switch (htc_rec_id) {
            case HTC_RECORD_CREDITS:
                AR_DEBUG_ASSERT(htc_rec_len >= sizeof(HTC_CREDIT_REPORT));
                HTCProcessCreditRpt(target,
                                    (HTC_CREDIT_REPORT *)pRecordBuf,
                                    htc_rec_len / (sizeof(HTC_CREDIT_REPORT)),
                                    FromEndpoint);
                break;
            default:
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n",
                        htc_rec_id, htc_rec_len));
                break;
        }

        if (A_FAILED(status)) {
            break;
        }

            /* advance buffer past this record for next time around */
        pBuffer += htc_rec_len; 
        Length -= htc_rec_len;
    }

    if (A_FAILED(status)) {
        DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer");
    }

    AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n"));
    return status;

}
Example #6
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;

}
Example #7
0
A_STATUS wmi_control_rx(A_UINT8 *pBuffer, int Length)
{
    WMI_CMD_HDR *cmd;
    A_UINT16 id;
    A_UINT8 *datap;
    A_UINT32 len;
    A_STATUS status = A_OK;
    A_CHAR *pWmiDumpStr = "WMI message payload";

    if (Length < sizeof(WMI_CMD_HDR)) { 
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, 
               ("WMI: invalid length: %d \n",Length));
        return A_ERROR;
    }

    cmd = (WMI_CMD_HDR *)pBuffer;
    id = cmd->commandId;
    datap = pBuffer + sizeof(WMI_CMD_HDR);
    len = Length - sizeof(WMI_CMD_HDR);
    
    AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("---- WMI recv, MsgNo %d, Event ID: 0x%X (%d) ---------------------------\n", 
            cmdRecvNum, id , id));
            
    cmdRecvNum++;
    
    switch (id) {
   
        case (WMI_READY_EVENTID):
            {
                WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
                AR_DEBUG_PRINTF(ATH_DEBUG_WMI,("WMI_READY_EVENTID\n"));
                if (len < sizeof(WMI_READY_EVENT)) {
                    return A_EINVAL;
                }
                A_MEMCPY(g_MACAddress, ev->macaddr, ATH_MAC_LEN);          
                ar6000_ready_event(ev->macaddr, ev->phyCapability);

            }
            break;
     
        case (WMI_CONNECT_EVENTID):
            {
                WMI_CONNECT_EVENT *ev;
                
                AR_DEBUG_PRINTF(ATH_DEBUG_WMI,("WMI_CONNECT_EVENTID \n"));
                
                if (len < sizeof(WMI_CONNECT_EVENT)) {
                    return A_EINVAL;
                }
                ev = (WMI_CONNECT_EVENT *)datap;
                            
                A_MEMCPY(g_bssid, ev->bssid, ATH_MAC_LEN);
            
                ar6000_connect_event(ev->channel, ev->bssid,
                                     ev->listenInterval, ev->beaconInterval,
                                     ev->networkType, ev->beaconIeLen,
                                     ev->assocReqLen, ev->assocRespLen,
                                     ev->assocInfo);
            }                         
            break;
     
        case (WMI_DISCONNECT_EVENTID):
            {
                WMI_DISCONNECT_EVENT *ev;
            
                if (len < sizeof(WMI_DISCONNECT_EVENT)) {
                    return A_EINVAL;
                }
            
                ev = (WMI_DISCONNECT_EVENT *)datap;
            
                A_MEMZERO(g_bssid, ATH_MAC_LEN);
            
                ar6000_disconnect_event(ev->disconnectReason, ev->bssid,
                                        ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
            }
            break;
       
        case (WMI_REGDOMAIN_EVENTID):  
            {
                WMI_REG_DOMAIN_EVENT *ev;

                AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI_REGDOMAIN_EVENTID\n"));      
                
                if (len < sizeof(*ev)) {
                    return A_EINVAL;
                }
                ev = (WMI_REG_DOMAIN_EVENT *)datap;
            
                ar6000_regDomain_event(ev->regDomain);
            }            
            
            break;
     
        case (WMI_EXTENSION_EVENTID):
            {
                A_UINT16 extId = datap[0] | ((A_UINT16)datap[1]) << 8;
                
                datap += sizeof(WMIX_CMD_HDR);
                len -= sizeof(WMIX_CMD_HDR);
                
                AR_DEBUG_PRINTF(ATH_DEBUG_WMI, 
                    ("WMI_EXTENSION_EVENTID - id: 0x%X (%d) length:%d \n",extId, extId, len));
                pWmiDumpStr = "WMI Extended Message payload";
            }
            break;
        
        case (WMI_REPORT_STATISTICS_EVENTID) :
            {
                WMI_TARGET_STATS *reply;

                AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI_EXTENSION_EVENTID\n"));     
                                
                if (len < sizeof(*reply)) {
                    return A_EINVAL;
                }
                
                reply = (WMI_TARGET_STATS *)datap;
        
                ar6000_targetStats_event(reply);   
            }
                     
        default:
            AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("UNHANDLED WMI EVENT : 0x%X (%d) \n",id,id));
            break;
    }

    AR_DEBUG_PRINTF(ATH_DEBUG_WMI, 
      ("------------------------------------------------------------------------------------\n"));
        
    if (g_WMIloggingReq) {
        DebugDumpBytes(datap, len, pWmiDumpStr);  
    }
    
    return status;
}
Example #8
0
static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
                                         A_UINT8    *pBuffer,
                                         int         Length,
                                         A_UINT32   *pNextLookAhead,
                                         HTC_ENDPOINT_ID FromEndpoint)
{
    HTC_RECORD_HDR          *pRecord;
    A_UINT8                 *pRecordBuf;
    HTC_LOOKAHEAD_REPORT    *pLookAhead;
    A_UINT8                 *pOrigBuffer;
    int                     origLength;
    A_STATUS                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 = A_OK;

    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)) &&
                    (pNextLookAhead != 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 */
                    ((A_UINT8 *)pNextLookAhead)[0] = pLookAhead->LookAhead[0];
                    ((A_UINT8 *)pNextLookAhead)[1] = pLookAhead->LookAhead[1];
                    ((A_UINT8 *)pNextLookAhead)[2] = pLookAhead->LookAhead[2];
                    ((A_UINT8 *)pNextLookAhead)[3] = pLookAhead->LookAhead[3];

                    if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
                        DebugDumpBytes((A_UINT8 *)pNextLookAhead,4,"Next Look Ahead");
                    }
                }
                break;
            default:
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n",
                        pRecord->RecordID, pRecord->Length));
                break;
        }

        if (A_FAILED(status)) {
            break;
        }

            /* advance buffer past this record for next time around */
        pBuffer += pRecord->Length;
        Length -= pRecord->Length;
    }

    if (A_FAILED(status)) {
        DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer");
    }

    AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n"));
    return status;

}
Example #9
0
/* 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, HTC_PACKET *pPacket)
{
    HTC_TARGET      *target = (HTC_TARGET *)Context;
    HTC_ENDPOINT    *pEndpoint;
    A_UINT32        nextLookAhead = 0;
    A_STATUS        status;

    AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (status:%d, ep:%d) \n",
                pPacket->Status, pPacket->Endpoint));

    AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
    pEndpoint = &target->EndPoint[pPacket->Endpoint];
    pPacket->Completion = NULL;

        /* get completion status */
    status = pPacket->Status;

    do {
        if (A_FAILED(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,&nextLookAhead);

        if (A_FAILED(status)) {
            break;
        }
            /* was there a lookahead for the next packet? */
        if (nextLookAhead != 0) {
            A_STATUS nextStatus;
            AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
                            ("HTCRecvCompleteHandler - next look ahead was non-zero : 0x%X \n",
                             nextLookAhead));
                /* we have another packet, get the next packet fetch started (pipelined) before
                 * we call into the endpoint's callback, this will start another async request */
            nextStatus = HTCRecvMessagePendingHandler(target,&nextLookAhead,NULL);
            if (A_EPROTO == nextStatus) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                            ("Next look ahead from recv header was INVALID\n"));
                DebugDumpBytes((A_UINT8 *)&nextLookAhead,
                                4,
                                "BAD lookahead from lookahead report");
            }
        } else {
             AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
            ("HTCRecvCompleteHandler - 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);
        }

        HTC_RX_STAT_PROFILE(target,pEndpoint,nextLookAhead);
        DO_RCV_COMPLETION(target,pPacket,pEndpoint);

    } while (FALSE);

    if (A_FAILED(status)) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n",
                         status));
            /* recyle this packet */
         HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
    }

    AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvCompleteHandler\n"));
}
Example #10
0
/* process a received message (i.e. strip off header, process any trailer data)
 * note : locks must be released when this function is called */
static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT32 *pNextLookAhead)
{
    A_UINT8   temp;
    A_UINT8   *pBuf;
    A_STATUS  status = A_OK;
    A_UINT16  payloadLen;
    A_UINT32  lookAhead;

    pBuf = pPacket->pBuffer;

    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, HTC_FRAME_HDR, PayloadLen);

        ((A_UINT8 *)&lookAhead)[0] = pBuf[0];
        ((A_UINT8 *)&lookAhead)[1] = pBuf[1];
        ((A_UINT8 *)&lookAhead)[2] = pBuf[2];
        ((A_UINT8 *)&lookAhead)[3] = pBuf[3];

        if (lookAhead != pPacket->HTCReserved) {
            /* 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! \n"));
             DebugDumpBytes((A_UINT8 *)&pPacket->HTCReserved,4,"Expected Message LookAhead");
             DebugDumpBytes(pBuf,sizeof(HTC_FRAME_HDR),"Current Frame Header");
#ifdef HTC_CAPTURE_LAST_FRAME
            DebugDumpBytes((A_UINT8 *)&target->LastFrameHdr,sizeof(HTC_FRAME_HDR),"Last Frame Header");
            if (target->LastTrailerLength != 0) {
                DebugDumpBytes(target->LastTrailer,
                               target->LastTrailerLength,
                               "Last trailer");
            }
#endif
            status = A_EPROTO;
            break;
        }

            /* get flags */
        temp = A_GET_UINT8_FIELD(pBuf, 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, 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;
            }

                /* process trailer data that follows HDR + application payload */
            status = HTCProcessTrailer(target,
                                       (pBuf + HTC_HDR_LENGTH + payloadLen - temp),
                                       temp,
                                       pNextLookAhead,
                                       pPacket->Endpoint);

            if (A_FAILED(status)) {
                break;
            }

#ifdef HTC_CAPTURE_LAST_FRAME
            A_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 (A_FAILED(status)) {
            /* dump the whole packet */
        DebugDumpBytes(pBuf,pPacket->ActualLength,"BAD HTC Recv PKT");
    } else {
#ifdef HTC_CAPTURE_LAST_FRAME
        A_MEMCPY(&target->LastFrameHdr,pBuf,sizeof(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;
}
Example #11
0
static void usb_hif_usb_recv_bundle_complete(struct urb *urb)
{
	HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context;
	A_STATUS status = A_OK;
	adf_nbuf_t buf = NULL;
	HIF_USB_PIPE *pipe = urb_context->pipe;
	A_UINT8 *netdata, *netdata_new;
	A_UINT32 netlen, netlen_new;
	HTC_FRAME_HDR *HtcHdr;
	A_UINT16 payloadLen;
	adf_nbuf_t new_skb = NULL;

	AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, (
			 "+%s: recv pipe: %d, stat:%d,len:%d urb:0x%p\n",
			 __func__,
			 pipe->logical_pipe_num,
			 urb->status, urb->actual_length,
			 urb));

	/* this urb is not pending anymore */
	usb_hif_remove_pending_transfer(urb_context);

	do {

		if (urb->status != 0) {
			status = A_ECOMM;
			switch (urb->status) {
			case -ECONNRESET:
			case -ENOENT:
			case -ESHUTDOWN:
				/* NOTE: no need to spew these errors when
				 * device is removed
				 * or urb is killed due to driver shutdown
				 */
				status = A_ECANCELED;
				break;
			default:
				AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (
						 "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n",
						 __func__,
						 pipe->logical_pipe_num,
						 pipe->ep_address,
						 urb->status));
				break;
			}
			break;
		}

		if (urb->actual_length == 0)
			break;

		buf = urb_context->buf;

		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
			A_UINT8 *data;
			A_UINT32 len;
			adf_nbuf_peek_header(buf, &data, &len);
			DebugDumpBytes(data, len, "hif recv data");
		}

		adf_nbuf_peek_header(buf, &netdata, &netlen);
		netlen = urb->actual_length;

		do {
#if defined(AR6004_1_0_ALIGN_WAR)
			A_UINT8 extra_pad;
			A_UINT16 act_frame_len;
#endif
			A_UINT16 frame_len;

			/* Hack into HTC header for bundle processing */
			HtcHdr = (HTC_FRAME_HDR *) netdata;
			if (HtcHdr->EndpointID >= ENDPOINT_MAX) {
				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
					("athusb: Rx: invalid EndpointID=%d\n",
					HtcHdr->EndpointID));
				break;
			}

			payloadLen = HtcHdr->PayloadLen;
			payloadLen = A_LE2CPU16(payloadLen);

#if defined(AR6004_1_0_ALIGN_WAR)
			act_frame_len = (HTC_HDR_LENGTH + payloadLen);

			if (HtcHdr->EndpointID == 0 ||
				HtcHdr->EndpointID == 1) {
				/* assumption: target won't pad on HTC endpoint
				 * 0 & 1.
				 */
				extra_pad = 0;
			} else {
				extra_pad =
				    A_GET_UINT8_FIELD((A_UINT8 *) HtcHdr,
						      HTC_FRAME_HDR,
						      ControlBytes[1]);
			}
#endif

			if (payloadLen > HIF_USB_RX_BUFFER_SIZE) {
				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
					("athusb: payloadLen too long %u\n",
					payloadLen));
				break;
			}
#if defined(AR6004_1_0_ALIGN_WAR)
			frame_len = (act_frame_len + extra_pad);
#else
			frame_len = (HTC_HDR_LENGTH + payloadLen);
#endif

			if (netlen >= frame_len) {
				/* allocate a new skb and copy */
#if defined(AR6004_1_0_ALIGN_WAR)
				new_skb =
				    adf_nbuf_alloc(NULL, act_frame_len, 0, 4,
						   FALSE);
				if (new_skb == NULL) {
					AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (
							 "athusb: allocate skb (len=%u) failed\n",
							 act_frame_len));
					break;
				}

				adf_nbuf_peek_header(new_skb, &netdata_new,
						     &netlen_new);
				adf_os_mem_copy(netdata_new, netdata,
						act_frame_len);
				adf_nbuf_put_tail(new_skb, act_frame_len);
#else
				new_skb =
				    adf_nbuf_alloc(NULL, frame_len, 0, 4,
						   FALSE);
				if (new_skb == NULL) {
					AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (
							 "athusb: allocate skb (len=%u) failed\n",
							 frame_len));
					break;
				}

				adf_nbuf_peek_header(new_skb, &netdata_new,
						     &netlen_new);
				adf_os_mem_copy(netdata_new, netdata,
						frame_len);
				adf_nbuf_put_tail(new_skb, frame_len);
#endif
				skb_queue_tail(&pipe->io_comp_queue, new_skb);
				new_skb = NULL;

				netdata += frame_len;
				netlen -= frame_len;
			} else {
				AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (
					 "athusb: subframe length %d not fitted into bundle packet length %d\n"
					 , netlen, frame_len));
				break;
			}

		} while (netlen);

		schedule_work(&pipe->io_complete_work);

	} while (FALSE);

	if (urb_context->buf == NULL) {
		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
				("athusb: buffer in urb_context is NULL\n"));
	}

	/* reset urb_context->buf ==> seems not necessary */
	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);

	if (A_SUCCESS(status)) {
		if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
			/* our free urbs are piling up, post more transfers */
			usb_hif_post_recv_bundle_transfers(pipe, 0
			/* pass zero for not allocating urb-buffer again */
			    );
		}
	}

	AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ("-%s\n", __func__));
}
Example #12
0
static void usb_hif_usb_recv_complete(struct urb *urb)
{
	HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context;
	A_STATUS status = A_OK;
	adf_nbuf_t buf = NULL;
	HIF_USB_PIPE *pipe = urb_context->pipe;

	AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, (
			 "+%s: recv pipe: %d, stat:%d,len:%d urb:0x%p\n",
			 __func__,
			 pipe->logical_pipe_num,
			 urb->status, urb->actual_length,
			 urb));

	/* this urb is not pending anymore */
	usb_hif_remove_pending_transfer(urb_context);

	do {

		if (urb->status != 0) {
			status = A_ECOMM;
			switch (urb->status) {
#ifdef RX_SG_SUPPORT
			case -EOVERFLOW:
				urb->actual_length = HIF_USB_RX_BUFFER_SIZE;
				status = A_OK;
				break;
#endif
			case -ECONNRESET:
			case -ENOENT:
			case -ESHUTDOWN:
				/* NOTE: no need to spew these errors when
				 * device is removed
				 * or urb is killed due to driver shutdown
				 */
				status = A_ECANCELED;
				break;
			default:
				AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (
						 "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n",
						 __func__,
						 pipe->logical_pipe_num,
						 pipe->ep_address,
						 urb->status));
				break;
			}
			break;
		}

		if (urb->actual_length == 0)
			break;

		buf = urb_context->buf;
		/* we are going to pass it up */
		urb_context->buf = NULL;
		adf_nbuf_put_tail(buf, urb->actual_length);
		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
			A_UINT8 *data;
			A_UINT32 len;
			adf_nbuf_peek_header(buf, &data, &len);
			DebugDumpBytes(data, len, "hif recv data");
		}

		/* note: queue implements a lock */
		skb_queue_tail(&pipe->io_comp_queue, buf);
		schedule_work(&pipe->io_complete_work);

	} while (FALSE);

	usb_hif_cleanup_recv_urb(urb_context);

	if (A_SUCCESS(status)) {
		if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
			/* our free urbs are piling up, post more transfers */
			usb_hif_post_recv_transfers(pipe,
						    HIF_USB_RX_BUFFER_SIZE);
		}
	}

	AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ("-%s\n", __func__));
}