[PATCH v2 4/6] drm/pagemap: Allocate folios when possible
Matthew Brost
matthew.brost at intel.com
Tue Jul 29 06:15:52 UTC 2025
On Mon, Jul 28, 2025 at 12:18:26PM +0200, Francois Dugast wrote:
> 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);
Opps, next should only increment the loop variable.
Matt
> > > + 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