mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-07 11:33:58 -04:00
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 <akpm@linux-foundation.org> Signed-off-by: Matthew Brost <matthew.brost@intel.com> Reviewed-by: Alistair Popple <apopple@nvidia.com> Reviewed-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20250306012657.3505757-3-matthew.brost@intel.com
This commit is contained in:
@@ -227,6 +227,7 @@ void migrate_vma_pages(struct migrate_vma *migrate);
|
||||
void migrate_vma_finalize(struct migrate_vma *migrate);
|
||||
int migrate_device_range(unsigned long *src_pfns, unsigned long start,
|
||||
unsigned long npages);
|
||||
int migrate_device_pfns(unsigned long *src_pfns, unsigned long npages);
|
||||
void migrate_device_pages(unsigned long *src_pfns, unsigned long *dst_pfns,
|
||||
unsigned long npages);
|
||||
void migrate_device_finalize(unsigned long *src_pfns,
|
||||
|
||||
@@ -871,6 +871,22 @@ void migrate_vma_finalize(struct migrate_vma *migrate)
|
||||
}
|
||||
EXPORT_SYMBOL(migrate_vma_finalize);
|
||||
|
||||
static unsigned long migrate_device_pfn_lock(unsigned long pfn)
|
||||
{
|
||||
struct folio *folio;
|
||||
|
||||
folio = folio_get_nontail_page(pfn_to_page(pfn));
|
||||
if (!folio)
|
||||
return 0;
|
||||
|
||||
if (!folio_trylock(folio)) {
|
||||
folio_put(folio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* migrate_device_range() - migrate device private pfns to normal memory.
|
||||
* @src_pfns: array large enough to hold migrating source device private pfns.
|
||||
@@ -895,23 +911,8 @@ int migrate_device_range(unsigned long *src_pfns, unsigned long start,
|
||||
{
|
||||
unsigned long i, pfn;
|
||||
|
||||
for (pfn = start, i = 0; i < npages; pfn++, i++) {
|
||||
struct folio *folio;
|
||||
|
||||
folio = folio_get_nontail_page(pfn_to_page(pfn));
|
||||
if (!folio) {
|
||||
src_pfns[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!folio_trylock(folio)) {
|
||||
src_pfns[i] = 0;
|
||||
folio_put(folio);
|
||||
continue;
|
||||
}
|
||||
|
||||
src_pfns[i] = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
|
||||
}
|
||||
for (pfn = start, i = 0; i < npages; pfn++, i++)
|
||||
src_pfns[i] = migrate_device_pfn_lock(pfn);
|
||||
|
||||
migrate_device_unmap(src_pfns, npages, NULL);
|
||||
|
||||
@@ -919,6 +920,27 @@ int migrate_device_range(unsigned long *src_pfns, unsigned long start,
|
||||
}
|
||||
EXPORT_SYMBOL(migrate_device_range);
|
||||
|
||||
/**
|
||||
* migrate_device_pfns() - migrate device private pfns to normal memory.
|
||||
* @src_pfns: pre-popluated array of source device private pfns to migrate.
|
||||
* @npages: number of pages to migrate.
|
||||
*
|
||||
* Similar to migrate_device_range() but supports non-contiguous pre-popluated
|
||||
* array of device pages to migrate.
|
||||
*/
|
||||
int migrate_device_pfns(unsigned long *src_pfns, unsigned long npages)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < npages; i++)
|
||||
src_pfns[i] = migrate_device_pfn_lock(src_pfns[i]);
|
||||
|
||||
migrate_device_unmap(src_pfns, npages, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(migrate_device_pfns);
|
||||
|
||||
/*
|
||||
* Migrate a device coherent folio back to normal memory. The caller should have
|
||||
* a reference on folio which will be copied to the new folio if migration is
|
||||
|
||||
Reference in New Issue
Block a user