Exemple #1
0
static inline int
htt_tx_send_base(
    htt_pdev_handle pdev,
    adf_nbuf_t msdu,
    u_int16_t msdu_id,
    int download_len,
    u_int8_t more_data)
{
    struct htt_host_tx_desc_t *htt_host_tx_desc;
    struct htt_htc_pkt *pkt;
    int packet_len;
    HTC_ENDPOINT_ID ep_id;

    /*
     * The HTT tx descriptor was attached as the prefix fragment to the
     * msdu netbuf during the call to htt_tx_desc_init.
     * Retrieve it so we can provide its HTC header space to HTC.
     */
    htt_host_tx_desc = (struct htt_host_tx_desc_t *)
        adf_nbuf_get_frag_vaddr(msdu, 0);

    pkt = htt_htc_pkt_alloc(pdev);
    if (!pkt) {
        return 1; /* failure */
    }

    pkt->msdu_id = msdu_id;
    pkt->pdev_ctxt = pdev->txrx_pdev;

    /* packet length includes HTT tx desc frag added above */
    packet_len = adf_nbuf_len(msdu);
    if (packet_len < download_len) {
        /*
         * This case of packet length being less than the nominal download
         * length can happen for a couple reasons:
         * In HL, the nominal download length is a large artificial value.
         * In LL, the frame may not have the optional header fields
         * accounted for in the nominal download size (LLC/SNAP header,
         * IPv4 or IPv6 header).
         */
        download_len = packet_len;
    }

    ep_id = htt_tx_htt2_get_ep_id(pdev, msdu);

    SET_HTC_PACKET_INFO_TX(
        &pkt->htc_pkt,
        pdev->tx_send_complete_part2,
        (unsigned char *) htt_host_tx_desc,
        download_len - HTC_HDR_LENGTH,
        ep_id,
        1); /* tag - not relevant here */

    SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msdu);

    adf_nbuf_trace_update(msdu, "HT:T:");
    HTCSendDataPkt(pdev->htc_pdev, &pkt->htc_pkt, more_data);

    return 0; /* success */
}
Exemple #2
0
void usb_hif_io_comp_work(struct work_struct *work)
{
	HIF_USB_PIPE *pipe = container_of(work, HIF_USB_PIPE, io_complete_work);
	adf_nbuf_t buf;
	HIF_DEVICE_USB *device;
	HTC_FRAME_HDR *HtcHdr;
	struct hif_usb_softc *sc;
	A_UINT8 *data;
	A_UINT32 len;

	AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__));
	device = pipe->device;
	sc = device->sc;

	while ((buf = skb_dequeue(&pipe->io_comp_queue))) {
		a_mem_trace(buf);
		if (pipe->flags & HIF_USB_PIPE_FLAG_TX) {
			AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_OUT,
					("+athusb xmit callback " "buf:0x%p\n",
					 buf));
			HtcHdr = (HTC_FRAME_HDR *) adf_nbuf_get_frag_vaddr(buf, 0);

#ifdef ATH_11AC_TXCOMPACT
#error ATH_11AC_TXCOMPACT only support for High Latency mode
#else
			device->htcCallbacks.txCompletionHandler(device->
								 htcCallbacks.
								 Context, buf,
								 HtcHdr->
								 EndpointID);
#endif
			AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_OUT,
					("-athusb xmit callback\n"));
		} else {
			AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN,
					("+athusb recv callback buf:" "0x%p\n",
					 buf));
			adf_nbuf_peek_header(buf, &data, &len);

			if (IS_FW_CRASH_DUMP(*((A_UINT32 *) data))) {
				sc->fw_data = data;
				sc->fw_data_len = len;
				device->htcCallbacks.fwEventHandler(
					device->htcCallbacks.Context, A_USB_ERROR);
				dev_kfree_skb(buf);
			} else {
				device->htcCallbacks.rxCompletionHandler(
				device->htcCallbacks.Context, buf,
				pipe->logical_pipe_num);
				AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN,
					("-athusb recv callback\n"));
			}
		}
	}

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

}
Exemple #3
0
A_STATUS HIFDevSendBuffer(HIF_SDIO_DEVICE *pDev, unsigned int transferID, a_uint8_t pipe,
        unsigned int nbytes, adf_nbuf_t buf)
{
    A_STATUS status;
    A_UINT32 paddedLength;
    int frag_count = 0, i, head_data_len;
    struct HIFSendContext *pSendContext;
    unsigned char *pData;
    A_UINT32 request = HIF_WR_ASYNC_BLOCK_INC;
    A_UINT8 mboxIndex = HIFDevMapPipeToMailBox(pDev, pipe);

    paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, nbytes);
