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.

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]>
---
 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