Skip to content

Commit 1054f19

Browse files
committed
Merge tag 'drm-xe-fixes-2025-12-30' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-fixes
Core Changes: - Ensure a SVM device memory allocation is idle before migration complete (Thomas) Driver Changes: - Fix a SVM debug printout (Thomas) - Use READ_ONCE() / WRITE_ONCE() for g2h_fence (Jonathan) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Hellstrom <thomas.hellstrom@linux.intel.com> Link: https://patch.msgid.link/aVOTf6-whmkgrUuq@fedora
2 parents f8f9c1f + bed2a6b commit 1054f19

6 files changed

Lines changed: 99 additions & 31 deletions

File tree

drivers/gpu/drm/drm_pagemap.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © 2024-2025 Intel Corporation
44
*/
55

6+
#include <linux/dma-fence.h>
67
#include <linux/dma-mapping.h>
78
#include <linux/migrate.h>
89
#include <linux/pagemap.h>
@@ -408,10 +409,14 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
408409
drm_pagemap_get_devmem_page(page, zdd);
409410
}
410411

411-
err = ops->copy_to_devmem(pages, pagemap_addr, npages);
412+
err = ops->copy_to_devmem(pages, pagemap_addr, npages,
413+
devmem_allocation->pre_migrate_fence);
412414
if (err)
413415
goto err_finalize;
414416

417+
dma_fence_put(devmem_allocation->pre_migrate_fence);
418+
devmem_allocation->pre_migrate_fence = NULL;
419+
415420
/* Upon success bind devmem allocation to range and zdd */
416421
devmem_allocation->timeslice_expiration = get_jiffies_64() +
417422
msecs_to_jiffies(timeslice_ms);
@@ -596,7 +601,7 @@ int drm_pagemap_evict_to_ram(struct drm_pagemap_devmem *devmem_allocation)
596601
for (i = 0; i < npages; ++i)
597602
pages[i] = migrate_pfn_to_page(src[i]);
598603

599-
err = ops->copy_to_ram(pages, pagemap_addr, npages);
604+
err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
600605
if (err)
601606
goto err_finalize;
602607

@@ -732,7 +737,7 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
732737
for (i = 0; i < npages; ++i)
733738
pages[i] = migrate_pfn_to_page(migrate.src[i]);
734739

735-
err = ops->copy_to_ram(pages, pagemap_addr, npages);
740+
err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
736741
if (err)
737742
goto err_finalize;
738743

@@ -813,18 +818,22 @@ EXPORT_SYMBOL_GPL(drm_pagemap_pagemap_ops_get);
813818
* @ops: Pointer to the operations structure for GPU SVM device memory
814819
* @dpagemap: The struct drm_pagemap we're allocating from.
815820
* @size: Size of device memory allocation
821+
* @pre_migrate_fence: Fence to wait for or pipeline behind before migration starts.
822+
* (May be NULL).
816823
*/
817824
void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
818825
struct device *dev, struct mm_struct *mm,
819826
const struct drm_pagemap_devmem_ops *ops,
820-
struct drm_pagemap *dpagemap, size_t size)
827+
struct drm_pagemap *dpagemap, size_t size,
828+
struct dma_fence *pre_migrate_fence)
821829
{
822830
init_completion(&devmem_allocation->detached);
823831
devmem_allocation->dev = dev;
824832
devmem_allocation->mm = mm;
825833
devmem_allocation->ops = ops;
826834
devmem_allocation->dpagemap = dpagemap;
827835
devmem_allocation->size = size;
836+
devmem_allocation->pre_migrate_fence = pre_migrate_fence;
828837
}
829838
EXPORT_SYMBOL_GPL(drm_pagemap_devmem_init);
830839

drivers/gpu/drm/xe/xe_guc_ct.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ static void g2h_fence_cancel(struct g2h_fence *g2h_fence)
104104
{
105105
g2h_fence->cancel = true;
106106
g2h_fence->fail = true;
107-
g2h_fence->done = true;
107+
108+
/* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */
109+
WRITE_ONCE(g2h_fence->done, true);
108110
}
109111

