@@ -743,6 +743,127 @@ static bool drm_gpusvm_check_pages(struct drm_gpusvm *gpusvm,
743743 return err ? false : true;
744744}
745745
746+ /**
747+ * drm_gpusvm_scan_mm() - Check the migration state of a drm_gpusvm_range
748+ * @range: Pointer to the struct drm_gpusvm_range to check.
749+ * @dev_private_owner: The struct dev_private_owner to use to determine
750+ * compatible device-private pages.
751+ * @pagemap: The struct dev_pagemap pointer to use for pagemap-specific
752+ * checks.
753+ *
754+ * Scan the CPU address space corresponding to @range and return the
755+ * current migration state. Note that the result may be invalid as
756+ * soon as the function returns. It's an advisory check.
757+ *
758+ * TODO: Bail early and call hmm_range_fault() for subranges.
759+ *
760+ * Return: See &enum drm_gpusvm_scan_result.
761+ */
762+ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm (struct drm_gpusvm_range * range ,
763+ void * dev_private_owner ,
764+ const struct dev_pagemap * pagemap )
765+ {
766+ struct mmu_interval_notifier * notifier = & range -> notifier -> notifier ;
767+ unsigned long start = drm_gpusvm_range_start (range );
768+ unsigned long end = drm_gpusvm_range_end (range );
769+ struct hmm_range hmm_range = {
770+ .default_flags = 0 ,
771+ .notifier = notifier ,
772+ .start = start ,
773+ .end = end ,
774+ .dev_private_owner = dev_private_owner ,
775+ };
776+ unsigned long timeout =
777+ jiffies + msecs_to_jiffies (HMM_RANGE_DEFAULT_TIMEOUT );
778+ enum drm_gpusvm_scan_result state = DRM_GPUSVM_SCAN_UNPOPULATED , new_state ;
779+ unsigned long * pfns ;
780+ unsigned long npages = npages_in_range (start , end );
781+ const struct dev_pagemap * other = NULL ;
782+ int err , i ;
783+
784+ pfns = kvmalloc_array (npages , sizeof (* pfns ), GFP_KERNEL );
785+ if (!pfns )
786+ return DRM_GPUSVM_SCAN_UNPOPULATED ;
787+
788+ hmm_range .hmm_pfns = pfns ;
789+
790+ retry :
791+ hmm_range .notifier_seq = mmu_interval_read_begin (notifier );
792+ mmap_read_lock (range -> gpusvm -> mm );
793+
794+ while (true) {
795+ err = hmm_range_fault (& hmm_range );
796+ if (err == - EBUSY ) {
797+ if (time_after (jiffies , timeout ))
798+ break ;
799+
800+ hmm_range .notifier_seq =
801+ mmu_interval_read_begin (notifier );
802+ continue ;
803+ }
804+ break ;
805+ }
806+ mmap_read_unlock (range -> gpusvm -> mm );
807+ if (err )
808+ goto err_free ;
809+
810+ drm_gpusvm_notifier_lock (range -> gpusvm );
811+ if (mmu_interval_read_retry (notifier , hmm_range .notifier_seq )) {
812+ drm_gpusvm_notifier_unlock (range -> gpusvm );
813+ goto retry ;
814+ }
815+
816+ for (i = 0 ; i < npages ;) {
817+ struct page * page ;
818+ const struct dev_pagemap * cur = NULL ;
819+
820+ if (!(pfns [i ] & HMM_PFN_VALID )) {
821+ state = DRM_GPUSVM_SCAN_UNPOPULATED ;
822+ goto err_free ;
823+ }
824+
825+ page = hmm_pfn_to_page (pfns [i ]);
826+ if (is_device_private_page (page ) ||
827+ is_device_coherent_page (page ))
828+ cur = page_pgmap (page );
829+
830+ if (cur == pagemap ) {
831+ new_state = DRM_GPUSVM_SCAN_EQUAL ;
832+ } else if (cur && (cur == other || !other )) {
833+ new_state = DRM_GPUSVM_SCAN_OTHER ;
834+ other = cur ;
835+ } else if (cur ) {
836+ new_state = DRM_GPUSVM_SCAN_MIXED_DEVICE ;
837+ } else {
838+ new_state = DRM_GPUSVM_SCAN_SYSTEM ;
839+ }
840+
841+ /*
842+ * TODO: Could use an array for state
843+ * transitions, and caller might want it
844+ * to bail early for some results.
845+ */
846+ if (state == DRM_GPUSVM_SCAN_UNPOPULATED ) {
847+ state = new_state ;
848+ } else if (state != new_state ) {
849+ if (new_state == DRM_GPUSVM_SCAN_SYSTEM ||
850+ state == DRM_GPUSVM_SCAN_SYSTEM )
851+ state = DRM_GPUSVM_SCAN_MIXED ;
852+ else if (state != DRM_GPUSVM_SCAN_MIXED )
853+ state = DRM_GPUSVM_SCAN_MIXED_DEVICE ;
854+ }
855+
856+ i += 1ul << drm_gpusvm_hmm_pfn_to_order (pfns [i ], i , npages );
857+ }
858+
859+ err_free :
860+ drm_gpusvm_notifier_unlock (range -> gpusvm );
861+
862+ kvfree (pfns );
863+ return state ;
864+ }
865+ EXPORT_SYMBOL (drm_gpusvm_scan_mm );
866+
746867/**
747868 * drm_gpusvm_range_chunk_size() - Determine chunk size for GPU SVM range
748869 * @gpusvm: Pointer to the GPU SVM structure
@@ -1038,6 +1159,7 @@ static void __drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
10381159 flags .has_dma_mapping = false;
10391160 WRITE_ONCE (svm_pages -> flags .__flags , flags .__flags );
10401161
1162+ drm_pagemap_put (svm_pages -> dpagemap );
10411163 svm_pages -> dpagemap = NULL ;
10421164 }
10431165}
@@ -1434,6 +1556,8 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
14341556
14351557 if (pagemap ) {
14361558 flags .has_devmem_pages = true;
1559+ drm_pagemap_get (dpagemap );
1560+ drm_pagemap_put (svm_pages -> dpagemap );
14371561 svm_pages -> dpagemap = dpagemap ;
14381562 }
14391563
0 commit comments