From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Daniel Vetter <daniel@ffwll.ch>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 5/6] drm/i915: Grab modeset locks for GPU rest on pre-ctg
Date: Fri, 21 Nov 2014 23:10:31 +0200 [thread overview]
Message-ID: <20141121211031.GG10649@intel.com> (raw)
In-Reply-To: <20141121204921.GD25711@phenom.ffwll.local>
On Fri, Nov 21, 2014 at 09:49:21PM +0100, Daniel Vetter wrote:
> On Fri, Nov 21, 2014 at 09:54:29PM +0200, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > On gen4 and earlier the GPU reset also resets the display, so we should
> > protect against concurrent modeset operations. Grab all the modeset locks
> > around the entire GPU reset dance, remebering first ti dislogde any
> > pending page flip to make sure we don't deadlock. Any pageflip coming
> > in between these two steps should fail anyway due to reset_in_progress,
> > so this should be safe.
> >
> > This fixes a lot of failed asserts in the modeset code when there's a
> > modeset racing with the reset. Naturally the asserts aren't happy when
> > the expected state has disappeared.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Two comments on this one, otherwise looks good (well didn't bother to
> check the new reset register frobbing).
> -Daniel
>
> > ---
> > drivers/gpu/drm/i915/i915_drv.c | 19 -------
> > drivers/gpu/drm/i915/i915_irq.c | 5 +-
> > drivers/gpu/drm/i915/intel_display.c | 96 ++++++++++++++++++++++++++++++------
> > drivers/gpu/drm/i915/intel_drv.h | 3 +-
> > 4 files changed, 86 insertions(+), 37 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 5066fd1..1e9c136 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -880,25 +880,6 @@ int i915_reset(struct drm_device *dev)
> > */
> > if (INTEL_INFO(dev)->gen > 5)
> > intel_reset_gt_powersave(dev);
> > -
> > -
> > - if (IS_GEN3(dev) || (IS_GEN4(dev) && !IS_G4X(dev))) {
> > - intel_runtime_pm_disable_interrupts(dev_priv);
> > - intel_runtime_pm_enable_interrupts(dev_priv);
> > -
> > - intel_modeset_init_hw(dev);
> > -
> > - spin_lock_irq(&dev_priv->irq_lock);
> > - if (dev_priv->display.hpd_irq_setup)
> > - dev_priv->display.hpd_irq_setup(dev);
> > - spin_unlock_irq(&dev_priv->irq_lock);
> > -
> > - drm_modeset_lock_all(dev);
> > - intel_modeset_setup_hw_state(dev, true);
> > - drm_modeset_unlock_all(dev);
> > -
> > - intel_hpd_init(dev_priv);
> > - }
> > } else {
> > mutex_unlock(&dev->struct_mutex);
> > }
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index 5908580d..8887674 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -2428,6 +2428,9 @@ static void i915_error_work_func(struct work_struct *work)
> > * simulated reset via debugs, so get an RPM reference.
> > */
> > intel_runtime_pm_get(dev_priv);
> > +
> > + intel_prepare_reset(dev);
> > +
> > /*
> > * All state reset _must_ be completed before we update the
> > * reset counter, for otherwise waiters might miss the reset
> > @@ -2436,7 +2439,7 @@ static void i915_error_work_func(struct work_struct *work)
> > */
> > ret = i915_reset(dev);
> >
> > - intel_display_handle_reset(dev);
> > + intel_finish_reset(dev);
> >
> > intel_runtime_pm_put(dev_priv);
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 3218455..8329f7c 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2765,25 +2765,10 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
> > return 0;
> > }
> >
> > -void intel_display_handle_reset(struct drm_device *dev)
> > +static void intel_complete_page_flips(struct drm_device *dev)
> > {
> > - struct drm_i915_private *dev_priv = dev->dev_private;
> > struct drm_crtc *crtc;
> >
> > - /*
> > - * Flips in the rings have been nuked by the reset,
> > - * so complete all pending flips so that user space
> > - * will get its events and not get stuck.
> > - *
> > - * Also update the base address of all primary
> > - * planes to the the last fb to make sure we're
> > - * showing the correct fb after a reset.
> > - *
> > - * Need to make two loops over the crtcs so that we
> > - * don't try to grab a crtc mutex before the
> > - * pending_flip_queue really got woken up.
> > - */
> > -
> > for_each_crtc(dev, crtc) {
> > struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > enum plane plane = intel_crtc->plane;
> > @@ -2791,6 +2776,12 @@ void intel_display_handle_reset(struct drm_device *dev)
> > intel_prepare_page_flip(dev, plane);
> > intel_finish_page_flip_plane(dev, plane);
> > }
> > +}
> > +
> > +static void intel_update_primary_planes(struct drm_device *dev)
> > +{
> > + struct drm_i915_private *dev_priv = dev->dev_private;
> > + struct drm_crtc *crtc;
> >
> > for_each_crtc(dev, crtc) {
> > struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > @@ -2810,6 +2801,79 @@ void intel_display_handle_reset(struct drm_device *dev)
> > }
> > }
> >
> > +void intel_prepare_reset(struct drm_device *dev)
> > +{
> > + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> > + return;
>
> ums just officially died please remove. Same for the one below.
okey dokey
>
> > +
> > + /*
> > + * Flips in the rings will be nuked by the reset,
> > + * so complete all pending flips so that user space
> > + * will get its events and not get stuck.
> > + *
> > + * Old platforms will also reset the display, so we
> > + * need to grab the modeset locks around the reset.
> > + * But in order to do that we must let any pending
> > + * page flip wait complete since the waiters may be
> > + * holding some modeset locks.
> > + */
> > + intel_complete_page_flips(dev);
>
> Is this really required? We complete them afterwards, and all the pageflip
> waiters I've found do check for gpu hangs and abort the pageflip wait.
> That's already required since the mmio flip might go missing, and thus far
> we've only completed the flip _after_ having reset the gpu and gem state
> (and grabbed dev->struct_mutex).
Hmm. Yeah, just waking them up ought to be sufficient to dislodge
things. And we already do that before scheduling the error work, but
after setting the reset_in_progress flag, which is very much critical
here. So I guess I could just move the complete pending flips bit to
intel_finish_reset().
But then I do wonder a bit why I originally needed to add the unlocked
page flip complete before the locked .update_plane() call. Did we miss
a wakeup somewhere or did we not abort pending flip waits on reset?
>
> > +
> > + /* no reset support for gen2 */
> > + if (IS_GEN2(dev))
> > + return;
> > +
> > + /* reset doesn't touch the display */
> > + if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
> > + return;
> > +
> > + drm_modeset_lock_all(dev);
> > +}
> > +
> > +void intel_finish_reset(struct drm_device *dev)
> > +{
> > + struct drm_i915_private *dev_priv = to_i915(dev);
> > +
> > + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> > + return;
> > +
> > + /* no reset support for gen2 */
> > + if (IS_GEN2(dev))
> > + return;
> > +
> > + /* reset doesn't touch the display */
> > + if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
> > + /*
> > + * Flips in the rings have been nuked by the reset,
> > + * so update the base address of all primary
> > + * planes to the the last fb to make sure we're
> > + * showing the correct fb after a reset.
> > + */
> > + intel_update_primary_planes(dev);
> > + return;
> > + }
> > +
> > + /*
> > + * The display has been reset as well,
> > + * so need a full re-initialization.
> > + */
> > + intel_runtime_pm_disable_interrupts(dev_priv);
> > + intel_runtime_pm_enable_interrupts(dev_priv);
> > +
> > + intel_modeset_init_hw(dev);
> > +
> > + spin_lock_irq(&dev_priv->irq_lock);
> > + if (dev_priv->display.hpd_irq_setup)
> > + dev_priv->display.hpd_irq_setup(dev);
> > + spin_unlock_irq(&dev_priv->irq_lock);
> > +
> > + intel_modeset_setup_hw_state(dev, true);
> > +
> > + intel_hpd_init(dev_priv);
> > +
> > + drm_modeset_unlock_all(dev);
> > +}
> > +
> > static int
> > intel_finish_fb(struct drm_framebuffer *old_fb)
> > {
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index f0a46ec..25fdbb1 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -958,7 +958,8 @@ unsigned long intel_gen4_compute_page_offset(int *x, int *y,
> > unsigned int tiling_mode,
> > unsigned int bpp,
> > unsigned int pitch);
> > -void intel_display_handle_reset(struct drm_device *dev);
> > +void intel_prepare_reset(struct drm_device *dev);
> > +void intel_finish_reset(struct drm_device *dev);
> > void hsw_enable_pc8(struct drm_i915_private *dev_priv);
> > void hsw_disable_pc8(struct drm_i915_private *dev_priv);
> > void intel_dp_get_m_n(struct intel_crtc *crtc,
> > --
> > 2.0.4
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2014-11-21 21:10 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-21 19:54 [PATCH 0/6] drm/i915: Implement gen3/4 GPU reset ville.syrjala
2014-11-21 19:54 ` [PATCH 1/6] drm/i915: Fix gen4 " ville.syrjala
2014-11-22 11:05 ` Chris Wilson
2014-11-24 12:57 ` Ville Syrjälä
2014-11-21 19:54 ` [PATCH 2/6] drm/i915: Restore the display config after a GPU reset on gen4 ville.syrjala
2014-11-21 19:54 ` [PATCH 3/6] drm/i915: Implement GPU reset for 915/945 ville.syrjala
2014-11-25 12:54 ` Daniel Vetter
2014-11-21 19:54 ` [PATCH 4/6] drm/i915: Implement GPU reset for g33 ville.syrjala
2014-11-21 19:54 ` [PATCH 5/6] drm/i915: Grab modeset locks for GPU rest on pre-ctg ville.syrjala
2014-11-21 20:49 ` Daniel Vetter
2014-11-21 21:10 ` Ville Syrjälä [this message]
2014-11-24 9:34 ` Daniel Vetter
2014-11-24 13:17 ` Ville Syrjälä
2014-11-24 16:28 ` [PATCH v2 " ville.syrjala
2014-11-21 19:54 ` [PATCH 6/6] drm/i915: Disable crtcs gracefully before GPU reset on gen3/4 ville.syrjala
2014-11-24 10:02 ` [PATCH 6/6] drm/i915: Disable crtcs gracefully before shuang.he
2014-11-24 16:28 ` [PATCH 7/6] drm/i915: Deal with video overlay on GPU reset ville.syrjala
2014-11-25 12:35 ` Daniel Vetter
2014-11-26 15:07 ` [PATCH v2 " ville.syrjala
2014-11-26 18:10 ` Daniel Vetter
2014-11-27 12:04 ` Dave Gordon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20141121211031.GG10649@intel.com \
--to=ville.syrjala@linux.intel.com \
--cc=daniel@ffwll.ch \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox