mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-15 19:01:45 -04:00
drm/xe: Convert pinned suspend eviction for exhaustive eviction
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
This commit is contained in:
@@ -1141,43 +1141,47 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo,
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user