Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe: Convert xe_bo_create_pin_map() for exhaustive eviction

Introduce an xe_bo_create_pin_map_novm() function that does not
take the drm_exec paramenter to simplify the conversion of many
callsites.
For the rest, ensure that the same drm_exec context that was used
for locking the vm is passed down to validation.

Use xe_validation_guard() where appropriate.

v2:
- Avoid gotos from within xe_validation_guard(). (Matt Brost)
- Break out the change to pf_provision_vf_lmem8 to a separate
patch.
- Adapt to signature change of xe_validation_guard().

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Link: https://lore.kernel.org/r/20250908101246.65025-12-thomas.hellstrom@linux.intel.com

+232 -131
+9 -9
drivers/gpu/drm/xe/display/intel_fbdev_fb.c
··· 42 42 obj = ERR_PTR(-ENODEV); 43 43 44 44 if (!IS_DGFX(xe) && !XE_GT_WA(xe_root_mmio_gt(xe), 22019338487_display)) { 45 - obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), 46 - NULL, size, 47 - ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT | 48 - XE_BO_FLAG_STOLEN | 49 - XE_BO_FLAG_GGTT); 45 + obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), 46 + size, 47 + ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT | 48 + XE_BO_FLAG_STOLEN | 49 + XE_BO_FLAG_GGTT, false); 50 50 if (!IS_ERR(obj)) 51 51 drm_info(&xe->drm, "Allocated fbdev into stolen\n"); 52 52 else ··· 54 54 } 55 55 56 56 if (IS_ERR(obj)) { 57 - obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), NULL, size, 58 - ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT | 59 - XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | 60 - XE_BO_FLAG_GGTT); 57 + obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), size, 58 + ttm_bo_type_kernel, XE_BO_FLAG_SCANOUT | 59 + XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | 60 + XE_BO_FLAG_GGTT, false); 61 61 } 62 62 63 63 if (IS_ERR(obj)) {
+5 -5
drivers/gpu/drm/xe/display/xe_dsb_buffer.c
··· 43 43 return false; 44 44 45 45 /* Set scanout flag for WC mapping */ 46 - obj = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), 47 - NULL, PAGE_ALIGN(size), 48 - ttm_bo_type_kernel, 49 - XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | 50 - XE_BO_FLAG_SCANOUT | XE_BO_FLAG_GGTT); 46 + obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), 47 + PAGE_ALIGN(size), 48 + ttm_bo_type_kernel, 49 + XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | 50 + XE_BO_FLAG_SCANOUT | XE_BO_FLAG_GGTT, false); 51 51 if (IS_ERR(obj)) { 52 52 kfree(vma); 53 53 return false;
+4 -4
drivers/gpu/drm/xe/display/xe_hdcp_gsc.c
··· 72 72 int ret = 0; 73 73 74 74 /* allocate object of two page for HDCP command memory and store it */ 75 - bo = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), NULL, PAGE_SIZE * 2, 76 - ttm_bo_type_kernel, 77 - XE_BO_FLAG_SYSTEM | 78 - XE_BO_FLAG_GGTT); 75 + bo = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), PAGE_SIZE * 2, 76 + ttm_bo_type_kernel, 77 + XE_BO_FLAG_SYSTEM | 78 + XE_BO_FLAG_GGTT, false); 79 79 80 80 if (IS_ERR(bo)) { 81 81 drm_err(&xe->drm, "Failed to allocate bo for HDCP streaming command!\n");
+6 -3
drivers/gpu/drm/xe/tests/xe_migrate.c
··· 204 204 205 205 big = xe_bo_create_pin_map(xe, tile, m->q->vm, SZ_4M, 206 206 ttm_bo_type_kernel, 207 - XE_BO_FLAG_VRAM_IF_DGFX(tile)); 207 + XE_BO_FLAG_VRAM_IF_DGFX(tile), 208 + exec); 208 209 if (IS_ERR(big)) { 209 210 KUNIT_FAIL(test, "Failed to allocate bo: %li\n", PTR_ERR(big)); 210 211 goto vunmap; ··· 213 212 214 213 pt = xe_bo_create_pin_map(xe, tile, m->q->vm, XE_PAGE_SIZE, 215 214 ttm_bo_type_kernel, 216 - XE_BO_FLAG_VRAM_IF_DGFX(tile)); 215 + XE_BO_FLAG_VRAM_IF_DGFX(tile), 216 + exec); 217 217 if (IS_ERR(pt)) { 218 218 KUNIT_FAIL(test, "Failed to allocate fake pt: %li\n", 219 219 PTR_ERR(pt)); ··· 224 222 tiny = xe_bo_create_pin_map(xe, tile, m->q->vm, 225 223 2 * SZ_4K, 226 224 ttm_bo_type_kernel, 227 - XE_BO_FLAG_VRAM_IF_DGFX(tile)); 225 + XE_BO_FLAG_VRAM_IF_DGFX(tile), 226 + exec); 228 227 if (IS_ERR(tiny)) { 229 228 KUNIT_FAIL(test, "Failed to allocate tiny fake pt: %li\n", 230 229 PTR_ERR(tiny));
+47 -5
drivers/gpu/drm/xe/xe_bo.c
··· 2513 2513 return ret ? ERR_PTR(ret) : bo; 2514 2514 } 2515 2515 2516 + /** 2517 + * xe_bo_create_pin_map() - Create pinned and mapped bo 2518 + * @xe: The xe device. 2519 + * @tile: The tile to select for migration of this bo, and the tile used for 2520 + * @vm: The vm to associate the buffer object with. The vm's resv must be locked 2521 + * with the transaction represented by @exec. 2522 + * GGTT binding if any. Only to be non-NULL for ttm_bo_type_kernel bos. 2523 + * @size: The storage size to use for the bo. 2524 + * @type: The TTM buffer object type. 2525 + * @flags: XE_BO_FLAG_ flags. 2526 + * @exec: The drm_exec transaction to use for exhaustive eviction, and 2527 + * previously used for locking @vm's resv. 2528 + * 2529 + * Create a pinned and mapped bo. The bo will be external and not associated 2530 + * with a VM. 2531 + * 2532 + * Return: The buffer object on success. Negative error pointer on failure. 2533 + * In particular, the function may return ERR_PTR(%-EINTR) if @exec was 2534 + * configured for interruptible locking. 2535 + */ 2516 2536 struct xe_bo *xe_bo_create_pin_map(struct xe_device *xe, struct xe_tile *tile, 2517 2537 struct xe_vm *vm, size_t size, 2518 - enum ttm_bo_type type, u32 flags) 2538 + enum ttm_bo_type type, u32 flags, 2539 + struct drm_exec *exec) 2519 2540 { 2520 - struct drm_exec *exec = vm ? xe_vm_validation_exec(vm) : XE_VALIDATION_UNIMPLEMENTED; 2521 - 2522 2541 return xe_bo_create_pin_map_at_aligned(xe, tile, vm, size, ~0ull, type, flags, 2523 2542 0, exec); 2543 + } 2544 + 2545 + /** 2546 + * xe_bo_create_pin_map_novm() - Create pinned and mapped bo 2547 + * @xe: The xe device. 2548 + * @tile: The tile to select for migration of this bo, and the tile used for 2549 + * GGTT binding if any. Only to be non-NULL for ttm_bo_type_kernel bos. 2550 + * @size: The storage size to use for the bo. 2551 + * @type: The TTM buffer object type. 2552 + * @flags: XE_BO_FLAG_ flags. 2553 + * @intr: Whether to execut any waits for backing store interruptible. 2554 + * 2555 + * Create a pinned and mapped bo. The bo will be external and not associated 2556 + * with a VM. 2557 + * 2558 + * Return: The buffer object on success. Negative error pointer on failure. 2559 + * In particular, the function may return ERR_PTR(%-EINTR) if @intr was set 2560 + * to true on entry. 2561 + */ 2562 + struct xe_bo *xe_bo_create_pin_map_novm(struct xe_device *xe, struct xe_tile *tile, 2563 + size_t size, enum ttm_bo_type type, u32 flags, 2564 + bool intr) 2565 + { 2566 + return xe_bo_create_pin_map_at_novm(xe, tile, size, ~0ull, type, flags, 0, intr); 2524 2567 } 2525 2568 2526 2569 static void __xe_bo_unpin_map_no_vm(void *arg) ··· 2578 2535 int ret; 2579 2536 2580 2537 KUNIT_STATIC_STUB_REDIRECT(xe_managed_bo_create_pin_map, xe, tile, size, flags); 2581 - 2582 - bo = xe_bo_create_pin_map(xe, tile, NULL, size, ttm_bo_type_kernel, flags); 2538 + bo = xe_bo_create_pin_map_novm(xe, tile, size, ttm_bo_type_kernel, flags, true); 2583 2539 if (IS_ERR(bo)) 2584 2540 return bo; 2585 2541
+5 -1
drivers/gpu/drm/xe/xe_bo.h
··· 108 108 u16 cpu_caching, u32 flags, struct drm_exec *exec); 109 109 struct xe_bo *xe_bo_create_pin_map(struct xe_device *xe, struct xe_tile *tile, 110 110 struct xe_vm *vm, size_t size, 111 - enum ttm_bo_type type, u32 flags); 111 + enum ttm_bo_type type, u32 flags, 112 + struct drm_exec *exec); 113 + struct xe_bo *xe_bo_create_pin_map_novm(struct xe_device *xe, struct xe_tile *tile, 114 + size_t size, enum ttm_bo_type type, u32 flags, 115 + bool intr); 112 116 struct xe_bo * 113 117 xe_bo_create_pin_map_at_novm(struct xe_device *xe, struct xe_tile *tile, 114 118 size_t size, u64 offset, enum ttm_bo_type type,
+4 -4
drivers/gpu/drm/xe/xe_gsc.c
··· 136 136 u64 ggtt_offset; 137 137 int err; 138 138 139 - bo = xe_bo_create_pin_map(xe, tile, NULL, GSC_VER_PKT_SZ * 2, 140 - ttm_bo_type_kernel, 141 - XE_BO_FLAG_SYSTEM | 142 - XE_BO_FLAG_GGTT); 139 + bo = xe_bo_create_pin_map_novm(xe, tile, GSC_VER_PKT_SZ * 2, 140 + ttm_bo_type_kernel, 141 + XE_BO_FLAG_SYSTEM | 142 + XE_BO_FLAG_GGTT, false); 143 143 if (IS_ERR(bo)) { 144 144 xe_gt_err(gt, "failed to allocate bo for GSC version query\n"); 145 145 return PTR_ERR(bo);
+12 -12
drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c
··· 55 55 xe_gt_assert(gt, size % sizeof(u32) == 0); 56 56 xe_gt_assert(gt, size == ndwords * sizeof(u32)); 57 57 58 - bo = xe_bo_create_pin_map(xe, tile, NULL, 59 - ALIGN(size, PAGE_SIZE), 60 - ttm_bo_type_kernel, 61 - XE_BO_FLAG_SYSTEM | 62 - XE_BO_FLAG_GGTT | 63 - XE_BO_FLAG_GGTT_INVALIDATE); 58 + bo = xe_bo_create_pin_map_novm(xe, tile, 59 + ALIGN(size, PAGE_SIZE), 60 + ttm_bo_type_kernel, 61 + XE_BO_FLAG_SYSTEM | 62 + XE_BO_FLAG_GGTT | 63 + XE_BO_FLAG_GGTT_INVALIDATE, false); 64 64 if (IS_ERR(bo)) 65 65 return PTR_ERR(bo); 66 66 ··· 91 91 xe_gt_assert(gt, size % sizeof(u32) == 0); 92 92 xe_gt_assert(gt, size == ndwords * sizeof(u32)); 93 93 94 - bo = xe_bo_create_pin_map(xe, tile, NULL, 95 - ALIGN(size, PAGE_SIZE), 96 - ttm_bo_type_kernel, 97 - XE_BO_FLAG_SYSTEM | 98 - XE_BO_FLAG_GGTT | 99 - XE_BO_FLAG_GGTT_INVALIDATE); 94 + bo = xe_bo_create_pin_map_novm(xe, tile, 95 + ALIGN(size, PAGE_SIZE), 96 + ttm_bo_type_kernel, 97 + XE_BO_FLAG_SYSTEM | 98 + XE_BO_FLAG_GGTT | 99 + XE_BO_FLAG_GGTT_INVALIDATE, false); 100 100 if (IS_ERR(bo)) 101 101 return PTR_ERR(bo); 102 102
+7 -6
drivers/gpu/drm/xe/xe_guc_engine_activity.c
··· 94 94 struct xe_tile *tile = gt_to_tile(gt); 95 95 struct xe_bo *bo, *metadata_bo; 96 96 97 - metadata_bo = xe_bo_create_pin_map(gt_to_xe(gt), tile, NULL, PAGE_ALIGN(metadata_size), 98 - ttm_bo_type_kernel, XE_BO_FLAG_SYSTEM | 99 - XE_BO_FLAG_GGTT | XE_BO_FLAG_GGTT_INVALIDATE); 97 + metadata_bo = xe_bo_create_pin_map_novm(gt_to_xe(gt), tile, PAGE_ALIGN(metadata_size), 98 + ttm_bo_type_kernel, XE_BO_FLAG_SYSTEM | 99 + XE_BO_FLAG_GGTT | XE_BO_FLAG_GGTT_INVALIDATE, 100 + false); 100 101 101 102 if (IS_ERR(metadata_bo)) 102 103 return PTR_ERR(metadata_bo); 103 104 104 - bo = xe_bo_create_pin_map(gt_to_xe(gt), tile, NULL, PAGE_ALIGN(size), 105 - ttm_bo_type_kernel, XE_BO_FLAG_VRAM_IF_DGFX(tile) | 106 - XE_BO_FLAG_GGTT | XE_BO_FLAG_GGTT_INVALIDATE); 105 + bo = xe_bo_create_pin_map_novm(gt_to_xe(gt), tile, PAGE_ALIGN(size), 106 + ttm_bo_type_kernel, XE_BO_FLAG_VRAM_IF_DGFX(tile) | 107 + XE_BO_FLAG_GGTT | XE_BO_FLAG_GGTT_INVALIDATE, false); 107 108 108 109 if (IS_ERR(bo)) { 109 110 xe_bo_unpin_map_no_vm(metadata_bo);
+6 -6
drivers/gpu/drm/xe/xe_lmtt.c
··· 67 67 goto out; 68 68 } 69 69 70 - bo = xe_bo_create_pin_map(lmtt_to_xe(lmtt), lmtt_to_tile(lmtt), NULL, 71 - PAGE_ALIGN(lmtt->ops->lmtt_pte_size(level) * 72 - lmtt->ops->lmtt_pte_num(level)), 73 - ttm_bo_type_kernel, 74 - XE_BO_FLAG_VRAM_IF_DGFX(lmtt_to_tile(lmtt)) | 75 - XE_BO_FLAG_NEEDS_64K); 70 + bo = xe_bo_create_pin_map_novm(lmtt_to_xe(lmtt), lmtt_to_tile(lmtt), 71 + PAGE_ALIGN(lmtt->ops->lmtt_pte_size(level) * 72 + lmtt->ops->lmtt_pte_num(level)), 73 + ttm_bo_type_kernel, 74 + XE_BO_FLAG_VRAM_IF_DGFX(lmtt_to_tile(lmtt)) | 75 + XE_BO_FLAG_NEEDS_64K, false); 76 76 if (IS_ERR(bo)) { 77 77 err = PTR_ERR(bo); 78 78 goto out_free_pt;
+4 -3
drivers/gpu/drm/xe/xe_lrc.c
··· 1340 1340 if (vm && vm->xef) /* userspace */ 1341 1341 bo_flags |= XE_BO_FLAG_PINNED_LATE_RESTORE; 1342 1342 1343 - lrc->bo = xe_bo_create_pin_map(xe, tile, NULL, bo_size, 1344 - ttm_bo_type_kernel, 1345 - bo_flags); 1343 + lrc->bo = xe_bo_create_pin_map_novm(xe, tile, 1344 + bo_size, 1345 + ttm_bo_type_kernel, 1346 + bo_flags, false); 1346 1347 if (IS_ERR(lrc->bo)) 1347 1348 return PTR_ERR(lrc->bo); 1348 1349
+14 -6
drivers/gpu/drm/xe/xe_migrate.c
··· 35 35 #include "xe_sched_job.h" 36 36 #include "xe_sync.h" 37 37 #include "xe_trace_bo.h" 38 + #include "xe_validation.h" 38 39 #include "xe_vm.h" 39 40 #include "xe_vram.h" 40 41 ··· 174 173 } 175 174 176 175 static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, 177 - struct xe_vm *vm) 176 + struct xe_vm *vm, struct drm_exec *exec) 178 177 { 179 178 struct xe_device *xe = tile_to_xe(tile); 180 179 u16 pat_index = xe->pat.idx[XE_CACHE_WB]; ··· 201 200 num_entries * XE_PAGE_SIZE, 202 201 ttm_bo_type_kernel, 203 202 XE_BO_FLAG_VRAM_IF_DGFX(tile) | 204 - XE_BO_FLAG_PAGETABLE); 203 + XE_BO_FLAG_PAGETABLE, exec); 205 204 if (IS_ERR(bo)) 206 205 return PTR_ERR(bo); 207 206 ··· 405 404 struct xe_tile *tile = m->tile; 406 405 struct xe_gt *primary_gt = tile->primary_gt; 407 406 struct xe_device *xe = tile_to_xe(tile); 407 + struct xe_validation_ctx ctx; 408 + struct drm_exec exec; 408 409 struct xe_vm *vm; 409 410 int err; 410 411 ··· 416 413 if (IS_ERR(vm)) 417 414 return PTR_ERR(vm); 418 415 419 - xe_vm_lock(vm, false); 420 - err = xe_migrate_prepare_vm(tile, m, vm); 421 - xe_vm_unlock(vm); 416 + err = 0; 417 + xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {}, err) { 418 + err = xe_vm_drm_exec_lock(vm, &exec); 419 + drm_exec_retry_on_contention(&exec); 420 + err = xe_migrate_prepare_vm(tile, m, vm, &exec); 421 + drm_exec_retry_on_contention(&exec); 422 + xe_validation_retry_on_oom(&ctx, &err); 423 + } 422 424 if (err) 423 - goto err_out; 425 + return err; 424 426 425 427 if (xe->info.has_usm) { 426 428 struct xe_hw_engine *hwe = xe_gt_hw_engine(primary_gt,
+3 -3
drivers/gpu/drm/xe/xe_oa.c
··· 883 883 { 884 884 struct xe_bo *bo; 885 885 886 - bo = xe_bo_create_pin_map(stream->oa->xe, stream->gt->tile, NULL, 887 - size, ttm_bo_type_kernel, 888 - XE_BO_FLAG_SYSTEM | XE_BO_FLAG_GGTT); 886 + bo = xe_bo_create_pin_map_novm(stream->oa->xe, stream->gt->tile, 887 + size, ttm_bo_type_kernel, 888 + XE_BO_FLAG_SYSTEM | XE_BO_FLAG_GGTT, false); 889 889 if (IS_ERR(bo)) 890 890 return PTR_ERR(bo); 891 891
+7 -3
drivers/gpu/drm/xe/xe_pt.c
··· 90 90 * @vm: The vm to create for. 91 91 * @tile: The tile to create for. 92 92 * @level: The page-table level. 93 + * @exec: The drm_exec object used to lock the vm. 93 94 * 94 95 * Allocate and initialize a single struct xe_pt metadata structure. Also 95 96 * create the corresponding page-table bo, but don't initialize it. If the ··· 102 101 * error. 103 102 */ 104 103 struct xe_pt *xe_pt_create(struct xe_vm *vm, struct xe_tile *tile, 105 - unsigned int level) 104 + unsigned int level, struct drm_exec *exec) 106 105 { 107 106 struct xe_pt *pt; 108 107 struct xe_bo *bo; ··· 126 125 bo_flags |= XE_BO_FLAG_PINNED_LATE_RESTORE; 127 126 128 127 pt->level = level; 128 + 129 + drm_WARN_ON(&vm->xe->drm, IS_ERR_OR_NULL(exec)); 129 130 bo = xe_bo_create_pin_map(vm->xe, tile, vm, SZ_4K, 130 131 ttm_bo_type_kernel, 131 - bo_flags); 132 + bo_flags, exec); 132 133 if (IS_ERR(bo)) { 133 134 err = PTR_ERR(bo); 134 135 goto err_kfree; ··· 594 591 if (covers || !*child) { 595 592 u64 flags = 0; 596 593 597 - xe_child = xe_pt_create(xe_walk->vm, xe_walk->tile, level - 1); 594 + xe_child = xe_pt_create(xe_walk->vm, xe_walk->tile, level - 1, 595 + xe_vm_validation_exec(vm)); 598 596 if (IS_ERR(xe_child)) 599 597 return PTR_ERR(xe_child); 600 598
+2 -1
drivers/gpu/drm/xe/xe_pt.h
··· 10 10 #include "xe_pt_types.h" 11 11 12 12 struct dma_fence; 13 + struct drm_exec; 13 14 struct xe_bo; 14 15 struct xe_device; 15 16 struct xe_exec_queue; ··· 30 29 unsigned int xe_pt_shift(unsigned int level); 31 30 32 31 struct xe_pt *xe_pt_create(struct xe_vm *vm, struct xe_tile *tile, 33 - unsigned int level); 32 + unsigned int level, struct drm_exec *exec); 34 33 35 34 void xe_pt_populate_empty(struct xe_tile *tile, struct xe_vm *vm, 36 35 struct xe_pt *pt);
+24 -10
drivers/gpu/drm/xe/xe_pxp_submit.c
··· 54 54 * Each termination is 16 DWORDS, so 4K is enough to contain a 55 55 * termination for each sessions. 56 56 */ 57 - bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4K, ttm_bo_type_kernel, 58 - XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | XE_BO_FLAG_GGTT); 57 + bo = xe_bo_create_pin_map_novm(xe, tile, SZ_4K, ttm_bo_type_kernel, 58 + XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | XE_BO_FLAG_GGTT, 59 + false); 59 60 if (IS_ERR(bo)) { 60 61 err = PTR_ERR(bo); 61 62 goto out_queue; ··· 88 87 { 89 88 struct xe_tile *tile = gt_to_tile(gt); 90 89 struct xe_device *xe = tile_to_xe(tile); 90 + struct xe_validation_ctx ctx; 91 91 struct xe_hw_engine *hwe; 92 + struct drm_exec exec; 92 93 struct xe_vm *vm; 93 94 struct xe_bo *bo; 94 95 struct xe_exec_queue *q; ··· 109 106 return PTR_ERR(vm); 110 107 111 108 /* We allocate a single object for the batch and the in/out memory */ 112 - xe_vm_lock(vm, false); 113 - bo = xe_bo_create_pin_map(xe, tile, vm, PXP_BB_SIZE + inout_size * 2, 114 - ttm_bo_type_kernel, 115 - XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | XE_BO_FLAG_NEEDS_UC); 116 - xe_vm_unlock(vm); 117 - if (IS_ERR(bo)) { 118 - err = PTR_ERR(bo); 119 - goto vm_out; 109 + 110 + xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags){}, err) { 111 + err = xe_vm_drm_exec_lock(vm, &exec); 112 + drm_exec_retry_on_contention(&exec); 113 + if (err) 114 + break; 115 + 116 + bo = xe_bo_create_pin_map(xe, tile, vm, PXP_BB_SIZE + inout_size * 2, 117 + ttm_bo_type_kernel, 118 + XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | 119 + XE_BO_FLAG_NEEDS_UC, &exec); 120 + drm_exec_retry_on_contention(&exec); 121 + if (IS_ERR(bo)) { 122 + err = PTR_ERR(bo); 123 + xe_validation_retry_on_oom(&ctx, &err); 124 + break; 125 + } 120 126 } 127 + if (err) 128 + goto vm_out; 121 129 122 130 fence = xe_vm_bind_kernel_bo(vm, bo, NULL, 0, XE_CACHE_WB); 123 131 if (IS_ERR(fence)) {
+73 -50
drivers/gpu/drm/xe/xe_vm.c
··· 1370 1370 * @xe: xe device. 1371 1371 * @tile: tile to set up for. 1372 1372 * @vm: vm to set up for. 1373 + * @exec: The struct drm_exec object used to lock the vm resv. 1373 1374 * 1374 1375 * Sets up a pagetable tree with one page-table per level and a single 1375 1376 * leaf PTE. All pagetable entries point to the single page-table or, ··· 1380 1379 * Return: 0 on success, negative error code on error. 1381 1380 */ 1382 1381 static int xe_vm_create_scratch(struct xe_device *xe, struct xe_tile *tile, 1383 - struct xe_vm *vm) 1382 + struct xe_vm *vm, struct drm_exec *exec) 1384 1383 { 1385 1384 u8 id = tile->id; 1386 1385 int i; 1387 1386 1388 1387 for (i = MAX_HUGEPTE_LEVEL; i < vm->pt_root[id]->level; i++) { 1389 - vm->scratch_pt[id][i] = xe_pt_create(vm, tile, i); 1388 + vm->scratch_pt[id][i] = xe_pt_create(vm, tile, i, exec); 1390 1389 if (IS_ERR(vm->scratch_pt[id][i])) { 1391 1390 int err = PTR_ERR(vm->scratch_pt[id][i]); 1392 1391 1393 1392 vm->scratch_pt[id][i] = NULL; 1394 1393 return err; 1395 1394 } 1396 - 1397 1395 xe_pt_populate_empty(tile, vm, vm->scratch_pt[id][i]); 1398 1396 } 1399 1397 ··· 1420 1420 } 1421 1421 } 1422 1422 1423 + static void xe_vm_pt_destroy(struct xe_vm *vm) 1424 + { 1425 + struct xe_tile *tile; 1426 + u8 id; 1427 + 1428 + xe_vm_assert_held(vm); 1429 + 1430 + for_each_tile(tile, vm->xe, id) { 1431 + if (vm->pt_root[id]) { 1432 + xe_pt_destroy(vm->pt_root[id], vm->flags, NULL); 1433 + vm->pt_root[id] = NULL; 1434 + } 1435 + } 1436 + } 1437 + 1423 1438 struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef) 1424 1439 { 1425 1440 struct drm_gem_object *vm_resv_obj; 1441 + struct xe_validation_ctx ctx; 1442 + struct drm_exec exec; 1426 1443 struct xe_vm *vm; 1427 1444 int err, number_tiles = 0; 1428 1445 struct xe_tile *tile; ··· 1524 1507 1525 1508 drm_gem_object_put(vm_resv_obj); 1526 1509 1527 - err = xe_vm_lock(vm, true); 1528 - if (err) 1529 - goto err_close; 1510 + err = 0; 1511 + xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {.interruptible = true}, 1512 + err) { 1513 + err = xe_vm_drm_exec_lock(vm, &exec); 1514 + drm_exec_retry_on_contention(&exec); 1530 1515 1531 - if (IS_DGFX(xe) && xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) 1532 - vm->flags |= XE_VM_FLAG_64K; 1516 + if (IS_DGFX(xe) && xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K) 1517 + vm->flags |= XE_VM_FLAG_64K; 1533 1518 1534 - for_each_tile(tile, xe, id) { 1535 - if (flags & XE_VM_FLAG_MIGRATION && 1536 - tile->id != XE_VM_FLAG_TILE_ID(flags)) 1537 - continue; 1519 + for_each_tile(tile, xe, id) { 1520 + if (flags & XE_VM_FLAG_MIGRATION && 1521 + tile->id != XE_VM_FLAG_TILE_ID(flags)) 1522 + continue; 1538 1523 1539 - vm->pt_root[id] = xe_pt_create(vm, tile, xe->info.vm_max_level); 1540 - if (IS_ERR(vm->pt_root[id])) { 1541 - err = PTR_ERR(vm->pt_root[id]); 1542 - vm->pt_root[id] = NULL; 1543 - goto err_unlock_close; 1524 + vm->pt_root[id] = xe_pt_create(vm, tile, xe->info.vm_max_level, 1525 + &exec); 1526 + if (IS_ERR(vm->pt_root[id])) { 1527 + err = PTR_ERR(vm->pt_root[id]); 1528 + vm->pt_root[id] = NULL; 1529 + xe_vm_pt_destroy(vm); 1530 + drm_exec_retry_on_contention(&exec); 1531 + xe_validation_retry_on_oom(&ctx, &err); 1532 + break; 1533 + } 1544 1534 } 1545 - } 1535 + if (err) 1536 + break; 1546 1537 1547 - if (xe_vm_has_scratch(vm)) { 1538 + if (xe_vm_has_scratch(vm)) { 1539 + for_each_tile(tile, xe, id) { 1540 + if (!vm->pt_root[id]) 1541 + continue; 1542 + 1543 + err = xe_vm_create_scratch(xe, tile, vm, &exec); 1544 + if (err) { 1545 + xe_vm_free_scratch(vm); 1546 + xe_vm_pt_destroy(vm); 1547 + drm_exec_retry_on_contention(&exec); 1548 + xe_validation_retry_on_oom(&ctx, &err); 1549 + break; 1550 + } 1551 + } 1552 + if (err) 1553 + break; 1554 + vm->batch_invalidate_tlb = true; 1555 + } 1556 + 1557 + if (vm->flags & XE_VM_FLAG_LR_MODE) { 1558 + INIT_WORK(&vm->preempt.rebind_work, preempt_rebind_work_func); 1559 + vm->batch_invalidate_tlb = false; 1560 + } 1561 + 1562 + /* Fill pt_root after allocating scratch tables */ 1548 1563 for_each_tile(tile, xe, id) { 1549 1564 if (!vm->pt_root[id]) 1550 1565 continue; 1551 1566 1552 - err = xe_vm_create_scratch(xe, tile, vm); 1553 - if (err) 1554 - goto err_unlock_close; 1567 + xe_pt_populate_empty(tile, vm, vm->pt_root[id]); 1555 1568 } 1556 - vm->batch_invalidate_tlb = true; 1557 1569 } 1558 - 1559 - if (vm->flags & XE_VM_FLAG_LR_MODE) 1560 - vm->batch_invalidate_tlb = false; 1561 - 1562 - /* Fill pt_root after allocating scratch tables */ 1563 - for_each_tile(tile, xe, id) { 1564 - if (!vm->pt_root[id]) 1565 - continue; 1566 - 1567 - xe_pt_populate_empty(tile, vm, vm->pt_root[id]); 1568 - } 1569 - xe_vm_unlock(vm); 1570 + if (err) 1571 + goto err_close; 1570 1572 1571 1573 /* Kernel migration VM shouldn't have a circular loop.. */ 1572 1574 if (!(flags & XE_VM_FLAG_MIGRATION)) { ··· 1618 1582 &xe->usm.next_asid, GFP_KERNEL); 1619 1583 up_write(&xe->usm.lock); 1620 1584 if (err < 0) 1621 - goto err_unlock_close; 1585 + goto err_close; 1622 1586 1623 1587 vm->usm.asid = asid; 1624 1588 } ··· 1627 1591 1628 1592 return vm; 1629 1593 1630 - err_unlock_close: 1631 - xe_vm_unlock(vm); 1632 1594 err_close: 1633 1595 xe_vm_close_and_put(vm); 1634 1596 return ERR_PTR(err); ··· 1759 1725 * destroy the pagetables immediately. 1760 1726 */ 1761 1727 xe_vm_free_scratch(vm); 1762 - 1763 - for_each_tile(tile, xe, id) { 1764 - if (vm->pt_root[id]) { 1765 - xe_pt_destroy(vm->pt_root[id], vm->flags, NULL); 1766 - vm->pt_root[id] = NULL; 1767 - } 1768 - } 1728 + xe_vm_pt_destroy(vm); 1769 1729 xe_vm_unlock(vm); 1770 1730 1771 1731 /* ··· 3809 3781 */ 3810 3782 int xe_vm_lock(struct xe_vm *vm, bool intr) 3811 3783 { 3812 - struct drm_exec *exec = XE_VALIDATION_UNIMPLEMENTED; 3813 3784 int ret; 3814 3785 3815 3786 if (intr) 3816 3787 ret = dma_resv_lock_interruptible(xe_vm_resv(vm), NULL); 3817 3788 else 3818 3789 ret = dma_resv_lock(xe_vm_resv(vm), NULL); 3819 - 3820 - if (!ret) 3821 - xe_vm_set_validation_exec(vm, exec); 3822 3790 3823 3791 return ret; 3824 3792 } ··· 3827 3803 */ 3828 3804 void xe_vm_unlock(struct xe_vm *vm) 3829 3805 { 3830 - xe_vm_set_validation_exec(vm, NULL); 3831 3806 dma_resv_unlock(xe_vm_resv(vm)); 3832 3807 } 3833 3808