diff options
| author | Michael Hennerich <michael.hennerich@analog.com> | 2026-08-28 11:46:55 +0100 |
|---|---|---|
| committer | Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> | 2026-08-31 00:52:42 +0100 |
| commit | 0d0ffbcc92e30a8d656ad76a6e278fa3400fed85 (patch) | |
| tree | 05435d699e4bc15c865659068f1c769883e31fb6 /tools/lib/python/kdoc | |
| parent | 4daa9ca557b4b98ae1ad38a6d1deaa3e31eb8edf (diff) | |
| download | linux-next-0d0ffbcc92e30a8d656ad76a6e278fa3400fed85.tar.gz linux-next-0d0ffbcc92e30a8d656ad76a6e278fa3400fed85.zip | |
iio: buffer-dmaengine: fix sg entry iteration when building dma_vecs
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>
Cc: stable@vger.kernel.org
Signed-off-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Diffstat (limited to 'tools/lib/python/kdoc')
0 files changed, 0 insertions, 0 deletions
