Exemple #1
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;
}
struct ol_tx_desc_t *
ol_tx_desc_ll(
    struct ol_txrx_pdev_t *pdev,
    struct ol_txrx_vdev_t *vdev,
    adf_nbuf_t netbuf,
    struct ol_txrx_msdu_info_t *msdu_info)
{
    struct ol_tx_desc_t *tx_desc;
    unsigned int i;
    u_int32_t num_frags;

    msdu_info->htt.info.vdev_id = vdev->vdev_id;
    msdu_info->htt.action.cksum_offload = adf_nbuf_get_tx_cksum(netbuf);
    switch (adf_nbuf_get_exemption_type(netbuf)) {
    case ADF_NBUF_EXEMPT_NO_EXEMPTION:
    case ADF_NBUF_EXEMPT_ON_KEY_MAPPING_KEY_UNAVAILABLE:
        /* We want to encrypt this frame */
        msdu_info->htt.action.do_encrypt = 1;
        break;
    case ADF_NBUF_EXEMPT_ALWAYS:
        /* We don't want to encrypt this frame */
        msdu_info->htt.action.do_encrypt = 0;
        break;
    default:
        adf_os_assert(0);
        break;
    }

    /* allocate the descriptor */
    tx_desc = ol_tx_desc_alloc(pdev, vdev);
    if (!tx_desc) return NULL;

    /* initialize the SW tx descriptor */
    tx_desc->netbuf = netbuf;
    /* fix this - get pkt_type from msdu_info */
    tx_desc->pkt_type = ol_tx_frm_std;

    /* initialize the HW tx descriptor */
    htt_tx_desc_init(
        pdev->htt_pdev, tx_desc->htt_tx_desc,
        tx_desc->htt_tx_desc_paddr,
        ol_tx_desc_id(pdev, tx_desc),
        netbuf,
        &msdu_info->htt, NULL, vdev->opmode == wlan_op_mode_ocb);

    /*
     * Initialize the fragmentation descriptor.
     * Skip the prefix fragment (HTT tx descriptor) that was added
     * during the call to htt_tx_desc_init above.
     */
    num_frags = adf_nbuf_get_num_frags(netbuf);
    /* num_frags are expected to be 2 max */
    num_frags = (num_frags > CVG_NBUF_MAX_EXTRA_FRAGS) ? CVG_NBUF_MAX_EXTRA_FRAGS : num_frags;
    htt_tx_desc_num_frags(pdev->htt_pdev, tx_desc->htt_tx_desc, num_frags-1);
    for (i = 1; i < num_frags; i++) {
        adf_os_size_t frag_len;
        u_int32_t frag_paddr;

        frag_len = adf_nbuf_get_frag_len(netbuf, i);
        frag_paddr = adf_nbuf_get_frag_paddr_lo(netbuf, i);
        htt_tx_desc_frag(
            pdev->htt_pdev, tx_desc->htt_tx_desc, i-1, frag_paddr, frag_len);
    }
    return tx_desc;
}