Hi,

On Fri, Aug 28, 2026 at 04:36:52PM +0800, Junhua Shen wrote:
> 
> The base-page count for a migrate.src[] entry was open-coded in several
> places along the migration path, and these variants handled
> MIGRATE_PFN_COMPOUND entries inconsistently.

Nit: not just inconsistently, I would mention the existing undercount issue
this patch fixes when VALID=0 && COMPOUND=1.

> 
> Factor it out into drm_pagemap_src_pfn_nr_pages() and use it in
> drm_pagemap_cpages() and both accounting loops of
> drm_pagemap_migrate_to_devmem(), so every site agrees on the base-page
> count and iteration stride.
> 
> Signed-off-by: Junhua Shen <[email protected]>

Consequently, we need a "Fixes" tag here.

With that, the change itself LGTM:

    Reviewed-by: Francois Dugast <[email protected]>

Francois

> ---
>  drivers/gpu/drm/drm_pagemap.c | 60 +++++++++++++++++++++++++----------
>  1 file changed, 43 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c
> index 892b325fa99b..a31cc4f0af68 100644
> --- a/drivers/gpu/drm/drm_pagemap.c
> +++ b/drivers/gpu/drm/drm_pagemap.c
> @@ -554,6 +554,37 @@ static int drm_pagemap_migrate_range(struct 
> drm_pagemap_devmem *devmem,
>       return ret;
>  }
>  
> +/**
> + * drm_pagemap_src_pfn_nr_pages() - Decode src entry and return base-page 
> count
> + * @src_pfn: Source migrate entry
> + * @src_page: Optional decoded source page when MIGRATE_PFN_VALID is set
> + *
> + * Decode @src_pfn to compute how many base pages it represents: use folio
> + * page count for valid entries, HPAGE_PMD_NR for COMPOUND-only entries,
> + * otherwise 1.
> + *
> + * Return: Number of base pages represented by @src_pfn.
> + */
> +static unsigned long drm_pagemap_src_pfn_nr_pages(unsigned long src_pfn,
> +                                                struct page **src_page)
> +{
> +     struct page *page = NULL;
> +     unsigned long nr_pages = 1;
> +
> +     if (src_pfn & MIGRATE_PFN_VALID) {
> +             page = migrate_pfn_to_page(src_pfn);
> +             if (page)
> +                     nr_pages = NR_PAGES(folio_order(page_folio(page)));
> +     } else if (src_pfn & MIGRATE_PFN_COMPOUND) {
> +             nr_pages = HPAGE_PMD_NR;
> +     }
> +
> +     if (src_page)
> +             *src_page = page;
> +
> +     return nr_pages;
> +}
> +
>  /**
>   * drm_pagemap_cpages() - Count collected pages
>   * @migrate_pfn: Array of migrate_pfn entries to account
> @@ -570,20 +601,14 @@ static int drm_pagemap_cpages(unsigned long 
> *migrate_pfn, unsigned long npages)
>       unsigned long i, cpages = 0;
>  
>       for (i = 0; i < npages;) {
> -             struct page *page = migrate_pfn_to_page(migrate_pfn[i]);
> -             struct folio *folio;
> -             unsigned int order = 0;
> +             unsigned long src_pfn = migrate_pfn[i];
> +             struct page *page;
> +             unsigned long nr_pages = drm_pagemap_src_pfn_nr_pages(src_pfn, 
> &page);
>  
> -             if (page) {
> -                     folio = page_folio(page);
> -                     order = folio_order(folio);
> -                     cpages += NR_PAGES(order);
> -             } else if (migrate_pfn[i] & MIGRATE_PFN_COMPOUND) {
> -                     order = HPAGE_PMD_ORDER;
> -                     cpages += NR_PAGES(order);
> -             }
> +             if (page || (src_pfn & MIGRATE_PFN_COMPOUND))
> +                     cpages += nr_pages;
>  
> -             i += NR_PAGES(order);
> +             i += nr_pages;
>       }
>  
>       return cpages;
> @@ -703,8 +728,9 @@ int drm_pagemap_migrate_to_devmem(struct 
> drm_pagemap_devmem *devmem_allocation,
>  
>       /* Count device-private pages to migrate */
>       for (i = 0; i < npages;) {
> -             struct page *src_page = migrate_pfn_to_page(migrate.src[i]);
> -             unsigned long nr_pages = src_page ? 
> NR_PAGES(folio_order(page_folio(src_page))) : 1;
> +             unsigned long src_pfn = migrate.src[i];
> +             struct page *src_page;
> +             unsigned long nr_pages = drm_pagemap_src_pfn_nr_pages(src_pfn, 
> &src_page);
>  
>               if (src_page && is_zone_device_page(src_page)) {
>                       if (page_pgmap(src_page) == pagemap)
> @@ -818,10 +844,10 @@ int drm_pagemap_migrate_to_devmem(struct 
> drm_pagemap_devmem *devmem_allocation,
>       migrate_vma_pages(&migrate);
>  
>       for (i = 0; !err && i < npages;) {
> -             struct page *page = migrate_pfn_to_page(migrate.src[i]);
> -             unsigned long nr_pages = page ? 
> NR_PAGES(folio_order(page_folio(page))) : 1;
> +             unsigned long src_pfn = migrate.src[i];
> +             unsigned long nr_pages = drm_pagemap_src_pfn_nr_pages(src_pfn, 
> NULL);
>  
> -             if (migrate.src[i] & MIGRATE_PFN_MIGRATE)
> +             if (src_pfn & MIGRATE_PFN_MIGRATE)
>                       migrated_pages += nr_pages;
>  
>               i += nr_pages;
> -- 
> 2.34.1
> 

Reply via email to