Skip to content

Commit a14fa8e

Browse files
committed
mm/migrate: Add migrate_device_pfns
Add migrate_device_pfns which prepares an array of pre-populated device pages for migration. This is needed for eviction of known set of non-contiguous devices pages to cpu pages which is a common case for SVM in DRM drivers using TTM. v2: - s/migrate_device_vma_range/migrate_device_prepopulated_range - Drop extra mmu invalidation (Vetter) v3: - s/migrate_device_prepopulated_range/migrate_device_pfns (Alistar) - Use helper to lock device pages (Alistar) - Update commit message with why this is required (Alistar) Cc: Andrew Morton <[email protected]> Signed-off-by: Matthew Brost <[email protected]> Reviewed-by: Alistair Popple <[email protected]> Reviewed-by: Gwan-gyeong Mun <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 1d724a2 commit a14fa8e

File tree

2 files changed

+38
-15
lines changed

2 files changed

+38
-15
lines changed

include/linux/migrate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ void migrate_vma_pages(struct migrate_vma *migrate);
227227
void migrate_vma_finalize(struct migrate_vma *migrate);
228228
int migrate_device_range(unsigned long *src_pfns, unsigned long start,
229229
unsigned long npages);
230+
int migrate_device_pfns(unsigned long *src_pfns, unsigned long npages);
230231
void migrate_device_pages(unsigned long *src_pfns, unsigned long *dst_pfns,
231232
unsigned long npages);
232233
void migrate_device_finalize(unsigned long *src_pfns,

mm/migrate_device.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,22 @@ void migrate_vma_finalize(struct migrate_vma *migrate)
871871
}
872872
EXPORT_SYMBOL(migrate_vma_finalize);
873873

874+
static unsigned long migrate_device_pfn_lock(unsigned long pfn)
875+
{
876+
struct folio *folio;
877+
878+
folio = folio_get_nontail_page(pfn_to_page(pfn));
879+
if (!folio)
880+
return 0;
881+
882+
if (!folio_trylock(folio)) {
883+
folio_put(folio);
884+
return 0;
885+
}
886+
887+
return migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
888+
}
889+
874890
/**
875891
* migrate_device_range() - migrate device private pfns to normal memory.
876892
* @src_pfns: array large enough to hold migrating source device private pfns.
@@ -895,29 +911,35 @@ int migrate_device_range(unsigned long *src_pfns, unsigned long start,
895911
{
896912
unsigned long i, pfn;
897913

898-
for (pfn = start, i = 0; i < npages; pfn++, i++) {
899-
struct folio *folio;
914+
for (pfn = start, i = 0; i < npages; pfn++, i++)
915+
src_pfns[i] = migrate_device_pfn_lock(pfn);
900916

901-
folio = folio_get_nontail_page(pfn_to_page(pfn));
902-
if (!folio) {
903-
src_pfns[i] = 0;
904-
continue;
905-
}
917+
migrate_device_unmap(src_pfns, npages, NULL);
906918

907-
if (!folio_trylock(folio)) {
908-
src_pfns[i] = 0;
909-
folio_put(folio);
910-
continue;
911-
}
919+
return 0;
920+
}
921+
EXPORT_SYMBOL(migrate_device_range);
912922

913-
src_pfns[i] = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
914-
}
923+
/**
924+
* migrate_device_pfns() - migrate device private pfns to normal memory.
925+
* @src_pfns: pre-popluated array of source device private pfns to migrate.
926+
* @npages: number of pages to migrate.
927+
*
928+
* Similar to migrate_device_range() but supports non-contiguous pre-popluated
929+
* array of device pages to migrate.
930+
*/
931+
int migrate_device_pfns(unsigned long *src_pfns, unsigned long npages)
932+
{
933+
unsigned long i;
934+
935+
for (i = 0; i < npages; i++)
936+
src_pfns[i] = migrate_device_pfn_lock(src_pfns[i]);
915937

916938
migrate_device_unmap(src_pfns, npages, NULL);
917939

918940
return 0;
919941
}
920-
EXPORT_SYMBOL(migrate_device_range);
942+
EXPORT_SYMBOL(migrate_device_pfns);
921943

922944
/*
923945
* Migrate a device coherent folio back to normal memory. The caller should have

0 commit comments

Comments
 (0)