Teardown of GuC HW/SW state was not properly done in unload path. During unload, we can rely on intel_guc_reset_prepare being done as part of i915_gem_suspend for disabling GuC interfaces. We will have to disable GuC submission prior to suspend as that involves communication with GuC to destroy doorbell. So intel_uc_fini_hw has to be called as part of i915_gem_suspend during unload as that really takes care of finishing the GuC operations. Created new parameter for i915_gem_suspend to handle unload/suspend path w.r.t gem and GuC suspend. GuC related allocations are cleaned up as part of intel_uc_cleanup_hw. Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Cc: Michal Wajdeczko <michal.wajdeczko@xxxxxxxxx> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx> Signed-off-by: Sagar Arun Kamble <sagar.a.kamble@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_drv.c | 8 ++++---- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_gem.c | 8 ++++++-- drivers/gpu/drm/i915/intel_guc.c | 13 +++++++++++++ drivers/gpu/drm/i915/intel_guc.h | 1 + drivers/gpu/drm/i915/intel_uc.c | 14 +++++--------- drivers/gpu/drm/i915/intel_uc.h | 1 + 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 218a8e1..c3fb73f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -599,7 +599,7 @@ static void i915_gem_fini(struct drm_i915_private *dev_priv) i915_gem_drain_workqueue(dev_priv); mutex_lock(&dev_priv->drm.struct_mutex); - intel_uc_fini_hw(dev_priv); + intel_uc_cleanup_hw(dev_priv); i915_gem_cleanup_engines(dev_priv); i915_gem_contexts_fini(dev_priv); i915_gem_cleanup_userptr(dev_priv); @@ -680,7 +680,7 @@ static int i915_load_modeset_init(struct drm_device *dev) return 0; cleanup_gem: - if (i915_gem_suspend(dev_priv)) + if (i915_gem_suspend(dev_priv, true)) DRM_ERROR("failed to idle hardware; continuing to unload!\n"); i915_gem_fini(dev_priv); cleanup_uc: @@ -1373,7 +1373,7 @@ void i915_driver_unload(struct drm_device *dev) i915_driver_unregister(dev_priv); - if (i915_gem_suspend(dev_priv)) + if (i915_gem_suspend(dev_priv, true)) DRM_ERROR("failed to idle hardware; continuing to unload!\n"); intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); @@ -1518,7 +1518,7 @@ static int i915_drm_suspend(struct drm_device *dev) pci_save_state(pdev); - error = i915_gem_suspend(dev_priv); + error = i915_gem_suspend(dev_priv, false); if (error) { dev_err(&pdev->dev, "GEM idle failed, resume might fail\n"); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 085647a..dd6a3ff 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3547,7 +3547,8 @@ void i915_gem_reset_engine(struct intel_engine_cs *engine, void i915_gem_cleanup_engines(struct drm_i915_private *dev_priv); int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, unsigned int flags); -int __must_check i915_gem_suspend(struct drm_i915_private *dev_priv); +int __must_check i915_gem_suspend(struct drm_i915_private *dev_priv, + bool unload); void i915_gem_resume(struct drm_i915_private *dev_priv); int i915_gem_fault(struct vm_fault *vmf); int i915_gem_object_wait(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e118b9a..1b1b9c7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4525,7 +4525,7 @@ void i915_gem_sanitize(struct drm_i915_private *i915) } } -int i915_gem_suspend(struct drm_i915_private *dev_priv) +int i915_gem_suspend(struct drm_i915_private *dev_priv, bool unload) { struct drm_device *dev = &dev_priv->drm; int ret; @@ -4572,7 +4572,11 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) WARN_ON(dev_priv->gt.awake); WARN_ON(!intel_engines_are_idle(dev_priv)); - intel_guc_system_suspend(&dev_priv->guc); + /* Handle GuC suspension in case of unloading/system suspend */ + if (unload) + intel_uc_fini_hw(dev_priv); + else + intel_guc_system_suspend(&dev_priv->guc); /* * Neither the BIOS, ourselves or any other kernel diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c index 3777659..f4ddfbb 100644 --- a/drivers/gpu/drm/i915/intel_guc.c +++ b/drivers/gpu/drm/i915/intel_guc.c @@ -313,3 +313,16 @@ int intel_guc_system_resume(struct intel_guc *guc) */ return ret; } + +void intel_guc_fini(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct drm_device *dev = &dev_priv->drm; + + if (i915.enable_guc_submission) { + mutex_lock(&dev->struct_mutex); + i915_guc_submission_disable(dev_priv); + mutex_unlock(&dev->struct_mutex); + intel_guc_reset_prepare(&dev_priv->guc); + } +} diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index e9664bf..ed3d202 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -161,6 +161,7 @@ struct intel_guc { int intel_guc_runtime_resume(struct intel_guc *guc); int intel_guc_system_suspend(struct intel_guc *guc); int intel_guc_system_resume(struct intel_guc *guc); +void intel_guc_fini(struct intel_guc *guc); static inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index 95af45f..e6b9330 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c @@ -363,20 +363,16 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) void intel_uc_fini_hw(struct drm_i915_private *dev_priv) { + intel_guc_fini(&dev_priv->guc); +} + +void intel_uc_cleanup_hw(struct drm_i915_private *dev_priv) +{ guc_free_load_err_log(&dev_priv->guc); if (!i915.enable_guc_loading) return; if (i915.enable_guc_submission) - i915_guc_submission_disable(dev_priv); - - guc_disable_communication(&dev_priv->guc); - - if (i915.enable_guc_submission) { - gen9_disable_guc_interrupts(dev_priv); i915_guc_submission_fini(dev_priv); - } - - i915_ggtt_disable_guc(dev_priv); } diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index 13460f8..bfe5639 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -97,5 +97,6 @@ struct intel_uc_fw { void intel_uc_fini_fw(struct drm_i915_private *dev_priv); int intel_uc_init_hw(struct drm_i915_private *dev_priv); void intel_uc_fini_hw(struct drm_i915_private *dev_priv); +void intel_uc_cleanup_hw(struct drm_i915_private *dev_priv); #endif -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx