Re: [PATCH v3] dma-buf: system_heap: Set allocation orders for larger page sizes

From: Juan Yescas

Date: Fri Sep 25 2026 - 11:38:20 EST


On Tue, Sep 22, 2026 at 5:11 AM Pankaj Patil
<pankaj.patil@xxxxxxxxxxxxxxxx> wrote:
>
> On 4/18/2025 1:49 AM, Juan Yescas wrote:
> > This change sets the allocation orders for the different page sizes
> > (4k, 16k, 64k) based on PAGE_SHIFT. Before this change, the orders
> > for large page sizes were calculated incorrectly, this caused system
> > heap to allocate from 2% to 4% more memory on 16KiB page size kernels.
> >
> > This change was tested on 4k/16k page size kernels.
> >
> > Signed-off-by: Juan Yescas <jyescas@xxxxxxxxxx>
> > Acked-by: John Stultz <jstultz@xxxxxxxxxx>
> > Reviewed-by: T.J. Mercier <tjmercier@xxxxxxxxxx>
> > ---
> >
> > Changes in v2:
> > - Add John's Acked-by tag.
> > - Add TJ's Reviewed-by tag
> > - Use dma-buf: system_heap: in the subject since this is specific to the
> > system heap, as per TJ.
> > - Remove extra space in if statement.
> >
> > Changes in v3:
> > - Remove defines for the orders as per Christian.
> > - Update the order array for 64k page sizes as per TJ
> >
> > drivers/dma-buf/heaps/system_heap.c | 21 ++++++++++++++++++---
> > 1 file changed, 18 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
> > index 26d5dc89ea16..8c10c0f2b473 100644
> > --- a/drivers/dma-buf/heaps/system_heap.c
> > +++ b/drivers/dma-buf/heaps/system_heap.c
> > @@ -18,6 +18,7 @@
> > #include <linux/mm.h>
> > #include <linux/module.h>
> > #include <linux/scatterlist.h>
> > +#include <linux/sizes.h>
> > #include <linux/slab.h>
> > #include <linux/vmalloc.h>
> >
> > @@ -44,14 +45,28 @@ struct dma_heap_attachment {
> > #define HIGH_ORDER_GFP (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \
> > | __GFP_NORETRY) & ~__GFP_RECLAIM) \
> > | __GFP_COMP)
> > -static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP};
> > /*
> > * The selection of the orders used for allocation (1MB, 64K, 4K) is designed
> > * to match with the sizes often found in IOMMUs. Using order 4 pages instead
> > * of order 0 pages can significantly improve the performance of many IOMMUs
> > * by reducing TLB pressure and time spent updating page tables.
> > + *
> > + * Note: When the order is 0, the minimum allocation is PAGE_SIZE. The possible
> > + * page sizes for ARM devices could be 4K, 16K and 64K.
> > + */
> > +#if (PAGE_SIZE == SZ_64K)
> > +static gfp_t order_flags[] = {HIGH_ORDER_GFP, LOW_ORDER_GFP};
> > +/* 1MiB allocs are calculated with (2 ^ (20 - PAGE_SHIFT)) * PAGE_SIZE = 1MiB */
> > +static const unsigned int orders[] = {20 - PAGE_SHIFT, 0};
> > +#else
> > +static gfp_t order_flags[] = {HIGH_ORDER_GFP, HIGH_ORDER_GFP, LOW_ORDER_GFP};
> > +/*
> > + * 1MiB allocs are calculated with (2 ^ (20 - PAGE_SHIFT)) * PAGE_SIZE = 1MiB
> > + * 64KiB allocs are calculated with (2 ^ (16 - PAGE_SHIFT)) * PAGE_SIZE = 64KiB
> > */
> > -static const unsigned int orders[] = {8, 4, 0};
> > +static const unsigned int orders[] = {20 - PAGE_SHIFT, 16 - PAGE_SHIFT, 0};
> > +#endif
> > +
> > #define NUM_ORDERS ARRAY_SIZE(orders)
> >
> > static struct sg_table *dup_sg_table(struct sg_table *table)
> > @@ -318,7 +333,7 @@ static struct page *alloc_largest_available(unsigned long size,
> > int i;
> >
> > for (i = 0; i < NUM_ORDERS; i++) {
> > - if (size < (PAGE_SIZE << orders[i]))
> > + if (size < (PAGE_SIZE << orders[i]))
> > continue;
> > if (max_order < orders[i])
> > continue;
>
> Hello Juan,
> I've posted a respin of the patch by extending upon your work,
> Can you please review?
> Aplogies for adding signed-off by, will drop it in v2.
>
> Link -
> https://lore.kernel.org/all/20260921-dma_buf_improvement-v1-1-23d82e771dec@xxxxxxxxxxxxxxxx/
>

Hi Pankaj,

There is another change that fixes the problem and adds the 2MiB
order. It has already been
reviewed the Christian König:

https://lore.kernel.org/all/20260914212258.2657788-3-dave@xxxxxxxxxxxx/

>