]> www.infradead.org Git - users/hch/misc.git/commitdiff
drm/xe: Convert pinned suspend eviction for exhaustive eviction
authorThomas Hellström <thomas.hellstrom@linux.intel.com>
Mon, 8 Sep 2025 10:12:46 +0000 (12:12 +0200)
committerThomas Hellström <thomas.hellstrom@linux.intel.com>
Wed, 10 Sep 2025 07:16:10 +0000 (09:16 +0200)
Pinned suspend eviction and preparation for eviction validates
system memory for eviction buffers. Do that under a
validation exclusive lock to avoid interfering with other
processes validating system graphics memory.

v2:
- Avoid gotos from within xe_validation_guard().
- 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-14-thomas.hellstrom@linux.intel.com
drivers/gpu/drm/xe/xe_bo.c

index 21efcb170239dc51df82f1642d0bcf5fee6a03f0..e6d16b34e5b53aa9e45d702367ec97893e6d7633 100644 (file)
@@ -1141,43 +1141,47 @@ out_unref:
 int xe_bo_notifier_prepare_pinned(struct xe_bo *bo)
 {
        struct xe_device *xe = ttm_to_xe_device(bo->ttm.bdev);
-       struct drm_exec *exec = XE_VALIDATION_UNIMPLEMENTED;
+       struct xe_validation_ctx ctx;
+       struct drm_exec exec;
        struct xe_bo *backup;
        int ret = 0;
 
-       xe_bo_lock(bo, false);
+       xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {.exclusive = true}, ret) {
+               ret = drm_exec_lock_obj(&exec, &bo->ttm.base);
+               drm_exec_retry_on_contention(&exec);
+               xe_assert(xe, !ret);
+               xe_assert(xe, !bo->backup_obj);
 
-       xe_assert(xe, !bo->backup_obj);
+               /*
+                * Since this is called from the PM notifier we might have raced with
+                * someone unpinning this after we dropped the pinned list lock and
+                * grabbing the above bo lock.
+                */
+               if (!xe_bo_is_pinned(bo))
+                       break;
 
-       /*
-        * Since this is called from the PM notifier we might have raced with
-        * someone unpinning this after we dropped the pinned list lock and
-        * grabbing the above bo lock.
-        */
-       if (!xe_bo_is_pinned(bo))
-               goto out_unlock_bo;
+               if (!xe_bo_is_vram(bo))
+                       break;
 
-       if (!xe_bo_is_vram(bo))
-               goto out_unlock_bo;
+               if (bo->flags & XE_BO_FLAG_PINNED_NORESTORE)
+                       break;
 
-       if (bo->flags & XE_BO_FLAG_PINNED_NORESTORE)
-               goto out_unlock_bo;
+               backup = xe_bo_init_locked(xe, NULL, NULL, bo->ttm.base.resv, NULL, xe_bo_size(bo),
+                                          DRM_XE_GEM_CPU_CACHING_WB, ttm_bo_type_kernel,
+                                          XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
+                                          XE_BO_FLAG_PINNED, &exec);
+               if (IS_ERR(backup)) {
+                       drm_exec_retry_on_contention(&exec);
+                       ret = PTR_ERR(backup);
+                       xe_validation_retry_on_oom(&ctx, &ret);
+                       break;
+               }
 
-       backup = xe_bo_init_locked(xe, NULL, NULL, bo->ttm.base.resv, NULL, xe_bo_size(bo),
-                                  DRM_XE_GEM_CPU_CACHING_WB, ttm_bo_type_kernel,
-                                  XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
-                                  XE_BO_FLAG_PINNED, exec);
-       if (IS_ERR(backup)) {
-               ret = PTR_ERR(backup);
-               goto out_unlock_bo;
+               backup->parent_obj = xe_bo_get(bo); /* Released by bo_destroy */
+               ttm_bo_pin(&backup->ttm);
+               bo->backup_obj = backup;
        }
 
-       backup->parent_obj = xe_bo_get(bo); /* Released by bo_destroy */
-       ttm_bo_pin(&backup->ttm);
-       bo->backup_obj = backup;
-
-out_unlock_bo:
-       xe_bo_unlock(bo);
        return ret;
 }
 
@@ -1203,57 +1207,12 @@ int xe_bo_notifier_unprepare_pinned(struct xe_bo *bo)
        return 0;
 }
 
