Skip to content

Commit 5ab57c7

Browse files
committed
drm/i915: Flush logical context image out to memory upon suspend
Before suspend, and especially before building the hibernation image, we need to context image to be coherent in memory. To do this we require that we perform a context switch to a disposable context (i.e. the dev_priv->kernel_context) - when that switch is complete, all other context images will be complete. This leaves the kernel_context image as incomplete, but fortunately that is disposable and we can do a quick fixup of the logical state after resuming. v2: Share the nearly identical code to switch to the kernel context with eviction. v3: Explain why we need the switch and reset. Testcase: igt/gem_exec_suspend # bsw References: https://bugs.freedesktop.org/show_bug.cgi?id=96526 Signed-off-by: Chris Wilson <[email protected]> Cc: Ville Syrjälä <[email protected]> Reviewed-by: Ville Syrjälä <[email protected]> Tested-by: Ville Syrjälä <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 945657b commit 5ab57c7

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,9 +1590,7 @@ static int i915_drm_resume(struct drm_device *dev)
15901590

15911591
intel_csr_ucode_resume(dev_priv);
15921592

1593-
mutex_lock(&dev->struct_mutex);
1594-
i915_gem_restore_gtt_mappings(dev);
1595-
mutex_unlock(&dev->struct_mutex);
1593+
i915_gem_resume(dev);
15961594

15971595
i915_restore_state(dev);
15981596
intel_opregion_setup(dev_priv);

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3384,6 +3384,7 @@ void i915_gem_init_swizzling(struct drm_device *dev);
33843384
void i915_gem_cleanup_engines(struct drm_device *dev);
33853385
int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv);
33863386
int __must_check i915_gem_suspend(struct drm_device *dev);
3387+
void i915_gem_resume(struct drm_device *dev);
33873388
void __i915_add_request(struct drm_i915_gem_request *req,
33883389
struct drm_i915_gem_object *batch_obj,
33893390
bool flush_caches);

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4983,12 +4983,30 @@ i915_gem_suspend(struct drm_device *dev)
49834983
intel_suspend_gt_powersave(dev_priv);
49844984

49854985
mutex_lock(&dev->struct_mutex);
4986+
4987+
/* We have to flush all the executing contexts to main memory so
4988+
* that they can saved in the hibernation image. To ensure the last
4989+
* context image is coherent, we have to switch away from it. That
4990+
* leaves the dev_priv->kernel_context still active when
4991+
* we actually suspend, and its image in memory may not match the GPU
4992+
* state. Fortunately, the kernel_context is disposable and we do
4993+
* not rely on its state.
4994+
*/
4995+
ret = i915_gem_switch_to_kernel_context(dev_priv);
4996+
if (ret)
4997+
goto err;
4998+
49864999
ret = i915_gem_wait_for_idle(dev_priv);
49875000
if (ret)
49885001
goto err;
49895002

49905003
i915_gem_retire_requests(dev_priv);
49915004

5005+
/* Note that rather than stopping the engines, all we have to do
5006+
* is assert that every RING_HEAD == RING_TAIL (all execution complete)
5007+
* and similar for all logical context images (to ensure they are
5008+
* all ready for hibernation).
5009+
*/
49925010
i915_gem_stop_engines(dev);
49935011
i915_gem_context_lost(dev_priv);
49945012
mutex_unlock(&dev->struct_mutex);
@@ -5009,6 +5027,23 @@ i915_gem_suspend(struct drm_device *dev)
50095027
return ret;
50105028
}
50115029

5030+
void i915_gem_resume(struct drm_device *dev)
5031+
{
5032+
struct drm_i915_private *dev_priv = to_i915(dev);
5033+
5034+
mutex_lock(&dev->struct_mutex);
5035+
i915_gem_restore_gtt_mappings(dev);
5036+
5037+
/* As we didn't flush the kernel context before suspend, we cannot
5038+
* guarantee that the context image is complete. So let's just reset
5039+
* it and start again.
5040+
*/
5041+
if (i915.enable_execlists)
5042+
intel_lr_context_reset(dev_priv, dev_priv->kernel_context);
5043+
5044+
mutex_unlock(&dev->struct_mutex);
5045+
}
5046+
50125047
void i915_gem_init_swizzling(struct drm_device *dev)
50135048
{
50145049
struct drm_i915_private *dev_priv = to_i915(dev);

0 commit comments

Comments
 (0)