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