[PATCH v1 3/5] drm/pagemap: DMA map folios when possible

Francois Dugast francois.dugast at intel.com
Thu Jul 17 13:38:25 UTC 2025


If the page is part of a folio, DMA map the whole folio at once instead of
mapping individual pages one after the other. For example if 2MB folios
are used instead of 4KB pages, this reduces the number of DMA mappings by
512.

The folio order (and consequently, the size) is persisted in the struct
drm_pagemap_device_addr to be available at the time of unmapping.

Signed-off-by: Francois Dugast <francois.dugast at intel.com>
Cc: Matthew Brost <matthew.brost at intel.com>
---
 drivers/gpu/drm/drm_pagemap.c | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c
index 0ed66aaade14..de15d96f6393 100644
--- a/drivers/gpu/drm/drm_pagemap.c
+++ b/drivers/gpu/drm/drm_pagemap.c
@@ -220,20 +220,31 @@ static int drm_pagemap_migrate_map_pages(struct device *dev,
 					 unsigned long npages,
 					 enum dma_data_direction dir)
 {
-	unsigned long i;
+	unsigned long i, j;
 
-	for (i = 0; i < npages; ++i) {
+	for (i = 0; i < npages;) {
 		struct page *page = migrate_pfn_to_page(migrate_pfn[i]);
+		struct folio *folio;
+		unsigned int order;
 
 		if (!page)
-			continue;
+			goto next;
 
 		if (WARN_ON_ONCE(is_zone_device_page(page)))
 			return -EFAULT;
 
-		device_addr[i].addr = dma_map_page(dev, page, 0, PAGE_SIZE, dir);
+		folio = page_folio(page);
+		order = folio_order(folio);
+		device_addr[i].addr = dma_map_page(dev, page, 0, page_size(page), dir);
+		device_addr[i].order = order;
+
 		if (dma_mapping_error(dev, device_addr[i].addr))
 			return -EFAULT;
+
+		for (j = 0; j < (0x1 << order) && i+j < npages; j++)
+			device_addr[i+j].addr = device_addr[i].addr + j * PAGE_SIZE;
+next:
+		i += 0x1 << order;
 	}
 
 	return 0;
@@ -257,11 +268,14 @@ static void drm_pagemap_migrate_unmap_pages(struct device *dev,
 {
 	unsigned long i;
 
-	for (i = 0; i < npages; ++i) {
+	for (i = 0; i < npages;) {
 		if (!device_addr[i].addr || dma_mapping_error(dev, device_addr[i].addr))
-			continue;
+			goto next;
+
+		dma_unmap_page(dev, device_addr[i].addr, PAGE_SIZE << device_addr[i].order, dir);
 
-		dma_unmap_page(dev, device_addr[i].addr, PAGE_SIZE, dir);
+next:
+		i += 0x1 << device_addr[i].order;
 	}
 }
 
-- 
2.43.0



More information about the Intel-xe mailing list