@@ -206,11 +206,11 @@ static void drm_pagemap_get_devmem_page(struct page *page,
206206
207207/**
208208 * drm_pagemap_migrate_map_pages() - Map migration pages for GPU SVM migration
209- * @dev: The device for which the pages are being mapped
210- * @local_dpagemap: The drm_pagemap pointer of the local drm_pagemap .
211- * @pagemap_addr: Array to store DMA information corresponding to mapped pages
212- * @migrate_pfn: Array of migrate page frame numbers to map
213- * @npages: Number of pages to map
209+ * @dev: The device performing the migration.
210+ * @local_dpagemap: The drm_pagemap local to the migrating device .
211+ * @pagemap_addr: Array to store DMA information corresponding to mapped pages.
212+ * @migrate_pfn: Array of page frame numbers of system pages or peer pages to map.
213+ * @npages: Number of system pages or peer pages to map.
214214 * @dir: Direction of data transfer (e.g., DMA_BIDIRECTIONAL)
215215 * @mdetails: Details governing the migration behaviour.
216216 *
@@ -229,8 +229,7 @@ static int drm_pagemap_migrate_map_pages(struct device *dev,
229229 enum dma_data_direction dir ,
230230 const struct drm_pagemap_migrate_details * mdetails )
231231{
232- unsigned long i ;
233- unsigned long num_peer_pages = 0 ;
232+ unsigned long num_peer_pages = 0 , num_local_pages = 0 , i ;
234233
235234 for (i = 0 ; i < npages ;) {
236235 struct page * page = migrate_pfn_to_page (migrate_pfn [i ]);
@@ -249,10 +248,15 @@ static int drm_pagemap_migrate_map_pages(struct device *dev,
249248 struct drm_pagemap * dpagemap = zdd -> dpagemap ;
250249 struct drm_pagemap_addr addr ;
251250
252- if (dpagemap == local_dpagemap && !mdetails -> can_migrate_same_pagemap )
253- goto next ;
251+ if (dpagemap == local_dpagemap ) {
252+ if (!mdetails -> can_migrate_same_pagemap )
253+ goto next ;
254+
255+ num_local_pages += NR_PAGES (order );
256+ } else {
257+ num_peer_pages += NR_PAGES (order );
258+ }
254259
255- num_peer_pages += NR_PAGES (order );
256260 addr = dpagemap -> ops -> device_map (dpagemap , dev , page , order , dir );
257261 if (dma_mapping_error (dev , addr .addr ))
258262 return - EFAULT ;
@@ -276,6 +280,9 @@ static int drm_pagemap_migrate_map_pages(struct device *dev,
276280 if (num_peer_pages )
277281 drm_dbg (local_dpagemap -> drm , "Migrating %lu peer pages over interconnect.\n" ,
278282 num_peer_pages );
283+ if (num_local_pages )
284+ drm_dbg (local_dpagemap -> drm , "Migrating %lu local pages over interconnect.\n" ,
285+ num_local_pages );
279286
280287 return 0 ;
281288}
@@ -328,6 +335,115 @@ npages_in_range(unsigned long start, unsigned long end)
328335 return (end - start ) >> PAGE_SHIFT ;
329336}
330337
338+ static int
339+ drm_pagemap_migrate_remote_to_local (struct drm_pagemap_devmem * devmem ,
340+ struct device * remote_device ,
341+ struct drm_pagemap * remote_dpagemap ,
342+ unsigned long local_pfns [],
343+ struct page * remote_pages [],
344+ struct drm_pagemap_addr pagemap_addr [],
345+ unsigned long npages ,
346+ const struct drm_pagemap_devmem_ops * ops ,
347+ const struct drm_pagemap_migrate_details * mdetails )
348+
349+ {
350+ int err = drm_pagemap_migrate_map_pages (remote_device , remote_dpagemap ,
351+ pagemap_addr , local_pfns ,
352+ npages , DMA_FROM_DEVICE , mdetails );
353+
354+ if (err )
355+ goto out ;
356+
357+ err = ops -> copy_to_ram (remote_pages , pagemap_addr , npages ,
358+ devmem -> pre_migrate_fence );
359+ out :
360+ drm_pagemap_migrate_unmap_pages (remote_device , pagemap_addr , local_pfns ,
361+ npages , DMA_FROM_DEVICE );
362+ return err ;
363+ }
364+
365+ static int
366+ drm_pagemap_migrate_sys_to_dev (struct drm_pagemap_devmem * devmem ,
367+ unsigned long sys_pfns [],
368+ struct page * local_pages [],
369+ struct drm_pagemap_addr pagemap_addr [],
370+ unsigned long npages ,
371+ const struct drm_pagemap_devmem_ops * ops ,
372+ const struct drm_pagemap_migrate_details * mdetails )
373+ {
374+ int err = drm_pagemap_migrate_map_pages (devmem -> dev , devmem -> dpagemap ,
375+ pagemap_addr , sys_pfns , npages ,
376+ DMA_TO_DEVICE , mdetails );
377+
378+ if (err )
379+ goto out ;
380+
381+ err = ops -> copy_to_devmem (local_pages , pagemap_addr , npages ,
382+ devmem -> pre_migrate_fence );
383+ out :
384+ drm_pagemap_migrate_unmap_pages (devmem -> dev , pagemap_addr , sys_pfns , npages ,
385+ DMA_TO_DEVICE );
386+ return err ;
387+ }
388+
389+ /**
390+ * struct migrate_range_loc - Cursor into the loop over migrate_pfns for migrating to
391+ * device.
392+ * @start: The current loop index.
393+ * @device: migrating device.
394+ * @dpagemap: Pointer to struct drm_pagemap used by the migrating device.
395+ * @ops: The copy ops to be used for the migrating device.
396+ */
397+ struct migrate_range_loc {
398+ unsigned long start ;
399+ struct device * device ;
400+ struct drm_pagemap * dpagemap ;
401+ const struct drm_pagemap_devmem_ops * ops ;
402+ };
403+
404+ static int drm_pagemap_migrate_range (struct drm_pagemap_devmem * devmem ,
405+ unsigned long src_pfns [],
406+ unsigned long dst_pfns [],
407+ struct page * pages [],
408+ struct drm_pagemap_addr pagemap_addr [],
409+ struct migrate_range_loc * last ,
410+ const struct migrate_range_loc * cur ,
411+ const struct drm_pagemap_migrate_details * mdetails )
412+ {
413+ int ret = 0 ;
414+
415+ if (cur -> start == 0 )
416+ goto out ;
417+
418+ if (cur -> start <= last -> start )
419+ return 0 ;
420+
421+ if (cur -> dpagemap == last -> dpagemap && cur -> ops == last -> ops )
422+ return 0 ;
423+
424+ if (last -> dpagemap )
425+ ret = drm_pagemap_migrate_remote_to_local (devmem ,
426+ last -> device ,
427+ last -> dpagemap ,
428+ & dst_pfns [last -> start ],
429+ & pages [last -> start ],
430+ & pagemap_addr [last -> start ],
431+ cur -> start - last -> start ,
432+ last -> ops , mdetails );
433+
434+ else
435+ ret = drm_pagemap_migrate_sys_to_dev (devmem ,
436+ & src_pfns [last -> start ],
437+ & pages [last -> start ],
438+ & pagemap_addr [last -> start ],
439+ cur -> start - last -> start ,
440+ last -> ops , mdetails );
441+
442+ out :
443+ * last = * cur ;
444+ return ret ;
445+ }
446+
331447/**
332448 * drm_pagemap_migrate_to_devmem() - Migrate a struct mm_struct range to device memory
333449 * @devmem_allocation: The device memory allocation to migrate to.
@@ -365,10 +481,11 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
365481 .end = end ,
366482 .pgmap_owner = pagemap -> owner ,
367483 .flags = MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT |
368- ( mdetails -> source_peer_migrates ? 0 : MIGRATE_VMA_SELECT_DEVICE_PRIVATE ) ,
484+ MIGRATE_VMA_SELECT_DEVICE_PRIVATE ,
369485 };
370486 unsigned long i , npages = npages_in_range (start , end );
371487 unsigned long own_pages = 0 , migrated_pages = 0 ;
488+ struct migrate_range_loc cur , last = {.device = dpagemap -> drm -> dev , .ops = ops };
372489 struct vm_area_struct * vas ;
373490 struct drm_pagemap_zdd * zdd = NULL ;
374491 struct page * * pages ;
@@ -467,44 +584,55 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
467584 if (err )
468585 goto err_finalize ;
469586
470- err = drm_pagemap_migrate_map_pages (devmem_allocation -> dev ,
471- devmem_allocation -> dpagemap , pagemap_addr ,
472- migrate .src , npages , DMA_TO_DEVICE ,
473- mdetails );
474-
475- if (err ) {
476- drm_pagemap_migrate_unmap_pages (devmem_allocation -> dev , pagemap_addr ,
477- migrate .src , npages , DMA_TO_DEVICE );
478-
479- goto err_finalize ;
480- }
481-
482587 own_pages = 0 ;
588+
483589 for (i = 0 ; i < npages ; ++ i ) {
484590 struct page * page = pfn_to_page (migrate .dst [i ]);
485591 struct page * src_page = migrate_pfn_to_page (migrate .src [i ]);
486-
487- if (unlikely (src_page && is_zone_device_page (src_page ) &&
488- page_pgmap (src_page ) == pagemap &&
489- !mdetails -> can_migrate_same_pagemap )) {
490- migrate .dst [i ] = 0 ;
491- pages [i ] = NULL ;
492- own_pages ++ ;
493- continue ;
592+ cur .start = i ;
593+
594+ pages [i ] = NULL ;
595+ if (src_page && is_device_private_page (src_page )) {
596+ struct drm_pagemap_zdd * src_zdd = src_page -> zone_device_data ;
597+
598+ if (page_pgmap (src_page ) == pagemap &&
599+ !mdetails -> can_migrate_same_pagemap ) {
600+ migrate .dst [i ] = 0 ;
601+ own_pages ++ ;
602+ continue ;
603+ }
604+ if (mdetails -> source_peer_migrates ) {
605+ cur .dpagemap = src_zdd -> dpagemap ;
606+ cur .ops = src_zdd -> devmem_allocation -> ops ;
607+ cur .device = cur .dpagemap -> drm -> dev ;
608+ pages [i ] = src_page ;
609+ }
610+ }
611+ if (!pages [i ]) {
612+ cur .dpagemap = NULL ;
613+ cur .ops = ops ;
614+ cur .device = dpagemap -> drm -> dev ;
615+ pages [i ] = page ;
494616 }
495- pages [i ] = page ;
496617 migrate .dst [i ] = migrate_pfn (migrate .dst [i ]);
497618 drm_pagemap_get_devmem_page (page , zdd );
498- }
499- drm_WARN_ON (dpagemap -> drm , !!own_pages );
500619
501- err = ops -> copy_to_devmem (pages , pagemap_addr , npages ,
502- devmem_allocation -> pre_migrate_fence );
503- drm_pagemap_migrate_unmap_pages (devmem_allocation -> dev , pagemap_addr ,
504- migrate .src , npages , DMA_TO_DEVICE );
620+ /* If we switched the migrating drm_pagemap, migrate previous pages now */
621+ err = drm_pagemap_migrate_range (devmem_allocation , migrate .src , migrate .dst ,
622+ pages , pagemap_addr , & last , & cur ,
623+ mdetails );
624+ if (err )
625+ goto err_finalize ;
626+ }
627+ cur .start = npages ;
628+ cur .ops = NULL ; /* Force migration */
629+ err = drm_pagemap_migrate_range (devmem_allocation , migrate .src , migrate .dst ,
630+ pages , pagemap_addr , & last , & cur , mdetails );
505631 if (err )
506632 goto err_finalize ;
507633
634+ drm_WARN_ON (dpagemap -> drm , !!own_pages );
635+
508636 dma_fence_put (devmem_allocation -> pre_migrate_fence );
509637 devmem_allocation -> pre_migrate_fence = NULL ;
510638
0 commit comments