diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index ec2c9abf1549..19362d0a0038 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -126,30 +126,6 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id) * dp_tx_htt_metadata_prepare() - Prepare HTT metadata for special frames * @vdev: DP vdev Handle * @nbuf: skb - * @align_pad: Alignment Pad bytes to be pushed in headroom before adding - * HTT metadata - * - * |-----------------------------| - * | | - * |-----------------------------| <-----Buffer Pointer Address given - * | | ^ in HW descriptor (aligned) - * | | | - * | HTT Metadata | | - * | | | - * | | | Packet Offset given in descriptor - * | | | - * | | | - * |-----------------------------| | - * | Alignment Pad | v - * |-----------------------------| <----- Actual buffer start address - * | SKB Data | (Unaligned) - * | | - * | | - * | | - * | | - * | | - * | | - * |-----------------------------| * * Prepares and fills HTT metadata in the frame pre-header for special frames * that should be transmitted using varying transmit parameters. @@ -161,11 +137,15 @@ dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id) * */ static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, - uint8_t align_pad, uint32_t *meta_data) + uint32_t *meta_data) { struct htt_tx_msdu_desc_ext2_t *desc_ext = (struct htt_tx_msdu_desc_ext2_t *) meta_data; - uint8_t htt_desc_size = 0; + + uint8_t htt_desc_size; + + /* Size rounded of multiple of 8 bytes */ + uint8_t htt_desc_size_aligned; uint8_t *hdr = NULL; @@ -177,30 +157,19 @@ static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf, * Metadata - HTT MSDU Extension header */ htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext2_t); + htt_desc_size_aligned = (htt_desc_size + 7) & ~0x7; if (vdev->mesh_vdev) { + /* Fill and add HTT metaheader */ - hdr = qdf_nbuf_push_head(nbuf, htt_desc_size + align_pad); + hdr = qdf_nbuf_push_head(nbuf, htt_desc_size_aligned); qdf_mem_copy(hdr, desc_ext, htt_desc_size); - if (qdf_unlikely(QDF_STATUS_SUCCESS != - qdf_nbuf_map_nbytes_single( - vdev->pdev->soc->osdev, nbuf, - QDF_DMA_TO_DEVICE, - (htt_desc_size + align_pad)))) { - - /* Handle failure */ - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "htt qdf_nbuf_map failed\n"); - - return 0; - } - } else if (vdev->opmode == wlan_op_mode_ocb) { /* Todo - Add support for DSRC */ } - return htt_desc_size; + return htt_desc_size_aligned; } /** @@ -434,16 +403,17 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, tx_desc->pdev = pdev; tx_desc->msdu_ext_desc = NULL; - if (qdf_unlikely(QDF_STATUS_SUCCESS != - qdf_nbuf_map(soc->osdev, nbuf, - QDF_DMA_TO_DEVICE))) { - /* Handle failure */ - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "qdf_nbuf_map failed\n"); - goto failure; - } - - align_pad = ((unsigned long) qdf_nbuf_mapped_paddr_get(nbuf)) & 0x7; + /** + * For non-scatter regular frames, buffer pointer is directly + * programmed in TCL input descriptor instead of using an MSDU + * extension descriptor.For this cass, HW requirement is that + * descriptor should always point to a 8-byte aligned address. + * + * So we add alignment pad to start of buffer, and specify the actual + * start of data through pkt_offset + */ + align_pad = ((unsigned long) qdf_nbuf_data(nbuf)) & 0x7; + qdf_nbuf_push_head(nbuf, align_pad); tx_desc->pkt_offset = align_pad; /* @@ -452,16 +422,47 @@ struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev, * transmit rate, power, priority, channel, channel bandwidth , nss etc. * These are filled in HTT MSDU descriptor and sent in frame pre-header. * These frames are sent as exception packets to firmware. + * + * HTT Metadata should be ensured to be multiple of 8-bytes, + * to get 8-byte aligned start address along with align_pad added above + * + * |-----------------------------| + * | | + * |-----------------------------| <-----Buffer Pointer Address given + * | | ^ in HW descriptor (aligned) + * | HTT Metadata | | + * | | | + * | | | Packet Offset given in descriptor + * | | | + * |-----------------------------| | + * | Alignment Pad | v + * |-----------------------------| <----- Actual buffer start address + * | SKB Data | (Unaligned) + * | | + * | | + * | | + * | | + * | | + * |-----------------------------| */ if (qdf_unlikely(vdev->mesh_vdev || (vdev->opmode == wlan_op_mode_ocb))) { htt_hdr_size = dp_tx_prepare_htt_metadata(vdev, nbuf, - align_pad, meta_data); + meta_data); tx_desc->pkt_offset += htt_hdr_size; tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW; is_exception = 1; } + if (qdf_unlikely(QDF_STATUS_SUCCESS != + qdf_nbuf_map(soc->osdev, nbuf, + QDF_DMA_TO_DEVICE))) { + /* Handle failure */ + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "qdf_nbuf_map failed\n"); + goto failure; + } + if (qdf_unlikely(vdev->nawds_enabled)) { eh = (struct ether_header *) qdf_nbuf_data(nbuf); if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost)) { @@ -652,22 +653,11 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, type = HAL_TX_BUF_TYPE_EXT_DESC; dma_addr = tx_desc->msdu_ext_desc->paddr; } else { - length = qdf_nbuf_len(tx_desc->nbuf); + length = qdf_nbuf_len(tx_desc->nbuf) - tx_desc->pkt_offset; type = HAL_TX_BUF_TYPE_BUFFER; - - /** - * For non-scatter regular frames, buffer pointer is directly - * programmed in TCL input descriptor instead of using an MSDU - * extension descriptor.For the direct buffer pointer case, HW - * requirement is that descriptor should always point to a - * 8-byte aligned address. - * Alignment padding is already accounted in pkt_offset - * - */ - dma_addr = (qdf_nbuf_mapped_paddr_get(tx_desc->nbuf) & ~0x7); + dma_addr = qdf_nbuf_mapped_paddr_get(tx_desc->nbuf); } - hal_tx_desc_set_fw_metadata(hal_tx_desc_cached, fw_metadata); hal_tx_desc_set_buf_addr(hal_tx_desc_cached, dma_addr , bm_id, tx_desc->id, type);