-/**
- * xe_bo_evict_pinned() - Evict a pinned VRAM object to system memory
- * @bo: The buffer object to move.
- *
- * On successful completion, the object memory will be moved to system memory.
- *
- * This is needed to for special handling of pinned VRAM object during
- * suspend-resume.
- *
- * Return: 0 on success. Negative error code on failure.
- */
-int xe_bo_evict_pinned(struct xe_bo *bo)
+static int xe_bo_evict_pinned_copy(struct xe_bo *bo, struct xe_bo *backup)
 {
-       struct xe_device *xe = ttm_to_xe_device(bo->ttm.bdev);
-       struct drm_exec *exec = XE_VALIDATION_UNIMPLEMENTED;
-       struct xe_bo *backup = bo->backup_obj;
-       bool backup_created = false;
+       struct xe_device *xe = xe_bo_device(bo);
        bool unmap = false;
        int ret = 0;
 
-       xe_bo_lock(bo, false);
-
-       if (WARN_ON(!bo->ttm.resource)) {
-               ret = -EINVAL;
-               goto out_unlock_bo;
-       }
-
-       if (WARN_ON(!xe_bo_is_pinned(bo))) {
-               ret = -EINVAL;
-               goto out_unlock_bo;
-       }
-
-       if (!xe_bo_is_vram(bo))
-               goto out_unlock_bo;
-
-       if (bo->flags & XE_BO_FLAG_PINNED_NORESTORE)
-               goto out_unlock_bo;
-
-       if (!backup) {
-               backup = xe_bo_init_locked(xe, NULL, NULL, bo->ttm.base.resv, NULL, xe_bo_size(bo),
-                                          DRM_XE_GEM_CPU_CACHING_WB, ttm_bo_type_kernel,
-                                          XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
-                                          XE_BO_FLAG_PINNED, exec);
-               if (IS_ERR(backup)) {
-                       ret = PTR_ERR(backup);
-                       goto out_unlock_bo;
-               }
-               backup->parent_obj = xe_bo_get(bo); /* Released by bo_destroy */
-               backup_created = true;
-       }
-
        if (xe_bo_is_user(bo) || (bo->flags & XE_BO_FLAG_PINNED_LATE_RESTORE)) {
                struct xe_migrate *migrate;
                struct dma_fence *fence;
@@ -1286,7 +1245,7 @@ int xe_bo_evict_pinned(struct xe_bo *bo)
                if (iosys_map_is_null(&bo->vmap)) {
                        ret = xe_bo_vmap(bo);
                        if (ret)
-                               goto out_backup;
+                               goto out_vunmap;
                        unmap = true;
                }
 
@@ -1296,15 +1255,78 @@ int xe_bo_evict_pinned(struct xe_bo *bo)
 
        if (!bo->backup_obj)
                bo->backup_obj = backup;
-
-out_backup:
+out_vunmap:
        xe_bo_vunmap(backup);
-       if (ret && backup_created)
-               xe_bo_put(backup);
-out_unlock_bo:
+out_backup:
        if (unmap)
                xe_bo_vunmap(bo);
-       xe_bo_unlock(bo);
+
+       return ret;
+}
+
+/**
+ * xe_bo_evict_pinned() - Evict a pinned VRAM object to system memory
+ * @bo: The buffer object to move.
+ *
+ * On successful completion, the object memory will be moved to system memory.
+ *
+ * This is needed to for special handling of pinned VRAM object during
+ * suspend-resume.
+ *
+ * Return: 0 on success. Negative error code on failure.
+ */
+int xe_bo_evict_pinned(struct xe_bo *bo)
+{
+       struct xe_device *xe = ttm_to_xe_device(bo->ttm.bdev);
+       struct xe_validation_ctx ctx;
+       struct drm_exec exec;
+       struct xe_bo *backup = bo->backup_obj;
+       bool backup_created = false;
+       int ret = 0;
+
+       xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {.exclusive = true}, ret) {
+               ret = drm_exec_lock_obj(&exec, &bo->ttm.base);
+               drm_exec_retry_on_contention(&exec);
+               xe_assert(xe, !ret);
+
+               if (WARN_ON(!bo->ttm.resource)) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               if (WARN_ON(!xe_bo_is_pinned(bo))) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               if (!xe_bo_is_vram(bo))
+                       break;
+
+               if (bo->flags & XE_BO_FLAG_PINNED_NORESTORE)
+                       break;
+
+               if (!backup) {
+                       backup = xe_bo_init_locked(xe, NULL, NULL, bo->ttm.base.resv, NULL,
+                                                  xe_bo_size(bo),
+                                                  DRM_XE_GEM_CPU_CACHING_WB, ttm_bo_type_kernel,
+                                                  XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
+                                                  XE_BO_FLAG_PINNED, &exec);
+                       if (IS_ERR(backup)) {
+                               drm_exec_retry_on_contention(&exec);
+                               ret = PTR_ERR(backup);
+                               xe_validation_retry_on_oom(&ctx, &ret);
+                               break;
+                       }
+                       backup->parent_obj = xe_bo_get(bo); /* Released by bo_destroy */
+                       backup_created = true;
+               }
+
+               ret = xe_bo_evict_pinned_copy(bo, backup);
+       }
+
+       if (ret && backup_created)
+               xe_bo_put(backup);
+
        return ret;
 }