110112
static bool g2h_fence_needs_alloc(struct g2h_fence *g2h_fence)
@@ -1203,10 +1205,13 @@ static int guc_ct_send_recv(struct xe_guc_ct *ct, const u32 *action, u32 len,
12031205
return ret;
12041206
}
12051207

1206-
ret = wait_event_timeout(ct->g2h_fence_wq, g2h_fence.done, HZ);
1208+
/* READ_ONCEs pairs with WRITE_ONCEs in parse_g2h_response
1209+
* and g2h_fence_cancel.
1210+
*/
1211+
ret = wait_event_timeout(ct->g2h_fence_wq, READ_ONCE(g2h_fence.done), HZ);
12071212
if (!ret) {
12081213
LNL_FLUSH_WORK(&ct->g2h_worker);
1209-
if (g2h_fence.done) {
1214+
if (READ_ONCE(g2h_fence.done)) {
12101215
xe_gt_warn(gt, "G2H fence %u, action %04x, done\n",
12111216
g2h_fence.seqno, action[0]);
12121217
ret = 1;
@@ -1454,7 +1459,8 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len)
14541459

14551460
g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
14561461

1457-
g2h_fence->done = true;
1462+
/* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */
1463+
WRITE_ONCE(g2h_fence->done, true);
14581464
smp_mb();
14591465

14601466
wake_up_all(&ct->g2h_fence_wq);

drivers/gpu/drm/xe/xe_migrate.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,7 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
20622062
unsigned long sram_offset,
20632063
struct drm_pagemap_addr *sram_addr,
20642064
u64 vram_addr,
2065+
struct dma_fence *deps,
20652066
const enum xe_migrate_copy_dir dir)
20662067
{
20672068
struct xe_gt *gt = m->tile->primary_gt;
@@ -2150,6 +2151,14 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
21502151

21512152
xe_sched_job_add_migrate_flush(job, MI_INVALIDATE_TLB);
21522153

2154+
if (deps && !dma_fence_is_signaled(deps)) {
2155+
dma_fence_get(deps);
2156+
err = drm_sched_job_add_dependency(&job->drm, deps);
2157+
if (err)
2158+
dma_fence_wait(deps, false);
2159+
err = 0;
2160+
}
2161+
21532162
mutex_lock(&m->job_mutex);
21542163
xe_sched_job_arm(job);
21552164
fence = dma_fence_get(&job->drm.s_fence->finished);
@@ -2175,6 +2184,8 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
21752184
* @npages: Number of pages to migrate.
21762185
* @src_addr: Array of DMA information (source of migrate)
21772186
* @dst_addr: Device physical address of VRAM (destination of migrate)
2187+
* @deps: struct dma_fence representing the dependencies that need
2188+
* to be signaled before migration.
21782189
*
21792190
* Copy from an array dma addresses to a VRAM device physical address
21802191
*
@@ -2184,10 +2195,11 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
21842195
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
21852196
unsigned long npages,
21862197
struct drm_pagemap_addr *src_addr,
2187-
u64 dst_addr)
2198+
u64 dst_addr,
2199+
struct dma_fence *deps)
21882200
{
21892201
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, src_addr, dst_addr,
2190-
XE_MIGRATE_COPY_TO_VRAM);
2202+
deps, XE_MIGRATE_COPY_TO_VRAM);
21912203
}
21922204

