// SPDX-License-Identifier: MIT
/*
* Copyright © 2021 Intel Corporation
*/
#include <drm/ttm/ttm_placement.h>
#include <drm/ttm/ttm_tt.h>
#include "i915_drv.h"
#include "intel_memory_region.h"
#include "intel_region_ttm.h"
#include "gem/i915_gem_region.h"
#include "gem/i915_gem_ttm.h"
#include "gem/i915_gem_ttm_move.h"
#include "gem/i915_gem_ttm_pm.h"
/**
* i915_ttm_backup_free - Free any backup attached to this object
* @ obj : The object whose backup is to be freed .
*/
void i915_ttm_backup_free(struct drm_i915_gem_object *obj)
{
if (obj->ttm.backup) {
i915_gem_object_put(obj->ttm.backup);
obj->ttm.backup = NULL;
}
}
/**
* struct i915_gem_ttm_pm_apply - Apply - to - region subclass for restore
* @ base : The i915_gem_apply_to_region we derive from .
* @ allow_gpu : Whether using the gpu blitter is allowed .
* @ backup_pinned : On backup , backup also pinned objects .
*/
struct i915_gem_ttm_pm_apply {
struct i915_gem_apply_to_region base;
bool allow_gpu : 1 ;
bool backup_pinned : 1 ;
};
static int i915_ttm_backup(struct i915_gem_apply_to_region *apply,
struct drm_i915_gem_object *obj)
{
struct i915_gem_ttm_pm_apply *pm_apply =
container_of(apply, typeof(*pm_apply), base);
struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
struct ttm_buffer_object *backup_bo;
struct drm_i915_private *i915 =
container_of(bo->bdev, typeof(*i915), bdev);
struct drm_i915_gem_object *backup;
struct ttm_operation_ctx ctx = {};
unsigned int flags;
int err = 0 ;
if (!i915_ttm_cpu_maps_iomem(bo->resource) || obj->ttm.backup)
return 0 ;
if (pm_apply->allow_gpu && i915_gem_object_evictable(obj))
return ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx);
if (!pm_apply->backup_pinned ||
(pm_apply->allow_gpu && (obj->flags & I915_BO_ALLOC_PM_EARLY)))
return 0 ;
if (obj->flags & I915_BO_ALLOC_PM_VOLATILE)
return 0 ;
/*
* It seems that we might have some framebuffers still pinned at this
* stage , but for such objects we might also need to deal with the CCS
* aux state . Make sure we force the save / restore of the CCS state ,
* otherwise we might observe display corruption , when returning from
* suspend .
*/
flags = 0 ;
if (i915_gem_object_needs_ccs_pages(obj)) {
WARN_ON_ONCE(!i915_gem_object_is_framebuffer(obj));
WARN_ON_ONCE(!pm_apply->allow_gpu);
flags = I915_BO_ALLOC_CCS_AUX;
}
backup = i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_SMEM],
obj->base.size, 0 , flags);
if (IS_ERR(backup))
return PTR_ERR(backup);
err = i915_gem_object_lock(backup, apply->ww);
if (err)
goto out_no_lock;
backup_bo = i915_gem_to_ttm(backup);
err = ttm_bo_populate(backup_bo, &ctx);
if (err)
goto out_no_populate;
err = i915_gem_obj_copy_ttm(backup, obj, pm_apply->allow_gpu, false );
if (err) {
drm_err(&i915->drm,
"Unable to copy from device to system memory, err:%pe\n" ,
ERR_PTR(err));
goto out_no_populate;
}
ttm_bo_wait_ctx(backup_bo, &ctx);
obj->ttm.backup = backup;
return 0 ;
out_no_populate:
i915_gem_ww_unlock_single(backup);
out_no_lock:
i915_gem_object_put(backup);
return err;
}
static int i915_ttm_recover(struct i915_gem_apply_to_region *apply,
struct drm_i915_gem_object *obj)
{
i915_ttm_backup_free(obj);
return 0 ;
}
/**
* i915_ttm_recover_region - Free the backup of all objects of a region
* @ mr : The memory region
*
* Checks all objects of a region if there is backup attached and if so
* frees that backup . Typically this is called to recover after a partially
* performed backup .
*/
void i915_ttm_recover_region(struct intel_memory_region *mr)
{
static const struct i915_gem_apply_to_region_ops recover_ops = {
.process_obj = i915_ttm_recover,
};
struct i915_gem_apply_to_region apply = {.ops = &recover_ops};
int ret;
ret = i915_gem_process_region(mr, &apply);
GEM_WARN_ON(ret);
}
/**
* i915_ttm_backup_region - Back up all objects of a region to smem .
* @ mr : The memory region
* @ flags : TTM backup flags
*
* Loops over all objects of a region and either evicts them if they are
* evictable or backs them up using a backup object if they are pinned .
*
* Return : Zero on success . Negative error code on error .
*/
int i915_ttm_backup_region(struct intel_memory_region *mr, u32 flags)
{
static const struct i915_gem_apply_to_region_ops backup_ops = {
.process_obj = i915_ttm_backup,
};
struct i915_gem_ttm_pm_apply pm_apply = {
.base = {.ops = &backup_ops},
.allow_gpu = flags & I915_TTM_BACKUP_ALLOW_GPU,
.backup_pinned = flags & I915_TTM_BACKUP_PINNED,
};
return i915_gem_process_region(mr, &pm_apply.base);
}
static int i915_ttm_restore(struct i915_gem_apply_to_region *apply,
struct drm_i915_gem_object *obj)
{
struct i915_gem_ttm_pm_apply *pm_apply =
container_of(apply, typeof(*pm_apply), base);
struct drm_i915_gem_object *backup = obj->ttm.backup;
struct ttm_buffer_object *backup_bo = i915_gem_to_ttm(backup);
struct ttm_operation_ctx ctx = {};
int err;
if (!backup)
return 0 ;
if (!pm_apply->allow_gpu && !(obj->flags & I915_BO_ALLOC_PM_EARLY))
return 0 ;
err = i915_gem_object_lock(backup, apply->ww);
if (err)
return err;
/* Content may have been swapped. */
if (!backup_bo->resource)
err = ttm_bo_validate(backup_bo, i915_ttm_sys_placement(), &ctx);
if (!err)
err = ttm_bo_populate(backup_bo, &ctx);
if (!err) {
err = i915_gem_obj_copy_ttm(obj, backup, pm_apply->allow_gpu,
false );
GEM_WARN_ON(err);
ttm_bo_wait_ctx(backup_bo, &ctx);
obj->ttm.backup = NULL;
err = 0 ;
}
i915_gem_ww_unlock_single(backup);
if (!err)
i915_gem_object_put(backup);
return err;
}
/**
* i915_ttm_restore_region - Restore backed - up objects of a region from smem .
* @ mr : The memory region
* @ flags : TTM backup flags
*
* Loops over all objects of a region and if they are backed - up , restores
* them from smem .
*
* Return : Zero on success . Negative error code on error .
*/
int i915_ttm_restore_region(struct intel_memory_region *mr, u32 flags)
{
static const struct i915_gem_apply_to_region_ops restore_ops = {
.process_obj = i915_ttm_restore,
};
struct i915_gem_ttm_pm_apply pm_apply = {
.base = {.ops = &restore_ops},
.allow_gpu = flags & I915_TTM_BACKUP_ALLOW_GPU,
};
return i915_gem_process_region(mr, &pm_apply.base);
}
Messung V0.5 in Prozent C=97 H=94 G=95
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-10-03)
¤
*© Formatika GbR, Deutschland