#ifdef ENABLE_MBOX_DUMMY_SPACE_FEATURE
    A_ASSERT(paddedLength - nbytes < HIF_DUMMY_SPACE_MASK + 1);
    /*
     * two most significant bytes to save dummy data count
     * data written into the dummy space will not put into the final mbox FIFO
     *
     */
    request |= ((paddedLength - nbytes) << 16);
#endif

    frag_count = adf_nbuf_get_num_frags(buf);

    if (frag_count > 1){
        /* header data length should be total sending length substract internal data length of netbuf */
        /*
         * | HIFSendContext | fragments except internal buffer | netbuf->data
         */
        head_data_len = sizeof(struct HIFSendContext) +
                (nbytes - adf_nbuf_get_frag_len(buf, frag_count - 1));
    } else {
        /*
         * | HIFSendContext | netbuf->data
         */
        head_data_len = sizeof(struct HIFSendContext);
    }

    /* Check whether head room is enough to save extra head data */
    if ((head_data_len <= adf_nbuf_headroom(buf)) &&
                (adf_nbuf_tailroom(buf) >= (paddedLength - nbytes))){
        pSendContext = (struct HIFSendContext*)adf_nbuf_push_head(buf, head_data_len);
        pSendContext->bNewAlloc = FALSE;
    } else {
        pSendContext = (struct HIFSendContext*)adf_os_mem_alloc(NULL,
                sizeof(struct HIFSendContext) + paddedLength);
        pSendContext->bNewAlloc = TRUE;
    }

    pSendContext->netbuf = buf;
    pSendContext->pDev = pDev;
    pSendContext->transferID = transferID;
    pSendContext->head_data_len = head_data_len;
    /*
     * Copy data to head part of netbuf or head of allocated buffer.
     * if buffer is new allocated, the last buffer should be copied also.
     * It assume last fragment is internal buffer of netbuf
     * sometime total length of fragments larger than nbytes
     */
    pData = (unsigned char *)pSendContext + sizeof(struct HIFSendContext);
    for (i = 0; i < (pSendContext->bNewAlloc ? frag_count : frag_count - 1); i ++){
        int frag_len = adf_nbuf_get_frag_len(buf, i);
        unsigned char *frag_addr = adf_nbuf_get_frag_vaddr(buf, i);
        if (frag_len > nbytes){
            frag_len = nbytes;
        }
        memcpy(pData, frag_addr, frag_len);
        pData += frag_len;
        nbytes -= frag_len;
        if (nbytes <= 0) {
            break;
        }
    }

    /* Reset pData pointer and send out */
    pData = (unsigned char *)pSendContext + sizeof(struct HIFSendContext);
    status = HIFReadWrite(pDev->HIFDevice,
            pDev->MailBoxInfo.MboxProp[mboxIndex].ExtendedAddress,
            (char*) pData,
            paddedLength,
            request,
            (void*)pSendContext);

    if (status == A_PENDING){
        /*
         * it will return A_PENDING in native HIF implementation,
         * which should be treated as successful result here.
         */
        status = A_OK;
    }
    /* release buffer or move back data pointer when failed */
    if (status != A_OK){
        if (pSendContext->bNewAlloc){
            adf_os_mem_free(pSendContext);
        } else {
            adf_nbuf_pull_head(buf, head_data_len);
        }
    }

    return status;
}