On Wed, Aug 09, 2017 at 03:53:47PM +0530, Sagar Arun Kamble wrote: > 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) This extra param is not very intuitive. Can we have two public functions: int i915_gem_suspend(struct drm_i915_private *dev_priv) int i915_gem_unload(struct drm_i915_private *dev_priv) > { > 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); You can use "guc" param here. > + } > +} > 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) I'm little confused with above names. Is there matching "prepare" function ? What is the expected order of calls ? early_init/init/prepare/cleanup/fini ? > +{ > 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