21932205
/**
@@ -2196,6 +2208,8 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
21962208
* @npages: Number of pages to migrate.
21972209
* @src_addr: Device physical address of VRAM (source of migrate)
21982210
* @dst_addr: Array of DMA information (destination of migrate)
2211+
* @deps: struct dma_fence representing the dependencies that need
2212+
* to be signaled before migration.
21992213
*
22002214
* Copy from a VRAM device physical address to an array dma addresses
22012215
*
@@ -2205,10 +2219,11 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
22052219
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
22062220
unsigned long npages,
22072221
u64 src_addr,
2208-
struct drm_pagemap_addr *dst_addr)
2222+
struct drm_pagemap_addr *dst_addr,
2223+
struct dma_fence *deps)
22092224
{
22102225
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, dst_addr, src_addr,
2211-
XE_MIGRATE_COPY_TO_SRAM);
2226+
deps, XE_MIGRATE_COPY_TO_SRAM);
22122227
}
22132228

22142229
static void xe_migrate_dma_unmap(struct xe_device *xe,
@@ -2384,7 +2399,7 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
23842399
__fence = xe_migrate_vram(m, current_bytes,
23852400
(unsigned long)buf & ~PAGE_MASK,
23862401
&pagemap_addr[current_page],
2387-
vram_addr, write ?
2402+
vram_addr, NULL, write ?
23882403
XE_MIGRATE_COPY_TO_VRAM :
23892404
XE_MIGRATE_COPY_TO_SRAM);
23902405
if (IS_ERR(__fence)) {

drivers/gpu/drm/xe/xe_migrate.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,14 @@ int xe_migrate_init(struct xe_migrate *m);
116116
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
117117
unsigned long npages,
118118
struct drm_pagemap_addr *src_addr,
119-
u64 dst_addr);
119+
u64 dst_addr,
120+
struct dma_fence *deps);
120121

121122
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
122123
unsigned long npages,
123124
u64 src_addr,
124-
struct drm_pagemap_addr *dst_addr);
125+
struct drm_pagemap_addr *dst_addr,
126+
struct dma_fence *deps);
125127

126128
struct dma_fence *xe_migrate_copy(struct xe_migrate *m,
127129
struct xe_bo *src_bo,

drivers/gpu/drm/xe/xe_svm.c

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,8 @@ static void xe_svm_copy_us_stats_incr(struct xe_gt *gt,
476476

477477
static int xe_svm_copy(struct page **pages,
478478
struct drm_pagemap_addr *pagemap_addr,
479-
unsigned long npages, const enum xe_svm_copy_dir dir)
479+
unsigned long npages, const enum xe_svm_copy_dir dir,
480+
struct dma_fence *pre_migrate_fence)
480481
{
481482
struct xe_vram_region *vr = NULL;
482483
struct xe_gt *gt = NULL;
@@ -565,7 +566,8 @@ static int xe_svm_copy(struct page **pages,
565566
__fence = xe_migrate_from_vram(vr->migrate,
566567
i - pos + incr,
567568
vram_addr,
568-
&pagemap_addr[pos]);
569+
&pagemap_addr[pos],
570+
pre_migrate_fence);
569571
} else {
570572
vm_dbg(&xe->drm,
571573
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%ld",
@@ -574,13 +576,14 @@ static int xe_svm_copy(struct page **pages,
574576
__fence = xe_migrate_to_vram(vr->migrate,
575577
i - pos + incr,
576578
&pagemap_addr[pos],
577-
vram_addr);
579+
vram_addr,
580+
pre_migrate_fence);
578581
}
579582
if (IS_ERR(__fence)) {
580583
err = PTR_ERR(__fence);
581584
goto err_out;
582585
}
583-
586+
pre_migrate_fence = NULL;
584587
dma_fence_put(fence);
585588
fence = __fence;
586589
}
@@ -603,20 +606,22 @@ static int xe_svm_copy(struct page **pages,
603606
vram_addr, (u64)pagemap_addr[pos].addr, 1);
604607
__fence = xe_migrate_from_vram(vr->migrate, 1,
605608
vram_addr,
606-
&pagemap_addr[pos]);
609+
&pagemap_addr[pos],
610+
pre_migrate_fence);
607611
} else {
608612
vm_dbg(&xe->drm,
609613
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%d",
610614
(u64)pagemap_addr[pos].addr, vram_addr, 1);
611615
__fence = xe_migrate_to_vram(vr->migrate, 1,
612616
&pagemap_addr[pos],
613-
vram_addr);
617+
vram_addr,
618+
pre_migrate_fence);
614619
}
615620
if (IS_ERR(__fence)) {
616621
err = PTR_ERR(__fence);
617622
goto err_out;
618623
}
619-
624+
pre_migrate_fence = NULL;
620625
dma_fence_put(fence);
621626
fence = __fence;
622627
}
@@ -629,6 +634,8 @@ static int xe_svm_copy(struct page **pages,
629634
dma_fence_wait(fence, false);
630635
dma_fence_put(fence);
631636
}
637+
if (pre_migrate_fence)
638+
dma_fence_wait(pre_migrate_fence, false);
632639

633640
/*
634641
* XXX: We can't derive the GT here (or anywhere in this functions, but
@@ -645,16 +652,20 @@ static int xe_svm_copy(struct page **pages,
645652

646653
static int xe_svm_copy_to_devmem(struct page **pages,
647654
struct drm_pagemap_addr *pagemap_addr,
648-
unsigned long npages)
655+
unsigned long npages,
656+
struct dma_fence *pre_migrate_fence)
649657
{
650-
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM);
658+
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM,
659+
pre_migrate_fence);
651660
}
652661

653662
static int xe_svm_copy_to_ram(struct page **pages,
654663
struct drm_pagemap_addr *pagemap_addr,
655-
unsigned long npages)
664+
unsigned long npages,
665+
struct dma_fence *pre_migrate_fence)
656666
{
657-
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM);
667+
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM,
668+
pre_migrate_fence);
658669
}
659670

660671
static struct xe_bo *to_xe_bo(struct drm_pagemap_devmem *devmem_allocation)
@@ -667,6 +678,7 @@ static void xe_svm_devmem_release(struct drm_pagemap_devmem *devmem_allocation)
667678
struct xe_bo *bo = to_xe_bo(devmem_allocation);
668679
struct xe_device *xe = xe_bo_device(bo);
669680

681+
dma_fence_put(devmem_allocation->pre_migrate_fence);
670682
xe_bo_put_async(bo);
671683
xe_pm_runtime_put(xe);
672684
}
@@ -861,6 +873,7 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
861873
unsigned long timeslice_ms)
862874
{
863875
struct xe_vram_region *vr = container_of(dpagemap, typeof(*vr), dpagemap);
876+
struct dma_fence *pre_migrate_fence = NULL;
864877
struct xe_device *xe = vr->xe;
865878
struct device *dev = xe->drm.dev;
866879
struct drm_buddy_block *block;
@@ -887,8 +900,20 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
887900
break;
888901
}
889902

903+
/* Ensure that any clearing or async eviction will complete before migration. */
904+
if (!dma_resv_test_signaled(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL)) {
905+
err = dma_resv_get_singleton(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
906+
&pre_migrate_fence);
907+
if (err)
908+
dma_resv_wait_timeout(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
909+
false, MAX_SCHEDULE_TIMEOUT);
910+
else if (pre_migrate_fence)
911+
dma_fence_enable_sw_signaling(pre_migrate_fence);
912+
}
913+
890914
drm_pagemap_devmem_init(&bo->devmem_allocation, dev, mm,
891-
&dpagemap_devmem_ops, dpagemap, end - start);
915+
&dpagemap_devmem_ops, dpagemap, end - start,
916+
pre_migrate_fence);
892917

893918
blocks = &to_xe_ttm_vram_mgr_resource(bo->ttm.resource)->blocks;
894919
list_for_each_entry(block, blocks, link)
@@ -941,7 +966,7 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm
941966
xe_assert(vm->xe, IS_DGFX(vm->xe));
942967

943968
if (xe_svm_range_in_vram(range)) {
944-
drm_info(&vm->xe->drm, "Range is already in VRAM\n");
969+
drm_dbg(&vm->xe->drm, "Range is already in VRAM\n");
945970
return false;
946971
}
947972

0 commit comments

Comments
 (0)