All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: "Nuno Sá" <nuno.sa@analog.com>
Cc: linux-iio@vger.kernel.org, Paul Cercueil <paul@crapouillou.net>,
	David Lechner <dlechner@baylibre.com>,
	Andy Shevchenko <andy@kernel.org>
Subject: Re: [PATCH v2 1/2] iio: buffer-dmaengine: fix sg entry iteration when building dma_vecs
Date: Sun, 30 Aug 2026 01:23:10 +0100	[thread overview]
Message-ID: <20260830012310.0a6930bf@jic23-huawei> (raw)
In-Reply-To: <20260828-iio-buffer-dmabuf-iommu-fic-v2-1-b4dd71827621@analog.com>

On Fri, 28 Aug 2026 11:46:55 +0100
Nuno Sá <nuno.sa@analog.com> wrote:

> From: Michael Hennerich <michael.hennerich@analog.com>
> 
> iio_dmaengine_buffer_submit_block() counts scatterlist entries with
> sg_nents_for_len(), which walks the CPU-side lengths (sg->length), but
> then consumes the DMA-side fields (sg_dma_address()/sg_dma_len()).
> After dma_map_sgtable() the two views may differ: an IOMMU can coalesce
> the mapping so that only the first sgt->nents entries carry valid DMA
> addresses, with nents < orig_nents.
> 
> On x86 with an IOMMU enabled, a DMABUF block backed by two 1 MiB
> system-heap chunks maps to a single 2 MiB IOVA range. The CPU-side
> count is 2, so the loop reads one entry past the mapped set and emits a
> garbage vec ({addr = ~0, len = 0}). The DMA engine driver rejects the
> vec array (prep returns NULL), the fence is signalled with -ENOMEM,
> which a userspace poller cannot observe, and the block is left in
> ACTIVE state so every further enqueue of it fails with -EBUSY. The
> visible symptom is a stream of zero-filled blocks followed by a wedged
> buffer.
> 
> Platforms without an IOMMU never hit this because nents == orig_nents.
> 
> Size the vec array with sgt->nents, i.e. the DMA-mapped view, and stop
> the fill loop once bytes_used is covered - which is allowed to be
> smaller than the block size - passing the number of vecs actually
> filled to dmaengine_prep_peripheral_dma_vec().
> 
> One vec per mapped entry is enough since coalescing can only ever
> reduce the number of entries. A single mapped entry longer than the
> device's maximum segment size would need more than one, but the DMA API
> already assumes no single segment exceeds it [1], and splitting a vec
> down to the hardware descriptor size is the DMA engine driver's job -
> which both current .device_prep_peripheral_dma_vec() implementations
> do.
> 
> [1]: commit ab2cbeb0ed30 ("iommu/dma: Handle SG length overflow better")
> 
> Assisted-by: Claude:claude-fable-5
> Fixes: 7a86d469983a ("iio: buffer-dmaengine: Support new DMABUF based userspace API")
> Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
> Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Applied to the fixes-togreg branch of iio.git and marked for stable.

Seems I can get away with taking patch 2 via the testing branch as
well :)  So done that.

Both those branches will get rebased so if anyone else has feedback on this
series it would be good to have.

Thanks,

Jonathan

> 
> ---
> 
> Note the Signed-off-by is just because I'm carrying Michael's patch!
> ---
>  drivers/iio/buffer/industrialio-buffer-dmaengine.c | 16 +++++++++++-----
>  1 file changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
> index ecc02a427b92..376486be3f55 100644
> --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
> +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
> @@ -104,10 +104,13 @@ static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue,
>  	if (block->sg_table) {
>  		unsigned long flags;
>  
> -		sgl = block->sg_table->sgl;
> -		nents = sg_nents_for_len(sgl, block->bytes_used);
> -		if (nents < 0)
> -			return nents;
> +		/*
> +		 * Only the first sgt->nents entries carry a valid
> +		 * sg_dma_address()/sg_dma_len() pair as mapping the table may
> +		 * have coalesced entries, in which case nents is smaller than
> +		 * orig_nents.
> +		 */
> +		nents = block->sg_table->nents;
>  
>  		vecs = kmalloc_array(nents, sizeof(*vecs), GFP_ATOMIC);
>  		if (!vecs)
> @@ -115,7 +118,8 @@ static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue,
>  
>  		len_total = block->bytes_used;
>  
> -		for (i = 0; i < nents; i++) {
> +		sgl = block->sg_table->sgl;
> +		for (i = 0; i < nents && len_total; i++) {
>  			vecs[i].addr = sg_dma_address(sgl);
>  			vecs[i].len = min(sg_dma_len(sgl), len_total);
>  			len_total -= vecs[i].len;
> @@ -123,6 +127,8 @@ static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue,
>  			sgl = sg_next(sgl);
>  		}
>  
> +		nents = i;
> +
>  		if (block->cyclic)
>  			flags = DMA_PREP_REPEAT;
>  		else
> 


  reply	other threads:[~2026-08-30  0:23 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-28 10:46 [PATCH v2 0/2] iio: buffer-dmaengine: fix dma_vec building for coalesced sg tables Nuno Sá
2026-08-28 10:46 ` [PATCH v2 1/2] iio: buffer-dmaengine: fix sg entry iteration when building dma_vecs Nuno Sá
2026-08-30  0:23   ` Jonathan Cameron [this message]
2026-08-28 10:46 ` [PATCH v2 2/2] iio: buffer-dmaengine: drop dead max_size computation Nuno Sá

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260830012310.0a6930bf@jic23-huawei \
    --to=jic23@kernel.org \
    --cc=andy@kernel.org \
    --cc=dlechner@baylibre.com \
    --cc=linux-iio@vger.kernel.org \
    --cc=nuno.sa@analog.com \
    --cc=paul@crapouillou.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.