* [PATCH] dma-buf: Split sgl by largest page-aligned chunk
@ 2026-06-21 22:21 David Hu
2026-06-21 22:34 ` sashiko-bot
` (2 more replies)
0 siblings, 3 replies; 23+ messages in thread
From: David Hu @ 2026-06-21 22:21 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: Jason Gunthorpe, Nicolin Chen, Leon Romanovsky, Kevin Tian,
Ankit Agrawal, Alex Williamson, linux-media, dri-devel,
linaro-mm-sig, linux-kernel, iommu, jmoroni, praan, kpberry,
David Hu, sashiko-bot, stable
Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
first entry, resulting in non-page-aligned DMA addresses for all
subsequent entries.
While the underlying IOMMU mapping may be contiguous, hardware
DMA engines often require explicit address alignment (e.g., page,
cacheline, or storage sector boundaries). Passing unaligned
addresses and lengths can cause explicit failures in DMA descriptor
creation or silent data corruption if lower unaligned bits are
truncated.
Fix this by splitting the scatterlist by the largest possible page
aligned chunk within `UINT_MAX` (`ALIGN_DOWN(UINT_MAX, PAGE_SIZE)`).
This ensures all scatterlist DMA addresses and lengths remain page
aligned and satisfy hardware constraints.
Page-aligned entries allow the system to cleanly chunk payloads into
PCIe MaxPayloadSize (MPS) (e.g., 128 bytes, 256 bytes, 512 bytes).
As a result, this may help reduce TLP fragmentation in P2P transfers
and alleviate potential congestion within a logical PCIe switch
partition, especially when Relaxed Ordering is not possible due to
hardware constraints.
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
Cc: stable@vger.kernel.org
Signed-off-by: David Hu <xuehaohu@google.com>
---
drivers/dma-buf/dma-buf-mapping.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 794acff2546a..f2bde38fdb1f 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -5,6 +5,9 @@
*/
#include <linux/dma-buf-mapping.h>
#include <linux/dma-resv.h>
+#include <linux/align.h>
+
+#define MAX_ENT_SZ ALIGN_DOWN(UINT_MAX, PAGE_SIZE)
static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
dma_addr_t addr)
@@ -12,9 +15,9 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
unsigned int len, nents;
int i;
- nents = DIV_ROUND_UP(length, UINT_MAX);
+ nents = DIV_ROUND_UP(length, MAX_ENT_SZ);
for (i = 0; i < nents; i++) {
- len = min_t(size_t, length, UINT_MAX);
+ len = min_t(size_t, length, MAX_ENT_SZ);
length -= len;
/*
* DMABUF abuses scatterlist to create a scatterlist
@@ -24,7 +27,7 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
* does not require the CPU list for mapping or unmapping.
*/
sg_set_page(sgl, NULL, 0, 0);
- sg_dma_address(sgl) = addr + (dma_addr_t)i * UINT_MAX;
+ sg_dma_address(sgl) = addr + (dma_addr_t)i * MAX_ENT_SZ;
sg_dma_len(sgl) = len;
sgl = sg_next(sgl);
}
@@ -41,14 +44,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
if (!state || !dma_use_iova(state)) {
for (i = 0; i < nr_ranges; i++)
- nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
+ nents += DIV_ROUND_UP(phys_vec[i].len, MAX_ENT_SZ);
} else {
/*
* In IOVA case, there is only one SG entry which spans
* for whole IOVA address space, but we need to make sure
* that it fits sg->length, maybe we need more.
*/
- nents = DIV_ROUND_UP(size, UINT_MAX);
+ nents = DIV_ROUND_UP(size, MAX_ENT_SZ);
}
return nents;
--
2.55.0.rc0.738.g0c8ab3ebcc-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH] dma-buf: Split sgl by largest page-aligned chunk
2026-06-21 22:21 [PATCH] dma-buf: Split sgl by largest page-aligned chunk David Hu
@ 2026-06-21 22:34 ` sashiko-bot
2026-06-22 8:13 ` David Laight
2026-06-23 1:54 ` [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks David Hu
2 siblings, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-06-21 22:34 UTC (permalink / raw)
To: David Hu; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Calling `sg_set_page` with a `NULL` page parameter triggers a kernel panic when `CONFIG_DEBUG_VM` and SPARSEMEM without VMEMMAP are enabled.
- [High] Calculating the number of scatterlist entries (`nents`) using `DIV_ROUND_UP()` overflows on 32-bit architectures, resulting in `nents = 0` and uninitialized or empty scatterlists for large buffer lengths.
- [High] dma_unmap_phys() is invoked iteratively on chunked scatterlist addresses and lengths rather than the exact address and size initially mapped by dma_map_phys().
- [High] The error path in `dma_buf_phys_vec_to_sgt` unmaps all allocated scatterlist entries, including unpopulated ones, leading to invalid DMA unmap requests.
--
commit f6cce91b1ad2e1c68270e81a3cd60cffb903c456
Author: David Hu <xuehaohu@google.com>
dma-buf: Split sgl by largest page-aligned chunk
Currently, fill_sg_entry() splits the scatterlist using UINT_MAX, resulting
in non-page-aligned DMA addresses for subsequent entries. This patch changes
the split size to the largest page-aligned chunk within UINT_MAX to satisfy
hardware DMA alignment constraints.
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
Cc: stable@vger.kernel.org
Signed-off-by: David Hu <xuehaohu@google.com>
> diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
> index 794acff2546a3..f2bde38fdb1f7 100644
> --- a/drivers/dma-buf/dma-buf-mapping.c
> +++ b/drivers/dma-buf/dma-buf-mapping.c
> @@ -12,9 +15,9 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> unsigned int len, nents;
> int i;
>
> - nents = DIV_ROUND_UP(length, UINT_MAX);
> + nents = DIV_ROUND_UP(length, MAX_ENT_SZ);
[Severity: High]
This isn't a bug introduced by this patch, but does this DIV_ROUND_UP
calculation overflow on 32-bit architectures?
On 32-bit platforms, size_t is 32 bits and MAX_ENT_SZ evaluates to 0xFFFFF000
assuming 4KB pages. The DIV_ROUND_UP macro expands to:
(length + MAX_ENT_SZ - 1) / MAX_ENT_SZ
If the length is greater than PAGE_SIZE, the numerator wraps around in 32-bit
arithmetic, resulting in a small value that evaluates to 0. This skips the
scatterlist setup loop entirely for large buffer lengths.
> for (i = 0; i < nents; i++) {
> - len = min_t(size_t, length, UINT_MAX);
> + len = min_t(size_t, length, MAX_ENT_SZ);
> length -= len;
> /*
> * DMABUF abuses scatterlist to create a scatterlist
> @@ -24,7 +27,7 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> * does not require the CPU list for mapping or unmapping.
> */
> sg_set_page(sgl, NULL, 0, 0);
[Severity: Critical]
This is a pre-existing issue, but does passing NULL to sg_set_page here
cause a kernel panic under certain configurations?
When CONFIG_DEBUG_VM and classic SPARSEMEM without VMEMMAP are enabled,
sg_set_page calls page_range_contiguous, which unconditionally calls
page_to_pfn.
On these setups, page_to_pfn determines the memory section by dereferencing
the page flags. Dereferencing a NULL page pointer here causes an immediate
kernel oops.
[ ... ]
> @@ -41,14 +44,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
>
> if (!state || !dma_use_iova(state)) {
> for (i = 0; i < nr_ranges; i++)
> - nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
> + nents += DIV_ROUND_UP(phys_vec[i].len, MAX_ENT_SZ);
[Severity: High]
This is a pre-existing issue, but does this calculation also suffer from the
same 32-bit overflow mentioned above, resolving to 0 for large lengths?
[ ... ]
[Severity: High]
This isn't a bug introduced by this patch, but looking at how the
scatterlists populated by fill_sg_entry are mapped and unmapped, are we
violating the DMA API contract in dma_buf_free_sgt?
In dma_buf_phys_vec_to_sgt, a monolithic physical range is mapped using a
single dma_map_phys call, and then fill_sg_entry splits it into chunks.
However, in dma_buf_free_sgt, dma_unmap_phys is iteratively called on each
individual scatterlist chunk:
for_each_sgtable_dma_sg(sgt, sgl, i)
dma_unmap_phys(attach->dev, sg_dma_address(sgl),
sg_dma_len(sgl), dir, DMA_ATTR_MMIO);
The DMA API requires that an allocation must be unmapped using the exact
same address and size parameters passed during creation. Chunked unmapping
violates this requirement.
[Severity: High]
This is also a pre-existing issue, but does the error path in
dma_buf_phys_vec_to_sgt incorrectly handle unmapping?
If dma_map_phys fails, the code jumps to the err_unmap_dma label. The error
loop uses:
for_each_sgtable_dma_sg(&dma->sgt, sgl, i)
dma_unmap_phys(attach->dev, sg_dma_address(sgl), ...);
Because the loop macro uses i as its internal iterator up to
dma->sgt.nents, which was initialized to the total allocated entries,
it overwrites the failure index.
This causes it to iterate over all allocated entries, including unpopulated
ones, passing 0 for the address and length to dma_unmap_phys, which leads
to invalid DMA unmap requests.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260621222130.1667453-1-xuehaohu@google.com?part=1
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] dma-buf: Split sgl by largest page-aligned chunk
2026-06-21 22:21 [PATCH] dma-buf: Split sgl by largest page-aligned chunk David Hu
2026-06-21 22:34 ` sashiko-bot
@ 2026-06-22 8:13 ` David Laight
2026-06-22 21:26 ` David Hu
2026-06-23 1:54 ` [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks David Hu
2 siblings, 1 reply; 23+ messages in thread
From: David Laight @ 2026-06-22 8:13 UTC (permalink / raw)
To: David Hu
Cc: Sumit Semwal, Christian König, Jason Gunthorpe, Nicolin Chen,
Leon Romanovsky, Kevin Tian, Ankit Agrawal, Alex Williamson,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, iommu,
jmoroni, praan, kpberry, sashiko-bot, stable
On Sun, 21 Jun 2026 22:21:30 +0000
David Hu <xuehaohu@google.com> wrote:
> Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
> This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
> first entry, resulting in non-page-aligned DMA addresses for all
> subsequent entries.
How did you find this?
It requires a single buffer over 4GB - seems highly unlikely.
>
> While the underlying IOMMU mapping may be contiguous, hardware
> DMA engines often require explicit address alignment (e.g., page,
> cacheline, or storage sector boundaries). Passing unaligned
> addresses and lengths can cause explicit failures in DMA descriptor
> creation or silent data corruption if lower unaligned bits are
> truncated.
>
> Fix this by splitting the scatterlist by the largest possible page
> aligned chunk within `UINT_MAX` (`ALIGN_DOWN(UINT_MAX, PAGE_SIZE)`).
> This ensures all scatterlist DMA addresses and lengths remain page
> aligned and satisfy hardware constraints.
It would almost certainly better to spilt into 2G chunks.
That removes any need for any divisions.
> Page-aligned entries allow the system to cleanly chunk payloads into
> PCIe MaxPayloadSize (MPS) (e.g., 128 bytes, 256 bytes, 512 bytes).
> As a result, this may help reduce TLP fragmentation in P2P transfers
> and alleviate potential congestion within a logical PCIe switch
> partition, especially when Relaxed Ordering is not possible due to
> hardware constraints.
>
> Reported-by: sashiko-bot <sashiko-bot@kernel.org>
> Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
> Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Hu <xuehaohu@google.com>
> ---
> drivers/dma-buf/dma-buf-mapping.c | 13 ++++++++-----
> 1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
> index 794acff2546a..f2bde38fdb1f 100644
> --- a/drivers/dma-buf/dma-buf-mapping.c
> +++ b/drivers/dma-buf/dma-buf-mapping.c
> @@ -5,6 +5,9 @@
> */
> #include <linux/dma-buf-mapping.h>
> #include <linux/dma-resv.h>
> +#include <linux/align.h>
> +
> +#define MAX_ENT_SZ ALIGN_DOWN(UINT_MAX, PAGE_SIZE)
>
> static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> dma_addr_t addr)
> @@ -12,9 +15,9 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> unsigned int len, nents;
> int i;
>
> - nents = DIV_ROUND_UP(length, UINT_MAX);
> + nents = DIV_ROUND_UP(length, MAX_ENT_SZ);
> for (i = 0; i < nents; i++) {
Why not change that to 'while (length) {' to avoid the division above.
> - len = min_t(size_t, length, UINT_MAX);
> + len = min_t(size_t, length, MAX_ENT_SZ);
I bet that doesn't need to be min_t()
> length -= len;
> /*
> * DMABUF abuses scatterlist to create a scatterlist
> @@ -24,7 +27,7 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> * does not require the CPU list for mapping or unmapping.
> */
> sg_set_page(sgl, NULL, 0, 0);
> - sg_dma_address(sgl) = addr + (dma_addr_t)i * UINT_MAX;
> + sg_dma_address(sgl) = addr + (dma_addr_t)i * MAX_ENT_SZ;
> sg_dma_len(sgl) = len;
Replace the multiply with 'addr += len'.
-- David
> sgl = sg_next(sgl);
> }
> @@ -41,14 +44,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
>
> if (!state || !dma_use_iova(state)) {
> for (i = 0; i < nr_ranges; i++)
> - nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
> + nents += DIV_ROUND_UP(phys_vec[i].len, MAX_ENT_SZ);
> } else {
> /*
> * In IOVA case, there is only one SG entry which spans
> * for whole IOVA address space, but we need to make sure
> * that it fits sg->length, maybe we need more.
> */
> - nents = DIV_ROUND_UP(size, UINT_MAX);
> + nents = DIV_ROUND_UP(size, MAX_ENT_SZ);
> }
>
> return nents;
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] dma-buf: Split sgl by largest page-aligned chunk
2026-06-22 8:13 ` David Laight
@ 2026-06-22 21:26 ` David Hu
2026-06-23 8:25 ` David Laight
0 siblings, 1 reply; 23+ messages in thread
From: David Hu @ 2026-06-22 21:26 UTC (permalink / raw)
To: David Laight
Cc: Sumit Semwal, Christian König, Jason Gunthorpe, Nicolin Chen,
Leon Romanovsky, Kevin Tian, Ankit Agrawal, Alex Williamson,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, iommu,
jmoroni, praan, kpberry, sashiko-bot, stable
On Mon, Jun 22, 2026 at 4:13 AM David Laight
<david.laight.linux@gmail.com> wrote:
>
Hi David,
Thank you for your review. You raised many good points regarding
optimizations here. I'll switch to using 2G as the max entry size
(`SZ_2G` from `linux/sizes.h`), and remove divisions and
multiplications. I'll also replace the `for()` loop with `while
(length)`, and drop `min_t()` in favor of `min()` by casting `SZ_2G`
to `size_t`. I'll send out a v2 with these changes shortly.
Thanks,
David
> > Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
> > This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
> > first entry, resulting in non-page-aligned DMA addresses for all
> > subsequent entries.
>
> How did you find this?
> It requires a single buffer over 4GB - seems highly unlikely.
It was observed during experiments with buffers over 8GB on an accelerator.
> >
> > While the underlying IOMMU mapping may be contiguous, hardware
> > DMA engines often require explicit address alignment (e.g., page,
> > cacheline, or storage sector boundaries). Passing unaligned
> > addresses and lengths can cause explicit failures in DMA descriptor
> > creation or silent data corruption if lower unaligned bits are
> > truncated.
> >
> > Fix this by splitting the scatterlist by the largest possible page
> > aligned chunk within `UINT_MAX` (`ALIGN_DOWN(UINT_MAX, PAGE_SIZE)`).
> > This ensures all scatterlist DMA addresses and lengths remain page
> > aligned and satisfy hardware constraints.
>
> It would almost certainly better to spilt into 2G chunks.
> That removes any need for any divisions.
I agree. 2G naturally aligns with most hardware boundaries, while also
allowing compiler optimizations with simple bit shifts.
>
> > Page-aligned entries allow the system to cleanly chunk payloads into
> > PCIe MaxPayloadSize (MPS) (e.g., 128 bytes, 256 bytes, 512 bytes).
> > As a result, this may help reduce TLP fragmentation in P2P transfers
> > and alleviate potential congestion within a logical PCIe switch
> > partition, especially when Relaxed Ordering is not possible due to
> > hardware constraints.
> >
> > Reported-by: sashiko-bot <sashiko-bot@kernel.org>
> > Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
> > Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: David Hu <xuehaohu@google.com>
> > ---
> > drivers/dma-buf/dma-buf-mapping.c | 13 ++++++++-----
> > 1 file changed, 8 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
> > index 794acff2546a..f2bde38fdb1f 100644
> > --- a/drivers/dma-buf/dma-buf-mapping.c
> > +++ b/drivers/dma-buf/dma-buf-mapping.c
> > @@ -5,6 +5,9 @@
> > */
> > #include <linux/dma-buf-mapping.h>
> > #include <linux/dma-resv.h>
> > +#include <linux/align.h>
> > +
> > +#define MAX_ENT_SZ ALIGN_DOWN(UINT_MAX, PAGE_SIZE)
>
> >
> > static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> > dma_addr_t addr)
> > @@ -12,9 +15,9 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> > unsigned int len, nents;
> > int i;
> >
> > - nents = DIV_ROUND_UP(length, UINT_MAX);
> > + nents = DIV_ROUND_UP(length, MAX_ENT_SZ);
> > for (i = 0; i < nents; i++) {
>
> Why not change that to 'while (length) {' to avoid the division above.
Sounds good, will do.
>
> > - len = min_t(size_t, length, UINT_MAX);
> > + len = min_t(size_t, length, MAX_ENT_SZ);
>
> I bet that doesn't need to be min_t()
Agreed.
>
> > length -= len;
> > /*
> > * DMABUF abuses scatterlist to create a scatterlist
> > @@ -24,7 +27,7 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> > * does not require the CPU list for mapping or unmapping.
> > */
> > sg_set_page(sgl, NULL, 0, 0);
> > - sg_dma_address(sgl) = addr + (dma_addr_t)i * UINT_MAX;
> > + sg_dma_address(sgl) = addr + (dma_addr_t)i * MAX_ENT_SZ;
> > sg_dma_len(sgl) = len;
>
> Replace the multiply with 'addr += len'.
Will update this as well.
>
> -- David
>
> > sgl = sg_next(sgl);
> > }
> > @@ -41,14 +44,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
> >
> > if (!state || !dma_use_iova(state)) {
> > for (i = 0; i < nr_ranges; i++)
> > - nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
> > + nents += DIV_ROUND_UP(phys_vec[i].len, MAX_ENT_SZ);
> > } else {
> > /*
> > * In IOVA case, there is only one SG entry which spans
> > * for whole IOVA address space, but we need to make sure
> > * that it fits sg->length, maybe we need more.
> > */
> > - nents = DIV_ROUND_UP(size, UINT_MAX);
> > + nents = DIV_ROUND_UP(size, MAX_ENT_SZ);
> > }
> >
> > return nents;
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-06-21 22:21 [PATCH] dma-buf: Split sgl by largest page-aligned chunk David Hu
2026-06-21 22:34 ` sashiko-bot
2026-06-22 8:13 ` David Laight
@ 2026-06-23 1:54 ` David Hu
2026-06-23 2:08 ` sashiko-bot
` (3 more replies)
2 siblings, 4 replies; 23+ messages in thread
From: David Hu @ 2026-06-23 1:54 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: David Laight, Jason Gunthorpe, Nicolin Chen, Leon Romanovsky,
Kevin Tian, Ankit Agrawal, Alex Williamson, linux-media,
dri-devel, linaro-mm-sig, linux-kernel, iommu, jmoroni, praan,
kpberry, chriscli, sashiko-bot, stable, David Hu
Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
first entry, resulting in non-page-aligned DMA addresses for all
subsequent entries.
While the underlying IOMMU mapping may be contiguous, hardware
DMA engines often require explicit address alignment (e.g., page,
cacheline, or storage sector boundaries). Passing unaligned
addresses and lengths can cause explicit failures in DMA descriptor
creation or silent data corruption if lower unaligned bits are
truncated.
Fix this by splitting the scatterlist into 2G chunks. An alternative
previously considered was to use the largest page aligned chunk within
`UINT_MAX` (`ALIGN_DOWN(UINT_MAX, PAGE_SIZE)`) to satisfy page
alignment. A 2G chunk is better as it naturally aligns with most known
hardware boundaries, while also allowing compiler optimizations with
simple bit shifts. This ensures all scatterlist DMA addresses and
lengths remain page aligned and satisfy hardware constraints.
Page-aligned entries allow the system to cleanly chunk payloads into
PCIe MaxPayloadSize (MPS) (e.g., 128 bytes, 256 bytes, 512 bytes).
As a result, this may help reduce TLP fragmentation in P2P transfers
and alleviate potential congestion within a logical PCIe switch
partition, especially when Relaxed Ordering is not possible due to
hardware constraints.
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
Cc: stable@vger.kernel.org
Signed-off-by: David Hu <xuehaohu@google.com>
---
Changes in v2:
- Updated commit title and message to reflect the switch to 2G chunks
- Switch to using 2G as the max sg entry size as it naturally aligns
with most hardware boundaries, while allowing compiler optimizations
with bit shifts (David Laight)
- Optimized away division calculation for `nent`, and multiplication
calculation for sgl address, by dropping the `for` loop in favor of a
`while (length)` loop (David Laight)
- Dropped `min_t` in favor of `min()` to maintain a strict type
checking safety net (David Laight)
drivers/dma-buf/dma-buf-mapping.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 794acff2546a..2d88e08c5ebf 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -5,16 +5,17 @@
*/
#include <linux/dma-buf-mapping.h>
#include <linux/dma-resv.h>
+#include <linux/sizes.h>
+
+#define MAX_SG_ENT_SZ ((size_t)SZ_2G)
static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
dma_addr_t addr)
{
- unsigned int len, nents;
- int i;
+ size_t len;
- nents = DIV_ROUND_UP(length, UINT_MAX);
- for (i = 0; i < nents; i++) {
- len = min_t(size_t, length, UINT_MAX);
+ while (length) {
+ len = min(length, MAX_SG_ENT_SZ);
length -= len;
/*
* DMABUF abuses scatterlist to create a scatterlist
@@ -24,11 +25,12 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
* does not require the CPU list for mapping or unmapping.
*/
sg_set_page(sgl, NULL, 0, 0);
- sg_dma_address(sgl) = addr + (dma_addr_t)i * UINT_MAX;
+ sg_dma_address(sgl) = addr;
sg_dma_len(sgl) = len;
+ addr += len;
+ /* Unconditionally advance. On last segment, this becomes NULL */
sgl = sg_next(sgl);
}
-
return sgl;
}
@@ -41,14 +43,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
if (!state || !dma_use_iova(state)) {
for (i = 0; i < nr_ranges; i++)
- nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
+ nents += DIV_ROUND_UP(phys_vec[i].len, MAX_SG_ENT_SZ);
} else {
/*
* In IOVA case, there is only one SG entry which spans
* for whole IOVA address space, but we need to make sure
* that it fits sg->length, maybe we need more.
*/
- nents = DIV_ROUND_UP(size, UINT_MAX);
+ nents = DIV_ROUND_UP(size, MAX_SG_ENT_SZ);
}
return nents;
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-06-23 1:54 ` [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks David Hu
@ 2026-06-23 2:08 ` sashiko-bot
2026-06-23 8:44 ` David Laight
` (2 subsequent siblings)
3 siblings, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-06-23 2:08 UTC (permalink / raw)
To: David Hu; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Critical] Arithmetic overflow in `calc_sg_nents` on 32-bit systems causes an under-allocation of scatterlist entries, leading to a NULL pointer dereference in `fill_sg_entry`.
Pre-existing issues:
- [High] Incorrect DMA unmapping of split scatterlist chunks and unpopulated entries violates the DMA API and corrupts IOMMU state.
--
commit f3f35bb73743f61d1b46175517c947331e0902f1
Author: David Hu <xuehaohu@google.com>
dma-buf: Split sgl into page-aligned 2G chunks
Currently, fill_sg_entry() splits the scatterlist using UINT_MAX. This patch
changes the split to 2G chunks to satisfy page alignment and natural hardware
boundaries for DMA engines.
Link: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
> diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
> index 794acff2546a3..2d88e08c5ebf9 100644
> --- a/drivers/dma-buf/dma-buf-mapping.c
> +++ b/drivers/dma-buf/dma-buf-mapping.c
> @@ -5,16 +5,17 @@
> */
> #include <linux/dma-buf-mapping.h>
> #include <linux/dma-resv.h>
> +#include <linux/sizes.h>
> +
> +#define MAX_SG_ENT_SZ ((size_t)SZ_2G)
>
> static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> dma_addr_t addr)
> {
> - unsigned int len, nents;
> - int i;
> + size_t len;
>
> - nents = DIV_ROUND_UP(length, UINT_MAX);
> - for (i = 0; i < nents; i++) {
> - len = min_t(size_t, length, UINT_MAX);
> + while (length) {
> + len = min(length, MAX_SG_ENT_SZ);
> length -= len;
> /*
> * DMABUF abuses scatterlist to create a scatterlist
> @@ -24,11 +25,12 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> * does not require the CPU list for mapping or unmapping.
> */
> sg_set_page(sgl, NULL, 0, 0);
[Severity: Critical]
Will this lead to a NULL pointer dereference on 32-bit systems?
If phys_vec[i].len is greater than 2GB (e.g. 0x80000001), the DIV_ROUND_UP
macro in calc_sg_nents() will overflow because size_t is 32-bit and
MAX_SG_ENT_SZ is 0x80000000:
(0x80000001 + 0x80000000 - 1) / 0x80000000 == 0
This means no SGL entries are calculated or allocated for this region. However,
the while loop in fill_sg_entry() will still iterate to process the remaining
length. It will eventually advance past the end of the undersized scatterlist
table via:
sgl = sg_next(sgl);
which becomes NULL, and then dereference it on the next iteration via
sg_set_page(sgl, ...).
> - sg_dma_address(sgl) = addr + (dma_addr_t)i * UINT_MAX;
> + sg_dma_address(sgl) = addr;
> sg_dma_len(sgl) = len;
> + addr += len;
> + /* Unconditionally advance. On last segment, this becomes NULL */
> sgl = sg_next(sgl);
> }
> -
> return sgl;
> }
>
> @@ -41,14 +43,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
>
> if (!state || !dma_use_iova(state)) {
> for (i = 0; i < nr_ranges; i++)
> - nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
> + nents += DIV_ROUND_UP(phys_vec[i].len, MAX_SG_ENT_SZ);
> } else {
> /*
> * In IOVA case, there is only one SG entry which spans
> * for whole IOVA address space, but we need to make sure
> * that it fits sg->length, maybe we need more.
> */
> - nents = DIV_ROUND_UP(size, UINT_MAX);
> + nents = DIV_ROUND_UP(size, MAX_SG_ENT_SZ);
> }
>
> return nents;
[Severity: High]
This isn't a bug introduced by this patch, but does iterating over the SGL to
unmap chunked entries violate the DMA API?
In dma_buf_phys_vec_to_sgt(), dma_map_phys() maps the full, contiguous original
length of phys_vec[i].len. However, fill_sg_entry() splits this mapped region
into smaller chunks.
When unmapping, both the error path in dma_buf_phys_vec_to_sgt() and the
teardown in dma_buf_free_sgt() iterate over the split SGL entries:
drivers/dma-buf/dma-buf-mapping.c:dma_buf_free_sgt() {
...
for_each_sgtable_dma_sg(sgt, sgl, i)
dma_unmap_phys(attach->dev, sg_dma_address(sgl),
sg_dma_len(sgl), dir, DMA_ATTR_MMIO);
...
}
Does the DMA API permit unmapping partial chunks instead of the exact length
and address originally mapped?
Additionally, in the error path of dma_buf_phys_vec_to_sgt():
drivers/dma-buf/dma-buf-mapping.c:dma_buf_phys_vec_to_sgt() {
...
err_unmap_dma:
if (!i || !dma->state) {
; /* Do nothing */
...
} else {
for_each_sgtable_dma_sg(&dma->sgt, sgl, i)
dma_unmap_phys(attach->dev, sg_dma_address(sgl),
sg_dma_len(sgl), dir, DMA_ATTR_MMIO);
}
...
}
Is it safe to reuse the outer loop variable i here? Since i was tracking the
successfully mapped count, using it in for_each_sgtable_dma_sg() clobbers it
and forces iteration up to the sgt->nents capacity, which could unmap
unpopulated zero-initialized entries or page 0.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260623015459.1153884-1-xuehaohu@google.com?part=1
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] dma-buf: Split sgl by largest page-aligned chunk
2026-06-22 21:26 ` David Hu
@ 2026-06-23 8:25 ` David Laight
2026-06-23 21:03 ` David Hu
0 siblings, 1 reply; 23+ messages in thread
From: David Laight @ 2026-06-23 8:25 UTC (permalink / raw)
To: David Hu
Cc: Sumit Semwal, Christian König, Jason Gunthorpe, Nicolin Chen,
Leon Romanovsky, Kevin Tian, Ankit Agrawal, Alex Williamson,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, iommu,
jmoroni, praan, kpberry, sashiko-bot, stable
On Mon, 22 Jun 2026 17:26:10 -0400
David Hu <xuehaohu@google.com> wrote:
> On Mon, Jun 22, 2026 at 4:13 AM David Laight
> <david.laight.linux@gmail.com> wrote:
> >
>
> Hi David,
>
> Thank you for your review. You raised many good points regarding
> optimizations here. I'll switch to using 2G as the max entry size
> (`SZ_2G` from `linux/sizes.h`), and remove divisions and
> multiplications. I'll also replace the `for()` loop with `while
> (length)`, and drop `min_t()` in favor of `min()` by casting `SZ_2G`
> to `size_t`.
You shouldn't need a cast at all.
David L.
> I'll send out a v2 with these changes shortly.
>
> Thanks,
> David
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-06-23 1:54 ` [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks David Hu
2026-06-23 2:08 ` sashiko-bot
@ 2026-06-23 8:44 ` David Laight
2026-06-23 20:55 ` Pranjal Shrivastava
2026-06-30 12:38 ` Jason Gunthorpe
2026-07-22 23:38 ` [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk dhu
2026-07-22 23:39 ` dhu
3 siblings, 2 replies; 23+ messages in thread
From: David Laight @ 2026-06-23 8:44 UTC (permalink / raw)
To: David Hu
Cc: Sumit Semwal, Christian König, Jason Gunthorpe, Nicolin Chen,
Leon Romanovsky, Kevin Tian, Ankit Agrawal, Alex Williamson,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, iommu,
jmoroni, praan, kpberry, chriscli, sashiko-bot, stable
On Tue, 23 Jun 2026 01:54:59 +0000
David Hu <xuehaohu@google.com> wrote:
> Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
> This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
> first entry, resulting in non-page-aligned DMA addresses for all
> subsequent entries.
There is a separate issue of whether this code is even needed at all.
Where can transfers over 2G (never mind 4G) actually come from.
The read, write and similar system calls limit transfers to INT_MAX
(even on 64bit) and a lot of driver code will need fixing it longer
lengths are allowed though.
io_uring better enforce the same limits.
So the transfers can come directly from userspace.
Not only that but you also need a single physically contiguous buffer.
Good luck allocating that!
Now maybe there are some peer-to-peer places where the large buffer
is device memory, but they will be unusual and probably need
special treatment anyway.
David
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-06-23 8:44 ` David Laight
@ 2026-06-23 20:55 ` Pranjal Shrivastava
2026-06-23 22:53 ` David Laight
2026-06-30 12:38 ` Jason Gunthorpe
1 sibling, 1 reply; 23+ messages in thread
From: Pranjal Shrivastava @ 2026-06-23 20:55 UTC (permalink / raw)
To: David Laight
Cc: David Hu, Sumit Semwal, Christian König, Jason Gunthorpe,
Nicolin Chen, Leon Romanovsky, Kevin Tian, Ankit Agrawal,
Alex Williamson, linux-media, dri-devel, linaro-mm-sig,
linux-kernel, iommu, jmoroni, kpberry, chriscli, sashiko-bot,
stable
On Tue, Jun 23, 2026 at 09:44:46AM +0100, David Laight wrote:
Hi David,
> On Tue, 23 Jun 2026 01:54:59 +0000
> David Hu <xuehaohu@google.com> wrote:
>
> > Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
> > This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
> > first entry, resulting in non-page-aligned DMA addresses for all
> > subsequent entries.
>
> There is a separate issue of whether this code is even needed at all.
> Where can transfers over 2G (never mind 4G) actually come from.
>
> The read, write and similar system calls limit transfers to INT_MAX
> (even on 64bit) and a lot of driver code will need fixing it longer
> lengths are allowed though.
> io_uring better enforce the same limits.
> So the transfers can come directly from userspace.
>
> Not only that but you also need a single physically contiguous buffer.
> Good luck allocating that!
>
> Now maybe there are some peer-to-peer places where the large buffer
> is device memory, but they will be unusual and probably need
> special treatment anyway.
>
I agree that traditional VFS read/write face the MAX_RW_COUNT limit
(~2GB), and io_uring has its limits, but I'm a little confused by the
push to enforce these limits here in the SGL code?
File I/O seems to be only one side of the picture. In my view, this fix
is necessary and certainly has a use-case:
For example, the RDMA subsystem has the capability to import dmabufs [1],
which gives rise to use cases for dmabuf beyond standard file ops
(via VFS/io_uring).
In these scenarios, GPU HBM can be exported as dmabufs. With recent GPUs,
HBM capacity can be in the order of hundreds of GBs [2]. RDMA can employ
infrastructure like the vfio-dmabuf-exporter [3] or similar dmabuf
exporters to frequently move huge blocks of data via P2PDMA.
If we restrict incoming dmabuf transfers to fit within VFS-centric
limits (2GB), we impose unnecessary overhead on the RDMA stack, forcing
it to manage a significantly higher number of memory registrations. By
cleanly splitting these massive contiguous device buffers into
page-aligned SGL entries, we directly improve the efficiency of P2P
transfers and memory registration.
Since this change doesn't seem to have a negative impact on standard file
I/O or break existing VFS constraints, I'm curious why we shouldn't
support splitting these >4GB P2P transfers? Am I missing something?
Thanks,
Praan
[1] https://elixir.bootlin.com/linux/v7.1.1/source/drivers/infiniband/core/umem_dmabuf.c#L174
[2] https://nvdam.widen.net/s/fdvdqvfvj2/hopper-h200-nvl-product-brief (Table 2-2)
[3] https://elixir.bootlin.com/linux/v7.1.1/source/drivers/vfio/pci/vfio_pci_dmabuf.c#L297
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] dma-buf: Split sgl by largest page-aligned chunk
2026-06-23 8:25 ` David Laight
@ 2026-06-23 21:03 ` David Hu
0 siblings, 0 replies; 23+ messages in thread
From: David Hu @ 2026-06-23 21:03 UTC (permalink / raw)
To: David Laight
Cc: Sumit Semwal, Christian König, Jason Gunthorpe, Nicolin Chen,
Leon Romanovsky, Kevin Tian, Ankit Agrawal, Alex Williamson,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, iommu,
jmoroni, praan, kpberry, sashiko-bot, stable
On Tue, Jun 23, 2026 at 4:25 AM David Laight
<david.laight.linux@gmail.com> wrote:
>
> On Mon, 22 Jun 2026 17:26:10 -0400
> David Hu <xuehaohu@google.com> wrote:
>
> > On Mon, Jun 22, 2026 at 4:13 AM David Laight
> > <david.laight.linux@gmail.com> wrote:
> > >
> >
> > Hi David,
> >
> > Thank you for your review. You raised many good points regarding
> > optimizations here. I'll switch to using 2G as the max entry size
> > (`SZ_2G` from `linux/sizes.h`), and remove divisions and
> > multiplications. I'll also replace the `for()` loop with `while
> > (length)`, and drop `min_t()` in favor of `min()` by casting `SZ_2G`
> > to `size_t`.
>
> You shouldn't need a cast at all.
Hi David,
You are right. It looks like `min(length, CONSTANT)` works well here
without triggering any type mismatch warnings, regardless of whether
`CONSTANT` is `SZ_1G` (`int`), `SZ_2G` (`unsigned int`), `SZ_4G`
(`unsigned long long`), or larger. I'll drop the cast and send out a
v3 shortly.
Thanks,
David
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-06-23 20:55 ` Pranjal Shrivastava
@ 2026-06-23 22:53 ` David Laight
2026-06-24 14:31 ` Leon Romanovsky
2026-06-30 12:42 ` Jason Gunthorpe
0 siblings, 2 replies; 23+ messages in thread
From: David Laight @ 2026-06-23 22:53 UTC (permalink / raw)
To: Pranjal Shrivastava
Cc: David Hu, Sumit Semwal, Christian König, Jason Gunthorpe,
Nicolin Chen, Leon Romanovsky, Kevin Tian, Ankit Agrawal,
Alex Williamson, linux-media, dri-devel, linaro-mm-sig,
linux-kernel, iommu, jmoroni, kpberry, chriscli, sashiko-bot,
stable
On Tue, 23 Jun 2026 20:55:32 +0000
Pranjal Shrivastava <praan@google.com> wrote:
> On Tue, Jun 23, 2026 at 09:44:46AM +0100, David Laight wrote:
>
> Hi David,
>
> > On Tue, 23 Jun 2026 01:54:59 +0000
> > David Hu <xuehaohu@google.com> wrote:
> >
> > > Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
> > > This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
> > > first entry, resulting in non-page-aligned DMA addresses for all
> > > subsequent entries.
> >
> > There is a separate issue of whether this code is even needed at all.
> > Where can transfers over 2G (never mind 4G) actually come from.
> >
> > The read, write and similar system calls limit transfers to INT_MAX
> > (even on 64bit) and a lot of driver code will need fixing it longer
> > lengths are allowed though.
> > io_uring better enforce the same limits.
> > So the transfers can come directly from userspace.
> >
> > Not only that but you also need a single physically contiguous buffer.
> > Good luck allocating that!
> >
> > Now maybe there are some peer-to-peer places where the large buffer
> > is device memory, but they will be unusual and probably need
> > special treatment anyway.
> >
>
> I agree that traditional VFS read/write face the MAX_RW_COUNT limit
> (~2GB), and io_uring has its limits, but I'm a little confused by the
> push to enforce these limits here in the SGL code?
>
> File I/O seems to be only one side of the picture. In my view, this fix
> is necessary and certainly has a use-case:
>
> For example, the RDMA subsystem has the capability to import dmabufs [1],
> which gives rise to use cases for dmabuf beyond standard file ops
> (via VFS/io_uring).
>
> In these scenarios, GPU HBM can be exported as dmabufs. With recent GPUs,
> HBM capacity can be in the order of hundreds of GBs [2]. RDMA can employ
> infrastructure like the vfio-dmabuf-exporter [3] or similar dmabuf
> exporters to frequently move huge blocks of data via P2PDMA.
Ok, that explains where big buffers can come from.
I just wasn't sure.
> If we restrict incoming dmabuf transfers to fit within VFS-centric
> limits (2GB), we impose unnecessary overhead on the RDMA stack, forcing
> it to manage a significantly higher number of memory registrations. By
> cleanly splitting these massive contiguous device buffers into
> page-aligned SGL entries, we directly improve the efficiency of P2P
> transfers and memory registration.
But a divide by '4G - PAGE_SIZE' is also non-trivial and (I think affects
a lot of io) when the quotient is always 1.
Splitting into 2G chunks is a lot cheaper.
> Since this change doesn't seem to have a negative impact on standard file
> I/O or break existing VFS constraints, I'm curious why we shouldn't
> support splitting these >4GB P2P transfers? Am I missing something?
I was only wondering whether it was needed...
It does bring up the question of why the >4GB transfers even need splitting.
But that is another question.
If you want to split large transfers into 4G-PAGE_SIZE blocks
it is probably worth having a quick test that returns 1 for 'small' buffers.
David
>
> Thanks,
> Praan
>
> [1] https://elixir.bootlin.com/linux/v7.1.1/source/drivers/infiniband/core/umem_dmabuf.c#L174
> [2] https://nvdam.widen.net/s/fdvdqvfvj2/hopper-h200-nvl-product-brief (Table 2-2)
> [3] https://elixir.bootlin.com/linux/v7.1.1/source/drivers/vfio/pci/vfio_pci_dmabuf.c#L297
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-06-23 22:53 ` David Laight
@ 2026-06-24 14:31 ` Leon Romanovsky
2026-06-30 12:42 ` Jason Gunthorpe
1 sibling, 0 replies; 23+ messages in thread
From: Leon Romanovsky @ 2026-06-24 14:31 UTC (permalink / raw)
To: David Laight
Cc: Pranjal Shrivastava, David Hu, Sumit Semwal, Christian König,
Jason Gunthorpe, Nicolin Chen, Kevin Tian, Ankit Agrawal,
Alex Williamson, linux-media, dri-devel, linaro-mm-sig,
linux-kernel, iommu, jmoroni, kpberry, chriscli, sashiko-bot,
stable
On Tue, Jun 23, 2026 at 11:53:50PM +0100, David Laight wrote:
> On Tue, 23 Jun 2026 20:55:32 +0000
> Pranjal Shrivastava <praan@google.com> wrote:
>
> > On Tue, Jun 23, 2026 at 09:44:46AM +0100, David Laight wrote:
> >
> > Hi David,
> >
> > > On Tue, 23 Jun 2026 01:54:59 +0000
> > > David Hu <xuehaohu@google.com> wrote:
> > >
> > > > Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
> > > > This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
> > > > first entry, resulting in non-page-aligned DMA addresses for all
> > > > subsequent entries.
> > >
> > > There is a separate issue of whether this code is even needed at all.
> > > Where can transfers over 2G (never mind 4G) actually come from.
> > >
> > > The read, write and similar system calls limit transfers to INT_MAX
> > > (even on 64bit) and a lot of driver code will need fixing it longer
> > > lengths are allowed though.
> > > io_uring better enforce the same limits.
> > > So the transfers can come directly from userspace.
> > >
> > > Not only that but you also need a single physically contiguous buffer.
> > > Good luck allocating that!
> > >
> > > Now maybe there are some peer-to-peer places where the large buffer
> > > is device memory, but they will be unusual and probably need
> > > special treatment anyway.
> > >
> >
> > I agree that traditional VFS read/write face the MAX_RW_COUNT limit
> > (~2GB), and io_uring has its limits, but I'm a little confused by the
> > push to enforce these limits here in the SGL code?
> >
> > File I/O seems to be only one side of the picture. In my view, this fix
> > is necessary and certainly has a use-case:
> >
> > For example, the RDMA subsystem has the capability to import dmabufs [1],
> > which gives rise to use cases for dmabuf beyond standard file ops
> > (via VFS/io_uring).
> >
> > In these scenarios, GPU HBM can be exported as dmabufs. With recent GPUs,
> > HBM capacity can be in the order of hundreds of GBs [2]. RDMA can employ
> > infrastructure like the vfio-dmabuf-exporter [3] or similar dmabuf
> > exporters to frequently move huge blocks of data via P2PDMA.
>
> Ok, that explains where big buffers can come from.
> I just wasn't sure.
>
> > If we restrict incoming dmabuf transfers to fit within VFS-centric
> > limits (2GB), we impose unnecessary overhead on the RDMA stack, forcing
> > it to manage a significantly higher number of memory registrations. By
> > cleanly splitting these massive contiguous device buffers into
> > page-aligned SGL entries, we directly improve the efficiency of P2P
> > transfers and memory registration.
>
> But a divide by '4G - PAGE_SIZE' is also non-trivial and (I think affects
> a lot of io) when the quotient is always 1.
> Splitting into 2G chunks is a lot cheaper.
>
> > Since this change doesn't seem to have a negative impact on standard file
> > I/O or break existing VFS constraints, I'm curious why we shouldn't
> > support splitting these >4GB P2P transfers? Am I missing something?
>
> I was only wondering whether it was needed...
> It does bring up the question of why the >4GB transfers even need splitting.
> But that is another question.
Just a side note:
In our vision, we aim to transition DMABUF to use physical
addresses directly https://lore.kernel.org/all/0-v1-b5cab63049c0+191af-dmabuf_map_type_jgg@nvidia.com/
and eliminate the scatter‑gather layer from the DMABUF path.
Thanks
>
> If you want to split large transfers into 4G-PAGE_SIZE blocks
> it is probably worth having a quick test that returns 1 for 'small' buffers.
>
> David
>
> >
> > Thanks,
> > Praan
> >
> > [1] https://elixir.bootlin.com/linux/v7.1.1/source/drivers/infiniband/core/umem_dmabuf.c#L174
> > [2] https://nvdam.widen.net/s/fdvdqvfvj2/hopper-h200-nvl-product-brief (Table 2-2)
> > [3] https://elixir.bootlin.com/linux/v7.1.1/source/drivers/vfio/pci/vfio_pci_dmabuf.c#L297
> >
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-06-23 8:44 ` David Laight
2026-06-23 20:55 ` Pranjal Shrivastava
@ 2026-06-30 12:38 ` Jason Gunthorpe
1 sibling, 0 replies; 23+ messages in thread
From: Jason Gunthorpe @ 2026-06-30 12:38 UTC (permalink / raw)
To: David Laight
Cc: David Hu, Sumit Semwal, Christian König, Nicolin Chen,
Leon Romanovsky, Kevin Tian, Ankit Agrawal, Alex Williamson,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, iommu,
jmoroni, praan, kpberry, chriscli, sashiko-bot, stable
On Tue, Jun 23, 2026 at 09:44:46AM +0100, David Laight wrote:
> On Tue, 23 Jun 2026 01:54:59 +0000
> David Hu <xuehaohu@google.com> wrote:
>
> > Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
> > This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
> > first entry, resulting in non-page-aligned DMA addresses for all
> > subsequent entries.
>
> There is a separate issue of whether this code is even needed at all.
> Where can transfers over 2G (never mind 4G) actually come from.
This is DMABUF land, you really can alocate DMABUFS of huge amounts of
physical memory, VFIO does this reliably and trivially for example. It
wouldn't come from the physical allocator.
So yes, these scenarios need to work in this code.
Jason
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-06-23 22:53 ` David Laight
2026-06-24 14:31 ` Leon Romanovsky
@ 2026-06-30 12:42 ` Jason Gunthorpe
2026-07-02 4:56 ` David Hu
1 sibling, 1 reply; 23+ messages in thread
From: Jason Gunthorpe @ 2026-06-30 12:42 UTC (permalink / raw)
To: David Laight
Cc: Pranjal Shrivastava, David Hu, Sumit Semwal, Christian König,
Nicolin Chen, Leon Romanovsky, Kevin Tian, Ankit Agrawal,
Alex Williamson, linux-media, dri-devel, linaro-mm-sig,
linux-kernel, iommu, jmoroni, kpberry, chriscli, sashiko-bot,
stable
On Tue, Jun 23, 2026 at 11:53:50PM +0100, David Laight wrote:
> > If we restrict incoming dmabuf transfers to fit within VFS-centric
> > limits (2GB), we impose unnecessary overhead on the RDMA stack, forcing
> > it to manage a significantly higher number of memory registrations. By
> > cleanly splitting these massive contiguous device buffers into
> > page-aligned SGL entries, we directly improve the efficiency of P2P
> > transfers and memory registration.
>
> But a divide by '4G - PAGE_SIZE' is also non-trivial and (I think affects
> a lot of io) when the quotient is always 1.
> Splitting into 2G chunks is a lot cheaper.
Doesn't matter this isn't fast path stuff. It is better to use fewer
SGL entries, IHMO.
> > Since this change doesn't seem to have a negative impact on standard file
> > I/O or break existing VFS constraints, I'm curious why we shouldn't
> > support splitting these >4GB P2P transfers? Am I missing something?
>
> I was only wondering whether it was needed...
> It does bring up the question of why the >4GB transfers even need splitting.
> But that is another question.
SGL can only store an unsigned int size, so any large physical range
has to be split down.
rdma now a days has code to process the sgl and restore back the > 4G
sizes since mode RDMA HW can accept that.
commit 486055f5e09df959ad4e3aa4ee75b5c91ddeec2e
Author: Michael Margolin <mrgolin@amazon.com>
Date: Mon Feb 17 14:16:23 2025 +0000
RDMA/core: Fix best page size finding when it can cross SG entries
So whatever this produces needs to be compatible with that to undo it.
Jason
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-06-30 12:42 ` Jason Gunthorpe
@ 2026-07-02 4:56 ` David Hu
2026-07-02 8:10 ` David Laight
0 siblings, 1 reply; 23+ messages in thread
From: David Hu @ 2026-07-02 4:56 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: David Laight, Pranjal Shrivastava, Sumit Semwal,
Christian König, Nicolin Chen, Leon Romanovsky, Kevin Tian,
Ankit Agrawal, Alex Williamson, linux-media, dri-devel,
linaro-mm-sig, linux-kernel, iommu, jmoroni, kpberry, chriscli,
sashiko-bot, stable
On Tue, Jun 30, 2026 at 8:42 AM Jason Gunthorpe <jgg@ziepe.ca> wrote:
>
> On Tue, Jun 23, 2026 at 11:53:50PM +0100, David Laight wrote:
>
> > > If we restrict incoming dmabuf transfers to fit within VFS-centric
> > > limits (2GB), we impose unnecessary overhead on the RDMA stack, forcing
> > > it to manage a significantly higher number of memory registrations. By
> > > cleanly splitting these massive contiguous device buffers into
> > > page-aligned SGL entries, we directly improve the efficiency of P2P
> > > transfers and memory registration.
> >
> > But a divide by '4G - PAGE_SIZE' is also non-trivial and (I think affects
> > a lot of io) when the quotient is always 1.
> > Splitting into 2G chunks is a lot cheaper.
>
> Doesn't matter this isn't fast path stuff. It is better to use fewer
> SGL entries, IHMO.
>
> > > Since this change doesn't seem to have a negative impact on standard file
> > > I/O or break existing VFS constraints, I'm curious why we shouldn't
> > > support splitting these >4GB P2P transfers? Am I missing something?
> >
> > I was only wondering whether it was needed...
> > It does bring up the question of why the >4GB transfers even need splitting.
> > But that is another question.
>
> SGL can only store an unsigned int size, so any large physical range
> has to be split down.
>
> rdma now a days has code to process the sgl and restore back the > 4G
> sizes since mode RDMA HW can accept that.
>
> commit 486055f5e09df959ad4e3aa4ee75b5c91ddeec2e
> Author: Michael Margolin <mrgolin@amazon.com>
> Date: Mon Feb 17 14:16:23 2025 +0000
>
> RDMA/core: Fix best page size finding when it can cross SG entries
>
> So whatever this produces needs to be compatible with that to undo it.
Thank you everyone. It looks like most open issues are sorted out.
I'll wait for maintainers to weigh in before sending out v3 (which
will remove the type cast for min() per David L.'s feedback, and
revert to ALIGN_DOWN(UINT_MAX, PAGE_SIZE) per Jason's feedback).
Hi Jason,
Thank you for your feedback. I took a closer look at the commit to
ensure compatibility. This patch is perfectly complementary, and
actually prevents a failure in an edge case for the latest
`ib_umem_find_best_pgsz` [1].
Regards,
David
[1] For dma-buf split with `0xFFFFFFFF`, in case of a discontinguity
in later buffers, we will hit this code path in
`ib_umem_find_best_pgsz`
```
if (i != 0)
mask |= va;
```
(*After `va` had been incremented by `0xFFFFFFFF`, due to `va +=
sg_dma_len(sg) - pgoff`)
(*Which will set the lowest bit of `mask` to 1)
Because `count_trailing_zeros(mask) returns 0`,
`ib_umem_find_best_pgsz()` will always return 0 in such cases.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-07-02 4:56 ` David Hu
@ 2026-07-02 8:10 ` David Laight
2026-07-03 4:11 ` David Hu
0 siblings, 1 reply; 23+ messages in thread
From: David Laight @ 2026-07-02 8:10 UTC (permalink / raw)
To: David Hu
Cc: Jason Gunthorpe, Pranjal Shrivastava, Sumit Semwal,
Christian König, Nicolin Chen, Leon Romanovsky, Kevin Tian,
Ankit Agrawal, Alex Williamson, linux-media, dri-devel,
linaro-mm-sig, linux-kernel, iommu, jmoroni, kpberry, chriscli,
sashiko-bot, stable
On Thu, 2 Jul 2026 00:56:40 -0400
David Hu <xuehaohu@google.com> wrote:
> On Tue, Jun 30, 2026 at 8:42 AM Jason Gunthorpe <jgg@ziepe.ca> wrote:
> >
> > On Tue, Jun 23, 2026 at 11:53:50PM +0100, David Laight wrote:
> >
> > > > If we restrict incoming dmabuf transfers to fit within VFS-centric
> > > > limits (2GB), we impose unnecessary overhead on the RDMA stack, forcing
> > > > it to manage a significantly higher number of memory registrations. By
> > > > cleanly splitting these massive contiguous device buffers into
> > > > page-aligned SGL entries, we directly improve the efficiency of P2P
> > > > transfers and memory registration.
> > >
> > > But a divide by '4G - PAGE_SIZE' is also non-trivial and (I think affects
> > > a lot of io) when the quotient is always 1.
> > > Splitting into 2G chunks is a lot cheaper.
> >
> > Doesn't matter this isn't fast path stuff. It is better to use fewer
> > SGL entries, IHMO.
> >
> > > > Since this change doesn't seem to have a negative impact on standard file
> > > > I/O or break existing VFS constraints, I'm curious why we shouldn't
> > > > support splitting these >4GB P2P transfers? Am I missing something?
> > >
> > > I was only wondering whether it was needed...
> > > It does bring up the question of why the >4GB transfers even need splitting.
> > > But that is another question.
> >
> > SGL can only store an unsigned int size, so any large physical range
> > has to be split down.
> >
> > rdma now a days has code to process the sgl and restore back the > 4G
> > sizes since mode RDMA HW can accept that.
> >
> > commit 486055f5e09df959ad4e3aa4ee75b5c91ddeec2e
> > Author: Michael Margolin <mrgolin@amazon.com>
> > Date: Mon Feb 17 14:16:23 2025 +0000
> >
> > RDMA/core: Fix best page size finding when it can cross SG entries
> >
> > So whatever this produces needs to be compatible with that to undo it.
>
> Thank you everyone. It looks like most open issues are sorted out.
> I'll wait for maintainers to weigh in before sending out v3 (which
> will remove the type cast for min() per David L.'s feedback, and
> revert to ALIGN_DOWN(UINT_MAX, PAGE_SIZE) per Jason's feedback).
Does this code get used a lot for 'normal' transfers?
I'm away from my normal systems and can't check.
But if pretty much all of the fragments are small (< 4G) then
it is probably worth adding a check for 'size < limit' before
anything else and optimising that case.
David
>
> Hi Jason,
>
> Thank you for your feedback. I took a closer look at the commit to
> ensure compatibility. This patch is perfectly complementary, and
> actually prevents a failure in an edge case for the latest
> `ib_umem_find_best_pgsz` [1].
>
> Regards,
> David
>
> [1] For dma-buf split with `0xFFFFFFFF`, in case of a discontinguity
> in later buffers, we will hit this code path in
> `ib_umem_find_best_pgsz`
>
> ```
> if (i != 0)
> mask |= va;
> ```
> (*After `va` had been incremented by `0xFFFFFFFF`, due to `va +=
> sg_dma_len(sg) - pgoff`)
> (*Which will set the lowest bit of `mask` to 1)
>
> Because `count_trailing_zeros(mask) returns 0`,
> `ib_umem_find_best_pgsz()` will always return 0 in such cases.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks
2026-07-02 8:10 ` David Laight
@ 2026-07-03 4:11 ` David Hu
0 siblings, 0 replies; 23+ messages in thread
From: David Hu @ 2026-07-03 4:11 UTC (permalink / raw)
To: David Laight
Cc: Jason Gunthorpe, Pranjal Shrivastava, Sumit Semwal,
Christian König, Nicolin Chen, Leon Romanovsky, Kevin Tian,
Ankit Agrawal, Alex Williamson, linux-media, dri-devel,
linaro-mm-sig, linux-kernel, iommu, jmoroni, kpberry, chriscli,
sashiko-bot, stable
On Thu, Jul 2, 2026 at 4:10 AM David Laight
<david.laight.linux@gmail.com> wrote:
>
> On Thu, 2 Jul 2026 00:56:40 -0400
> David Hu <xuehaohu@google.com> wrote:
>
> > On Tue, Jun 30, 2026 at 8:42 AM Jason Gunthorpe <jgg@ziepe.ca> wrote:
> > >
> > > On Tue, Jun 23, 2026 at 11:53:50PM +0100, David Laight wrote:
> > >
> > > > > If we restrict incoming dmabuf transfers to fit within VFS-centric
> > > > > limits (2GB), we impose unnecessary overhead on the RDMA stack, forcing
> > > > > it to manage a significantly higher number of memory registrations. By
> > > > > cleanly splitting these massive contiguous device buffers into
> > > > > page-aligned SGL entries, we directly improve the efficiency of P2P
> > > > > transfers and memory registration.
> > > >
> > > > But a divide by '4G - PAGE_SIZE' is also non-trivial and (I think affects
> > > > a lot of io) when the quotient is always 1.
> > > > Splitting into 2G chunks is a lot cheaper.
> > >
> > > Doesn't matter this isn't fast path stuff. It is better to use fewer
> > > SGL entries, IHMO.
> > >
> > > > > Since this change doesn't seem to have a negative impact on standard file
> > > > > I/O or break existing VFS constraints, I'm curious why we shouldn't
> > > > > support splitting these >4GB P2P transfers? Am I missing something?
> > > >
> > > > I was only wondering whether it was needed...
> > > > It does bring up the question of why the >4GB transfers even need splitting.
> > > > But that is another question.
> > >
> > > SGL can only store an unsigned int size, so any large physical range
> > > has to be split down.
> > >
> > > rdma now a days has code to process the sgl and restore back the > 4G
> > > sizes since mode RDMA HW can accept that.
> > >
> > > commit 486055f5e09df959ad4e3aa4ee75b5c91ddeec2e
> > > Author: Michael Margolin <mrgolin@amazon.com>
> > > Date: Mon Feb 17 14:16:23 2025 +0000
> > >
> > > RDMA/core: Fix best page size finding when it can cross SG entries
> > >
> > > So whatever this produces needs to be compatible with that to undo it.
> >
> > Thank you everyone. It looks like most open issues are sorted out.
> > I'll wait for maintainers to weigh in before sending out v3 (which
> > will remove the type cast for min() per David L.'s feedback, and
> > revert to ALIGN_DOWN(UINT_MAX, PAGE_SIZE) per Jason's feedback).
>
> Does this code get used a lot for 'normal' transfers?
> I'm away from my normal systems and can't check.
> But if pretty much all of the fragments are small (< 4G) then
> it is probably worth adding a check for 'size < limit' before
> anything else and optimising that case.
>
Hi David,
Thank you for raising this. This file (`dma-buf-mapping.c`) was
recently added [1] to exclusively export MMIO device memory.
Therefore, it is bypassed completely for `normal` transfers (IIUC,
e.g., video buffers for V4L2 or DRM).
Regards,
David
[1] https://lore.kernel.org/all/20251120-dmabuf-vfio-v9-6-d7f71607f371@nvidia.com/
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk
2026-06-23 1:54 ` [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks David Hu
2026-06-23 2:08 ` sashiko-bot
2026-06-23 8:44 ` David Laight
@ 2026-07-22 23:38 ` dhu
2026-07-23 0:02 ` sashiko-bot
2026-07-22 23:39 ` dhu
3 siblings, 1 reply; 23+ messages in thread
From: dhu @ 2026-07-22 23:38 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: Jason Gunthorpe, David Laight, Nicolin Chen, Leon Romanovsky,
Kevin Tian, Ankit Agrawal, Alex Williamson, Pranjal Shrivastava,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, iommu,
stable, jmoroni, kpberry, chriscli, viursachi, xuehaohu,
sashiko-bot
From: David Hu <xuehaohu@google.com>
Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
first entry, resulting in non-page-aligned DMA addresses for all
subsequent entries.
While the underlying IOMMU mapping may be contiguous, hardware
DMA engines often require explicit address alignment (e.g., page,
cacheline, or storage sector boundaries). Passing unaligned
addresses and lengths can cause explicit failures in DMA descriptor
creation or silent data corruption if lower unaligned bits are
truncated.
In addition, a non-page-aligned sgl length will trigger an edge case
in `ib_umem_find_best_pgsz()`. In case of a discontinuity in later
buffers, we will have a `va` with lowest bit set to 1. That will lead
to `ib_umem_find_best_pgsz()` always return 0, and break the promise
to find best page size for the mapping on the NIC side.
Fix this by splitting the scatterlist by the largest possible page
aligned chunk within `UINT_MAX` (`ALIGN_DOWN(UINT_MAX, PAGE_SIZE)`).
This ensures all scatterlist DMA addresses and lengths remain page
aligned, while minimizing the total number of sgl entries.
Page-aligned entries allow the system to cleanly chunk payloads into
PCIe MaxPayloadSize (MPS) (e.g., 128 bytes, 256 bytes, 512 bytes).
As a result, this may help reduce TLP fragmentation in P2P transfers
and alleviate potential congestion within a logical PCIe switch
partition, especially when Relaxed Ordering is not possible due to
hardware constraints.
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
Cc: stable@vger.kernel.org
Signed-off-by: David Hu <xuehaohu@google.com>
---
Changes in v3:
- Removed the type cast for `min` (David Laight)
- Reverted max ent size to be `ALIGN_DOWN(UINT_MAX, PAGE_SIZE)` and
updated commit message to reflect that (Jason Gunthorpe)
- Updated commit message to reflect that this also fixes an edge case
in `ib_umem_find_best_pgsz()`
Changes in v2:
- Updated commit title and message to reflect the switch to 2G chunks
- Switch to using 2G as the max sg entry size as it naturally aligns
with most hardware boundaries, while allowing compiler optimizations
with bit shifts (David Laight)
- Optimized away division calculation for `nent`, and multiplication
calculation for sgl address, by dropping the `for` loop in favor of a
`while (length)` loop (David Laight)
- Dropped `min_t` in favor of `min()` to maintain a strict type
checking safety net (David Laight)
drivers/dma-buf/dma-buf-mapping.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 794acff2546a..50ded9daf5fb 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -5,16 +5,17 @@
*/
#include <linux/dma-buf-mapping.h>
#include <linux/dma-resv.h>
+#include <linux/align.h>
+
+#define MAX_SG_ENT_SZ ALIGN_DOWN(UINT_MAX, PAGE_SIZE)
static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
dma_addr_t addr)
{
- unsigned int len, nents;
- int i;
+ size_t len;
- nents = DIV_ROUND_UP(length, UINT_MAX);
- for (i = 0; i < nents; i++) {
- len = min_t(size_t, length, UINT_MAX);
+ while (length) {
+ len = min(length, MAX_SG_ENT_SZ);
length -= len;
/*
* DMABUF abuses scatterlist to create a scatterlist
@@ -24,8 +25,10 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
* does not require the CPU list for mapping or unmapping.
*/
sg_set_page(sgl, NULL, 0, 0);
- sg_dma_address(sgl) = addr + (dma_addr_t)i * UINT_MAX;
+ sg_dma_address(sgl) = addr;
sg_dma_len(sgl) = len;
+ addr += len;
+ /* Unconditionally advance. On last segment, this becomes NULL */
sgl = sg_next(sgl);
}
@@ -41,14 +44,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
if (!state || !dma_use_iova(state)) {
for (i = 0; i < nr_ranges; i++)
- nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
+ nents += DIV_ROUND_UP(phys_vec[i].len, MAX_SG_ENT_SZ);
} else {
/*
* In IOVA case, there is only one SG entry which spans
* for whole IOVA address space, but we need to make sure
* that it fits sg->length, maybe we need more.
*/
- nents = DIV_ROUND_UP(size, UINT_MAX);
+ nents = DIV_ROUND_UP(size, MAX_SG_ENT_SZ);
}
return nents;
--
2.55.0.229.g6434b31f56-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk
2026-06-23 1:54 ` [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks David Hu
` (2 preceding siblings ...)
2026-07-22 23:38 ` [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk dhu
@ 2026-07-22 23:39 ` dhu
2026-07-22 23:59 ` sashiko-bot
2026-07-23 9:46 ` Leon Romanovsky
3 siblings, 2 replies; 23+ messages in thread
From: dhu @ 2026-07-22 23:39 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: Jason Gunthorpe, David Laight, Nicolin Chen, Leon Romanovsky,
Kevin Tian, Ankit Agrawal, Alex Williamson, Pranjal Shrivastava,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, iommu,
stable, jmoroni, kpberry, chriscli, viursachi, xuehaohu,
sashiko-bot
From: David Hu <xuehaohu@google.com>
Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
first entry, resulting in non-page-aligned DMA addresses for all
subsequent entries.
While the underlying IOMMU mapping may be contiguous, hardware
DMA engines often require explicit address alignment (e.g., page,
cacheline, or storage sector boundaries). Passing unaligned
addresses and lengths can cause explicit failures in DMA descriptor
creation or silent data corruption if lower unaligned bits are
truncated.
In addition, a non-page-aligned sgl length will trigger an edge case
in `ib_umem_find_best_pgsz()`. In case of a discontinuity in later
buffers, we will have a `va` with lowest bit set to 1. That will lead
to `ib_umem_find_best_pgsz()` always return 0, and break the promise
to find best page size for the mapping on the NIC side.
Fix this by splitting the scatterlist by the largest possible page
aligned chunk within `UINT_MAX` (`ALIGN_DOWN(UINT_MAX, PAGE_SIZE)`).
This ensures all scatterlist DMA addresses and lengths remain page
aligned, while minimizing the total number of sgl entries.
Page-aligned entries allow the system to cleanly chunk payloads into
PCIe MaxPayloadSize (MPS) (e.g., 128 bytes, 256 bytes, 512 bytes).
As a result, this may help reduce TLP fragmentation in P2P transfers
and alleviate potential congestion within a logical PCIe switch
partition, especially when Relaxed Ordering is not possible due to
hardware constraints.
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
Cc: stable@vger.kernel.org
Signed-off-by: David Hu <xuehaohu@google.com>
---
Changes in v3:
- Removed the type cast for `min` (David Laight)
- Reverted max ent size to be `ALIGN_DOWN(UINT_MAX, PAGE_SIZE)` and
updated commit message to reflect that (Jason Gunthorpe)
- Updated commit message to reflect that this also fixes an edge case
in `ib_umem_find_best_pgsz()`
Changes in v2:
- Updated commit title and message to reflect the switch to 2G chunks
- Switch to using 2G as the max sg entry size as it naturally aligns
with most hardware boundaries, while allowing compiler optimizations
with bit shifts (David Laight)
- Optimized away division calculation for `nent`, and multiplication
calculation for sgl address, by dropping the `for` loop in favor of a
`while (length)` loop (David Laight)
- Dropped `min_t` in favor of `min()` to maintain a strict type
checking safety net (David Laight)
drivers/dma-buf/dma-buf-mapping.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 794acff2546a..50ded9daf5fb 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -5,16 +5,17 @@
*/
#include <linux/dma-buf-mapping.h>
#include <linux/dma-resv.h>
+#include <linux/align.h>
+
+#define MAX_SG_ENT_SZ ALIGN_DOWN(UINT_MAX, PAGE_SIZE)
static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
dma_addr_t addr)
{
- unsigned int len, nents;
- int i;
+ size_t len;
- nents = DIV_ROUND_UP(length, UINT_MAX);
- for (i = 0; i < nents; i++) {
- len = min_t(size_t, length, UINT_MAX);
+ while (length) {
+ len = min(length, MAX_SG_ENT_SZ);
length -= len;
/*
* DMABUF abuses scatterlist to create a scatterlist
@@ -24,8 +25,10 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
* does not require the CPU list for mapping or unmapping.
*/
sg_set_page(sgl, NULL, 0, 0);
- sg_dma_address(sgl) = addr + (dma_addr_t)i * UINT_MAX;
+ sg_dma_address(sgl) = addr;
sg_dma_len(sgl) = len;
+ addr += len;
+ /* Unconditionally advance. On last segment, this becomes NULL */
sgl = sg_next(sgl);
}
@@ -41,14 +44,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
if (!state || !dma_use_iova(state)) {
for (i = 0; i < nr_ranges; i++)
- nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
+ nents += DIV_ROUND_UP(phys_vec[i].len, MAX_SG_ENT_SZ);
} else {
/*
* In IOVA case, there is only one SG entry which spans
* for whole IOVA address space, but we need to make sure
* that it fits sg->length, maybe we need more.
*/
- nents = DIV_ROUND_UP(size, UINT_MAX);
+ nents = DIV_ROUND_UP(size, MAX_SG_ENT_SZ);
}
return nents;
--
2.55.0.229.g6434b31f56-goog
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk
2026-07-22 23:39 ` dhu
@ 2026-07-22 23:59 ` sashiko-bot
2026-07-23 9:46 ` Leon Romanovsky
1 sibling, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-22 23:59 UTC (permalink / raw)
To: dhu; +Cc: dri-devel, media-ci
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Integer Overflow / NULL Pointer Dereference in sg mapping calculation
Pre-existing issues:
- [High] 32-bit Integer Overflow causing incomplete DMA mappings
- [High] DMA API Violation (Mismatched Map/Unmap Size)
- [High] IOVA Resource Leak on Error Paths
--
--- Patch [1]: [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk ---
commit 6c6b736bcfe57779f8dd4452cee1c6738c03f76d
Author: David Hu <xuehaohu@google.com>
dma-buf: Split sgl by largest page-aligned chunk
This commit updates scatterlist chunking in dma-buf to use
ALIGN_DOWN(UINT_MAX, PAGE_SIZE) instead of UINT_MAX. This ensures that
scatterlist DMA addresses and lengths remain strictly page-aligned, which
avoids truncation on hardware engines and fixes a fallback issue in
ib_umem_find_best_pgsz().
Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
> diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
> index 794acff2546a3..50ded9daf5fb3 100644
> --- a/drivers/dma-buf/dma-buf-mapping.c
> +++ b/drivers/dma-buf/dma-buf-mapping.c
[ ... ]
> @@ -24,8 +25,10 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> * does not require the CPU list for mapping or unmapping.
> */
> sg_set_page(sgl, NULL, 0, 0);
[Severity: High]
Does this new while loop correctly handle an undersized scatterlist?
If calc_sg_nents() returns 0 due to the 32-bit overflow mentioned below,
this while loop still processes the full length. It will exhaust the
SGL entries, receive a NULL from sg_next(), and dereference it during
the next call to sg_set_page().
> - sg_dma_address(sgl) = addr + (dma_addr_t)i * UINT_MAX;
> + sg_dma_address(sgl) = addr;
> sg_dma_len(sgl) = len;
> + addr += len;
> + /* Unconditionally advance. On last segment, this becomes NULL */
> sgl = sg_next(sgl);
> }
>
> @@ -41,14 +44,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
>
> if (!state || !dma_use_iova(state)) {
> for (i = 0; i < nr_ranges; i++)
> - nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
> + nents += DIV_ROUND_UP(phys_vec[i].len, MAX_SG_ENT_SZ);
^^^^
[Severity: High]
Can this DIV_ROUND_UP() overflow on 32-bit platforms?
MAX_SG_ENT_SZ is ALIGN_DOWN(0xFFFFFFFF, PAGE_SIZE), which is 0xFFFFF000.
The DIV_ROUND_UP(len, MAX_SG_ENT_SZ) expands to
(len + 0xFFFFF000 - 1) / 0xFFFFF000. If len is 4097 or greater, this
addition overflows a 32-bit integer and wraps around, yielding 0. This
allocates 0 scatterlist entries for that chunk.
> } else {
> /*
> * In IOVA case, there is only one SG entry which spans
> * for whole IOVA address space, but we need to make sure
> * that it fits sg->length, maybe we need more.
> */
> - nents = DIV_ROUND_UP(size, UINT_MAX);
> + nents = DIV_ROUND_UP(size, MAX_SG_ENT_SZ);
[Severity: High]
Similarly, can this calculation overflow in the IOVA case when processing
sizes >= 4097 bytes on a 32-bit platform?
> }
>
> return nents;
[ ... ]
While reviewing this code, I noticed a few pre-existing issues in the same
file that you might want to address:
[Severity: High]
This isn't a bug introduced by this patch, but does mapped_len silently wrap
around on 64-bit platforms?
drivers/dma-buf/dma-buf-mapping.c:dma_buf_phys_vec_to_sgt() {
unsigned int nents, mapped_len = 0;
[ ... ]
for (i = 0; i < nr_ranges; i++) {
[ ... ]
mapped_len += phys_vec[i].len;
}
}
Because mapped_len is a 32-bit unsigned int and phys_vec[i].len is a 64-bit
size_t, calculating a total mapping size larger than 4GB overflows mapped_len.
[Severity: High]
This isn't a bug introduced by this patch, but does the error path leak the
IOVA allocation?
drivers/dma-buf/dma-buf-mapping.c:dma_buf_phys_vec_to_sgt() {
[ ... ]
dma_iova_try_alloc(attach->dev, dma->state, 0, size);
[ ... ]
ret = sg_alloc_table(&dma->sgt, nents, GFP_KERNEL | __GFP_ZERO);
if (ret)
goto err_free_state;
[ ... ]
err_unmap_dma:
if (!i || !dma->state) {
; /* Do nothing */
} else if (dma_use_iova(dma->state)) {
dma_iova_destroy(attach->dev, dma->state, mapped_len, dir,
DMA_ATTR_MMIO);
[ ... ]
}
If sg_alloc_table() fails, the code branches to err_free_state, returning
without calling dma_iova_destroy(). Additionally, if mapping the first range
fails (i == 0), the err_unmap_dma path executes the empty if-block and skips
cleanup.
[Severity: High]
This isn't a bug introduced by this patch, but does this unmap sequence
violate the requirement to match map and unmap sizes?
drivers/dma-buf/dma-buf-mapping.c:dma_buf_phys_vec_to_sgt() {
[ ... ]
addr = dma_map_phys(attach->dev, phys_vec[i].paddr,
phys_vec[i].len, dir, DMA_ATTR_MMIO);
[ ... ]
}
drivers/dma-buf/dma-buf-mapping.c:dma_buf_free_sgt() {
[ ... ]
for_each_sgtable_dma_sg(sgt, sgl, i)
dma_unmap_phys(attach->dev, sg_dma_address(sgl),
sg_dma_len(sgl), dir, DMA_ATTR_MMIO);
[ ... ]
}
The physical memory regions are mapped as single, contiguous blocks using
phys_vec[i].len, but the teardown path unmaps them in smaller chunks
iterating over the split scatterlist.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260722233932.3997681-1-dhu@x6u.co?part=1
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk
2026-07-22 23:38 ` [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk dhu
@ 2026-07-23 0:02 ` sashiko-bot
0 siblings, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-23 0:02 UTC (permalink / raw)
To: dhu; +Cc: dri-devel, media-ci
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but in the error handling path `err_unmap_dma`, `for_each_sgtable_dma_sg` incorrectly iterates over all allocated entries and calls `dma_unmap_phys` on zero-initialized memory.
- [High] This problem wasn't introduced by this patch, but in the error handling path `err_unmap_dma`, if mapping fails on the very first iteration (`i == 0`), it skips cleaning up the IOVA state, permanently leaking the IOVA space.
--
--- Patch [1]: [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk ---
commit 4626127ac68c48120c89f9454d7c72b3a29300b8
Author: David Hu <xuehaohu@google.com>
dma-buf: Split sgl by largest page-aligned chunk
This commit modifies the scatterlist splitting logic to use the largest
page-aligned chunk instead of UINT_MAX. This ensures that scatterlist
DMA lengths and addresses remain page-aligned. The change prevents
hardware DMA engine failures and addresses an edge case in
ib_umem_find_best_pgsz().
Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
Cc: stable@vger.kernel.org
> diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
> index 794acff2546a3..50ded9daf5fb3 100644
> --- a/drivers/dma-buf/dma-buf-mapping.c
> +++ b/drivers/dma-buf/dma-buf-mapping.c
[ ... ]
While looking at this file, I noticed a couple of pre-existing issues in
dma_buf_phys_vec_to_sgt().
> err_unmap_dma:
> if (!i || !dma->state) {
> ; /* Do nothing */
[Severity: High]
This isn't a bug introduced by this patch, but if mapping fails on the very
first iteration (i == 0), will this skip cleaning up the IOVA state?
If PCI_P2PDMA_MAP_THRU_HOST_BRIDGE is used, dma_iova_try_alloc() allocates
IOVA space before the mapping loop. If the very first dma_iova_link() fails,
the error path jumps here. Since !i evaluates to true, the code skips
calling dma_iova_destroy().
Does this permanently leak the device's IOVA space?
> } else if (dma_use_iova(dma->state)) {
> dma_iova_destroy(attach->dev, dma->state, mapped_len, dir,
> DMA_ATTR_MMIO);
> } else {
> for_each_sgtable_dma_sg(&dma->sgt, sgl, i)
> dma_unmap_phys(attach->dev, sg_dma_address(sgl),
> sg_dma_len(sgl), dir, DMA_ATTR_MMIO);
[Severity: High]
This isn't a bug introduced by this patch, but does this loop over
uninitialized entries?
The for_each_sgtable_dma_sg macro shadows the outer loop variable i, which
represents the number of successfully mapped entries. Instead of bounding
the loop to the mapped entries, it resets i to 0 and unconditionally
iterates up to the total allocated entries (dma->sgt.nents).
Since sg_alloc_table zero-initializes the memory via __GFP_ZERO, the unmapped
elements will have DMA addresses and lengths of 0. Can calling dma_unmap_phys
with a 0 address and 0 length cause IOMMU translation corruption or explicit
DMA faults?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260722233806.3922093-1-dhu@x6u.co?part=1
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk
2026-07-22 23:39 ` dhu
2026-07-22 23:59 ` sashiko-bot
@ 2026-07-23 9:46 ` Leon Romanovsky
2026-07-23 16:07 ` David Hu
1 sibling, 1 reply; 23+ messages in thread
From: Leon Romanovsky @ 2026-07-23 9:46 UTC (permalink / raw)
To: dhu
Cc: Sumit Semwal, Christian König, Jason Gunthorpe, David Laight,
Nicolin Chen, Kevin Tian, Ankit Agrawal, Alex Williamson,
Pranjal Shrivastava, linux-media, dri-devel, linaro-mm-sig,
linux-kernel, iommu, stable, jmoroni, kpberry, chriscli,
viursachi, xuehaohu, sashiko-bot
On Wed, Jul 22, 2026 at 11:39:32PM +0000, dhu@x6u.co wrote:
> From: David Hu <xuehaohu@google.com>
>
> Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
> This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
> first entry, resulting in non-page-aligned DMA addresses for all
> subsequent entries.
>
> While the underlying IOMMU mapping may be contiguous, hardware
> DMA engines often require explicit address alignment (e.g., page,
> cacheline, or storage sector boundaries). Passing unaligned
> addresses and lengths can cause explicit failures in DMA descriptor
> creation or silent data corruption if lower unaligned bits are
> truncated.
>
> In addition, a non-page-aligned sgl length will trigger an edge case
> in `ib_umem_find_best_pgsz()`. In case of a discontinuity in later
> buffers, we will have a `va` with lowest bit set to 1. That will lead
> to `ib_umem_find_best_pgsz()` always return 0, and break the promise
> to find best page size for the mapping on the NIC side.
>
> Fix this by splitting the scatterlist by the largest possible page
> aligned chunk within `UINT_MAX` (`ALIGN_DOWN(UINT_MAX, PAGE_SIZE)`).
> This ensures all scatterlist DMA addresses and lengths remain page
> aligned, while minimizing the total number of sgl entries.
>
> Page-aligned entries allow the system to cleanly chunk payloads into
> PCIe MaxPayloadSize (MPS) (e.g., 128 bytes, 256 bytes, 512 bytes).
> As a result, this may help reduce TLP fragmentation in P2P transfers
> and alleviate potential congestion within a logical PCIe switch
> partition, especially when Relaxed Ordering is not possible due to
> hardware constraints.
>
> Reported-by: sashiko-bot <sashiko-bot@kernel.org>
> Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
> Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Hu <xuehaohu@google.com>
> ---
> Changes in v3:
> - Removed the type cast for `min` (David Laight)
> - Reverted max ent size to be `ALIGN_DOWN(UINT_MAX, PAGE_SIZE)` and
> updated commit message to reflect that (Jason Gunthorpe)
> - Updated commit message to reflect that this also fixes an edge case
> in `ib_umem_find_best_pgsz()`
>
> Changes in v2:
> - Updated commit title and message to reflect the switch to 2G chunks
> - Switch to using 2G as the max sg entry size as it naturally aligns
> with most hardware boundaries, while allowing compiler optimizations
> with bit shifts (David Laight)
> - Optimized away division calculation for `nent`, and multiplication
> calculation for sgl address, by dropping the `for` loop in favor of a
> `while (length)` loop (David Laight)
> - Dropped `min_t` in favor of `min()` to maintain a strict type
> checking safety net (David Laight)
>
> drivers/dma-buf/dma-buf-mapping.c | 19 +++++++++++--------
> 1 file changed, 11 insertions(+), 8 deletions(-)
Could you please avoid sending patches as replies? It severely disrupts
the reading flow when using mutt's threaded view.
Regarding the patch,
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Thanks
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk
2026-07-23 9:46 ` Leon Romanovsky
@ 2026-07-23 16:07 ` David Hu
0 siblings, 0 replies; 23+ messages in thread
From: David Hu @ 2026-07-23 16:07 UTC (permalink / raw)
To: Leon Romanovsky
Cc: dhu, Sumit Semwal, Christian König, Jason Gunthorpe,
David Laight, Nicolin Chen, Kevin Tian, Ankit Agrawal,
Alex Williamson, Pranjal Shrivastava, linux-media, dri-devel,
linaro-mm-sig, linux-kernel, iommu, stable, jmoroni, kpberry,
chriscli, viursachi, sashiko-bot
On Thu, Jul 23, 2026 at 5:46 AM Leon Romanovsky <leon@kernel.org> wrote:
>
> On Wed, Jul 22, 2026 at 11:39:32PM +0000, dhu@x6u.co wrote:
> > From: David Hu <xuehaohu@google.com>
> >
> > Currently, `fill_sg_entry()` splits the scatterlist using `UINT_MAX`.
> > This creates a non-page-aligned DMA length (`0xFFFFFFFF`) for the
[ ... ]
> >
> > drivers/dma-buf/dma-buf-mapping.c | 19 +++++++++++--------
> > 1 file changed, 11 insertions(+), 8 deletions(-)
>
> Could you please avoid sending patches as replies? It severely disrupts
> the reading flow when using mutt's threaded view.
>
> Regarding the patch,
> Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
>
Hi Leon,
Understood. In the future, I'll start a new thread for new patch revisions.
Thank you for your review.
Regards,
David
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2026-07-23 16:07 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-21 22:21 [PATCH] dma-buf: Split sgl by largest page-aligned chunk David Hu
2026-06-21 22:34 ` sashiko-bot
2026-06-22 8:13 ` David Laight
2026-06-22 21:26 ` David Hu
2026-06-23 8:25 ` David Laight
2026-06-23 21:03 ` David Hu
2026-06-23 1:54 ` [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks David Hu
2026-06-23 2:08 ` sashiko-bot
2026-06-23 8:44 ` David Laight
2026-06-23 20:55 ` Pranjal Shrivastava
2026-06-23 22:53 ` David Laight
2026-06-24 14:31 ` Leon Romanovsky
2026-06-30 12:42 ` Jason Gunthorpe
2026-07-02 4:56 ` David Hu
2026-07-02 8:10 ` David Laight
2026-07-03 4:11 ` David Hu
2026-06-30 12:38 ` Jason Gunthorpe
2026-07-22 23:38 ` [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk dhu
2026-07-23 0:02 ` sashiko-bot
2026-07-22 23:39 ` dhu
2026-07-22 23:59 ` sashiko-bot
2026-07-23 9:46 ` Leon Romanovsky
2026-07-23 16:07 ` David Hu
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.