Skip to content

Commit 59260fe

Browse files
committed
Merge tag 'drm-xe-next-2025-12-30' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next
Core Changes: - Dynamic pagemaps and multi-device SVM (Thomas) Driver Changes: - Introduce SRIOV scheduler Groups (Daniele) - Configure migration queue as low latency (Francois) - Don't use absolute path in generated header comment (Calvin Owens) - Add SoC remapper support for system controller (Umesh) - Insert compiler barriers in GuC code (Jonathan) - Rebar updates (Lucas) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Hellstrom <thomas.hellstrom@linux.intel.com> Link: https://patch.msgid.link/aVOiULyYdnFbq-JB@fedora
2 parents 9ec3c8e + 0b075f8 commit 59260fe

62 files changed

Lines changed: 3879 additions & 483 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

drivers/gpu/drm/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ obj-$(CONFIG_DRM_GPUVM) += drm_gpuvm.o
109109

110110
drm_gpusvm_helper-y := \
111111
drm_gpusvm.o\
112-
drm_pagemap.o
112+
drm_pagemap.o\
113+
drm_pagemap_util.o
113114
obj-$(CONFIG_DRM_GPUSVM) += drm_gpusvm_helper.o
114115

115116
obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o

drivers/gpu/drm/drm_gpusvm.c

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)