|SUCCESS| [v1,2/2] dma/odm: avoid zero length DMA transfers

dpdklab at iol.unh.edu dpdklab at iol.unh.edu
Mon Jun 1 13:33:54 CEST 2026


Test-Label: ai-code-review
Test-Status: SUCCESS
https://dpdk.org/patch/164741

_AI Code Review_

=== Patch Review: series.patch (via Claude) ===
Review date: 2026-06-01

Commit: 20260601101559.1925302-2-sthotton at marvell.com
Author: Vamsi Attunuru <vattunuru at marvell.com>
Subject: [PATCH v1 1/2] dma/odm: support dev to mem transfers

This patch adds support for device-to-memory and memory-to-device DMA
transfers by extending the existing memory-to-memory functionality.

> diff --git a/drivers/dma/odm/odm.c b/drivers/dma/odm/odm.c
> index 270808f4df..0633ce0b4b 100644
> --- a/drivers/dma/odm/odm.c
> +++ b/drivers/dma/odm/odm.c
> @@ -125,13 +125,41 @@ odm_disable(struct odm_dev *odm)
>  	return 0;
>  }
>  
> +static int
> +odm_get_ext_port_type(const struct rte_dma_vchan_conf *conf, uint8_t *ext_port)
> +{
> +	uint8_t coreid;
> +
> +	if (conf->src_port.port_type == RTE_DMA_PORT_PCIE) {
> +		coreid = conf->src_port.pcie.coreid;
> +	} else if (conf->dst_port.port_type == RTE_DMA_PORT_PCIE) {
> +		coreid = conf->dst_port.pcie.coreid;
> +	} else {
> +		*ext_port = ODM_EXT_PORT_NCB;
> +		return 0;
> +	}

Does this code allow simultaneous src and dst to be RTE_DMA_PORT_PCIE,
which would set coreid twice to potentially different values?

> +
> +	switch (coreid) {
> +	case 0:
> +		*ext_port = ODM_EXT_PORT_PEM0;
> +		return 0;
> +	case 1:
> +		*ext_port = ODM_EXT_PORT_PEM1;
> +		return 0;
> +	default:
> +		ODM_LOG(ERR, "Unsupported PCIe coreid %u (only 0 and 1 are valid)", coreid);
> +		return -EINVAL;
> +	}
> +}
> +
>  int
> -odm_vchan_setup(struct odm_dev *odm, int vchan, int nb_desc)
> +odm_vchan_setup(struct odm_dev *odm, int vchan, const struct rte_dma_vchan_conf *conf)
>  {
>  	struct odm_queue *vq = &odm->vq[vchan];
>  	int isize, csize, max_nb_desc, rc = 0;
>  	union odm_mbox_msg mbox_msg;
>  	const struct rte_memzone *mz;
> +	uint8_t ext_port;
>  	char name[32];
>  
>  	if (vq->iring_mz != NULL)
> @@ -140,10 +168,29 @@ odm_vchan_setup(struct odm_dev *odm, int vchan, int nb_desc)
>  	mbox_msg.u[0] = 0;
>  	mbox_msg.u[1] = 0;
>  
> +	switch (conf->direction) {
> +	case RTE_DMA_DIR_DEV_TO_MEM:
> +		vq->xtype = ODM_XTYPE_INBOUND;
> +		break;
> +	case RTE_DMA_DIR_MEM_TO_DEV:
> +		vq->xtype = ODM_XTYPE_OUTBOUND;
> +		break;
> +	case RTE_DMA_DIR_MEM_TO_MEM:
> +		vq->xtype = ODM_XTYPE_INTERNAL;
> +		break;
> +	default:
> +		ODM_LOG(ERR, "Unsupported DMA direction %d", conf->direction);
> +		return -EINVAL;
> +	}
> +
>  	/* ODM PF driver expects vfid starts from index 0 */
>  	mbox_msg.q.vfid = odm->vfid;
>  	mbox_msg.q.cmd = ODM_QUEUE_OPEN;
>  	mbox_msg.q.qidx = vchan;
> +	rc = odm_get_ext_port_type(conf, &ext_port);
> +	if (rc < 0)
> +		return rc;
> +	mbox_msg.q.ext_port = ext_port;

Does this code leak vq->iring_mz if odm_get_ext_port_type() returns an
error, given the check for vq->iring_mz != NULL earlier and the comment
about its cleanup in odm_vchan_destroy()?

>  	rc = send_mbox_to_pf(odm, &mbox_msg, &mbox_msg);
>  	if (rc < 0)
>  		return rc;

[ ... ]

> diff --git a/drivers/dma/odm/odm_dmadev.c b/drivers/dma/odm/odm_dmadev.c
> index a2f4ed9a8e..0211133bd4 100644
> --- a/drivers/dma/odm/odm_dmadev.c
> +++ b/drivers/dma/odm/odm_dmadev.c
> @@ -30,7 +30,8 @@ odm_dmadev_info_get(const struct rte_dma_dev *dev, struct rte_dma_info *dev_info
>  	dev_info->max_vchans = odm->max_qs;
>  	dev_info->nb_vchans = odm->num_qs;
>  	dev_info->dev_capa =
> -		(RTE_DMA_CAPA_MEM_TO_MEM | RTE_DMA_CAPA_OPS_COPY | RTE_DMA_CAPA_OPS_COPY_SG);
> +		(RTE_DMA_CAPA_MEM_TO_MEM | RTE_DMA_CAPA_OPS_COPY | RTE_DMA_CAPA_OPS_COPY_SG |
> +		 RTE_DMA_CAPA_MEM_TO_DEV | RTE_DMA_CAPA_DEV_TO_MEM);

Are there corresponding capability checks added when setting up the
device direction to validate that the requested direction matches the
advertised capabilities?

[ ... ]


Commit: 20260601101559.1925302-3-sthotton at marvell.com
Author: Shijith Thotton <sthotton at marvell.com>
Subject: [PATCH v1 2/2] dma/odm: avoid zero length DMA transfers

This patch adds validation to reject zero-length DMA operations.

> diff --git a/drivers/dma/odm/odm_dmadev.c b/drivers/dma/odm/odm_dmadev.c
> index 0211133bd4..7488b960fd 100644
> --- a/drivers/dma/odm/odm_dmadev.c
> +++ b/drivers/dma/odm/odm_dmadev.c
> @@ -110,6 +110,9 @@ odm_dmadev_copy(void *dev_private, uint16_t vchan, rte_iova_t src, rte_iova_t ds
>  	vq = &odm->vq[vchan];
>  	hdr.s.xtype = vq->xtype;
>  
> +	if (unlikely(!length))
> +		return -EINVAL;

This uses the implicit comparison forbidden by the coding standard. The
check should be written as 'if (unlikely(length == 0))'.

> +
>  	h = length;
>  	h |= ((uint64_t)length << 32);
>  
> @@ -262,14 +265,20 @@ odm_dmadev_copy_sg(void *dev_private, uint16_t vchan, const struct rte_dma_sge *
>  	pending_submit_len = vq->pending_submit_len;
>  	pending_submit_cnt = vq->pending_submit_cnt;
>  
> -	if (unlikely(nb_src > 4 || nb_dst > 4))
> +	if (unlikely(!nb_src || nb_src > 4 || !nb_dst || nb_dst > 4))
>  		return -EINVAL;

Same issue here - uses forbidden implicit comparisons. Should be
'nb_src == 0' and 'nb_dst == 0'.

>  
> -	for (i = 0; i < nb_src; i++)
> +	for (i = 0; i < nb_src; i++) {
> +		if (unlikely(!src[i].length))
> +			return -EINVAL;

Same issue - should be 'src[i].length == 0'.

>  		s_sz += src[i].length;
> +	}
>  
> -	for (i = 0; i < nb_dst; i++)
> +	for (i = 0; i < nb_dst; i++) {
> +		if (unlikely(!dst[i].length))
> +			return -EINVAL;

Same issue - should be 'dst[i].length == 0'.

>  		d_sz += dst[i].length;
> +	}
>  
>  	if (s_sz != d_sz)
>  		return -EINVAL;
> @@ -342,6 +351,9 @@ odm_dmadev_fill(void *dev_private, uint16_t vchan, uint64_t pattern, rte_iova_t
>  		.s.nlst = 1,
>  	};
>  
> +	if (unlikely(!length))
> +		return -EINVAL;

Same issue - should be 'length == 0'.

>  
>  	h = (uint64_t)length;
>  


More information about the test-report mailing list