[PATCH v2 4/6] drm/pagemap: Allocate folios when possible
Francois Dugast
francois.dugast at intel.com
Mon Jul 28 10:18:26 UTC 2025
On Fri, Jul 25, 2025 at 02:43:48PM -0700, Matthew Brost wrote:
> On Fri, Jul 25, 2025 at 05:39:28PM +0200, Francois Dugast wrote:
> > If the order is greater than zero, allocate a folio when populating the
> > RAM PFNs instead of allocating individual pages one after the other. For
> > example if 2MB folios are used instead of 4KB pages, this reduces the
> > number of calls to the allocation API by 512.
> >
> > v2:
> > - Use page order instead of extr argument (Matthew Brost)
> > - Allocate with folio_alloc() (Matthew Brost)
> > - Loop for mpages and free_pages based on order (Matthew Brost)
> >
> > Signed-off-by: Francois Dugast <francois.dugast at intel.com>
> > Cc: Matthew Brost <matthew.brost at intel.com>
> > ---
> > drivers/gpu/drm/drm_pagemap.c | 38 ++++++++++++++++++++++++++---------
> > 1 file changed, 28 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c
> > index b6f5d3a8e445..38753ce2bca7 100644
> > --- a/drivers/gpu/drm/drm_pagemap.c
> > +++ b/drivers/gpu/drm/drm_pagemap.c
> > @@ -458,54 +458,72 @@ static int drm_pagemap_migrate_populate_ram_pfn(struct vm_area_struct *vas,
> > {
> > unsigned long i;
> >
> > - for (i = 0; i < npages; ++i, addr += PAGE_SIZE) {
> > + for (i = 0; i < npages;) {
> > struct page *page, *src_page;
> > + unsigned int order;
> > + struct folio *folio;
> >
> > if (!(src_mpfn[i] & MIGRATE_PFN_MIGRATE))
> > - continue;
> > + goto next;
> >
> > src_page = migrate_pfn_to_page(src_mpfn[i]);
> > if (!src_page)
> > - continue;
> > + goto next;
> >
> > if (fault_page) {
> > if (src_page->zone_device_data !=
> > fault_page->zone_device_data)
> > - continue;
> > + goto next;
> > }
> >
> > + order = folio_order(page_folio(src_page));
> > +
> > + /* TODO: Support fallback to single pages if THP allocation fails */
> > if (vas)
> > - page = alloc_page_vma(GFP_HIGHUSER, vas, addr);
> > + folio = vma_alloc_folio(GFP_HIGHUSER, order, vas, addr);
> > else
> > - page = alloc_page(GFP_HIGHUSER);
> > + folio = folio_alloc(GFP_HIGHUSER, order);
>
> I haven't checked but I assume if order == 0, then alloc_page_vma ==
> vma_alloc_folio? So goes for alloc_page / folio_alloc. If so, then this
> looks good.
Yes according to include/linux/gfp.h:
- alloc_page_vma()->alloc_page_vma_noprof()->vma_alloc_folio_noprof(order=0)
- vma_alloc_folio()->vma_alloc_folio_noprof(order)
>
> >
> > - if (!page)
> > + if (!folio)
> > goto free_pages;
> >
> > + page = folio_page(folio, 0);
> > mpfn[i] = migrate_pfn(page_to_pfn(page));
> > +
> > +next:
> > + addr += page_size(page);
> > + i += NR_PAGES(order);
> > }
> >
> > - for (i = 0; i < npages; ++i) {
> > + for (i = 0; i < npages;) {
> > struct page *page = migrate_pfn_to_page(mpfn[i]);
> > + unsigned int order;
>
> unsigned int order = 0;
>
> >
> > if (!page)
> > continue;
>
> s/continue/goto next;
>
>
> >
> > WARN_ON_ONCE(!trylock_page(page));
> > - ++*mpages;
> > +
> > + order = folio_order(page_folio(page));
>
> next:
>
> > + *mpages += NR_PAGES(order);
> > + i += NR_PAGES(order);
> > }
> >
> > return 0;
> >
> > free_pages:
> > - for (i = 0; i < npages; ++i) {
> > + for (i = 0; i < npages;) {
>
> Same logic changes to this loop as the one above.
Will fix.
Francois
>
> Matt
>
> > struct page *page = migrate_pfn_to_page(mpfn[i]);
> > + unsigned int order;
> >
> > if (!page)
> > continue;
> >
> > put_page(page);
> > mpfn[i] = 0;
> > +
> > + order = folio_order(page_folio(page));
> > + i += NR_PAGES(order);
> > }
> > return -ENOMEM;
> > }
> > --
> > 2.43.0
> >
More information about the Intel-xe
mailing list