drm/i915: Reset the gpu on takeover
The GPU may be in an unknown state following resume and module load. The previous occupant may have left contexts loaded, or other dangerous state, which can cause an immediate GPU hang for us. The only save course of action is to reset the GPU prior to using it - similarly to how we reset the GPU prior to unload (before a second user may be affected by our leftover state). We need to reset the GPU very early in our load/resume sequence so that any stale HW pointers are revoked prior to any resource allocations we make (that may conflict). A reset should only be a couple of milliseconds on a slow device, a cost we should easily be able to absorb into our initialisation times. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170124110135.6418-2-chris@chris-wilson.co.uk
This commit is contained in:
Родитель
bb8f0f5abd
Коммит
241455172b
|
@ -950,6 +950,7 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
|
|||
goto put_bridge;
|
||||
|
||||
intel_uncore_init(dev_priv);
|
||||
i915_gem_init_mmio(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1731,6 +1732,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
|
|||
!(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
|
||||
intel_power_domains_init_hw(dev_priv, true);
|
||||
|
||||
i915_gem_sanitize(dev_priv);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
out:
|
||||
|
|
|
@ -3120,6 +3120,7 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv);
|
||||
int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
void i915_gem_sanitize(struct drm_i915_private *i915);
|
||||
int i915_gem_load_init(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_load_cleanup(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_load_init_fences(struct drm_i915_private *dev_priv);
|
||||
|
@ -3335,6 +3336,7 @@ int i915_gem_reset_prepare(struct drm_i915_private *dev_priv);
|
|||
void i915_gem_reset_finish(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
|
||||
void i915_gem_init_mmio(struct drm_i915_private *i915);
|
||||
int __must_check i915_gem_init(struct drm_i915_private *dev_priv);
|
||||
int __must_check i915_gem_init_hw(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_init_swizzling(struct drm_i915_private *dev_priv);
|
||||
|
|
|
@ -4201,6 +4201,23 @@ static void assert_kernel_context_is_current(struct drm_i915_private *dev_priv)
|
|||
!i915_gem_context_is_kernel(engine->last_retired_context));
|
||||
}
|
||||
|
||||
void i915_gem_sanitize(struct drm_i915_private *i915)
|
||||
{
|
||||
/*
|
||||
* If we inherit context state from the BIOS or earlier occupants
|
||||
* of the GPU, the GPU may be in an inconsistent state when we
|
||||
* try to take over. The only way to remove the earlier state
|
||||
* is by resetting. However, resetting on earlier gen is tricky as
|
||||
* it may impact the display and we are uncertain about the stability
|
||||
* of the reset, so we only reset recent machines with logical
|
||||
* context support (that must be reset to remove any stray contexts).
|
||||
*/
|
||||
if (HAS_HW_CONTEXTS(i915)) {
|
||||
int reset = intel_gpu_reset(i915, ALL_ENGINES);
|
||||
WARN_ON(reset && reset != -ENODEV);
|
||||
}
|
||||
}
|
||||
|
||||
int i915_gem_suspend(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
|
@ -4271,10 +4288,7 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv)
|
|||
* machines is a good idea, we don't - just in case it leaves the
|
||||
* machine in an unusable condition.
|
||||
*/
|
||||
if (HAS_HW_CONTEXTS(dev_priv)) {
|
||||
int reset = intel_gpu_reset(dev_priv, ALL_ENGINES);
|
||||
WARN_ON(reset && reset != -ENODEV);
|
||||
}
|
||||
i915_gem_sanitize(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -4492,6 +4506,11 @@ out_unlock:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void i915_gem_init_mmio(struct drm_i915_private *i915)
|
||||
{
|
||||
i915_gem_sanitize(i915);
|
||||
}
|
||||
|
||||
void
|
||||
i915_gem_cleanup_engines(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче