On Mon, Feb 08, 2016 at 02:13:26AM +0100, Mario Kleiner wrote: > Changes to drm_update_vblank_count() in Linux 4.4 broke the > behaviour of the pre/post modeset functions as the new update > code doesn't deal with hw vblank counter resets inbetween calls > to drm_vblank_pre_modeset an drm_vblank_post_modeset, as it > should. > > This causes mistreatment of such hw counter resets as counter > wraparound, and thereby large forward jumps of the software > vblank counter which in turn cause vblank event dispatching > and vblank waits to fail/hang --> userspace clients hang. > > This symptom was reported on radeon-kms to cause a infinite > hang of KDE Plasma 5 shell's login procedure, preventing users > from logging in. > > Fix this by detecting when drm_update_vblank_count() is called > inside a pre->post modeset interval. If so, clamp valid vblank > increments to the safe values 0 and 1, pretty much restoring > the update behavior of the old update code of Linux 4.3 and > earlier. Also reset the last recorded hw vblank count at call > to drm_vblank_post_modeset() to be safe against hw that after > modesetting, dpms on etc. only fires its first vblank irq after > drm_vblank_post_modeset() was already called. > > Reported-by: Vlastimil Babka <vbabka@xxxxxxx> > Signed-off-by: Mario Kleiner <mario.kleiner.de@xxxxxxxxx> > Cc: <stable@xxxxxxxxxxxxxxx> # 4.4+ > Cc: michel@xxxxxxxxxxx > Cc: vbabka@xxxxxxx > Cc: ville.syrjala@xxxxxxxxxxxxxxx > Cc: daniel.vetter@xxxxxxxx > Cc: dri-devel@xxxxxxxxxxxxxxxxxxxxx > Cc: alexander.deucher@xxxxxxx > Cc: christian.koenig@xxxxxxx We need to untangle the new vblank stuff that assumes solide (atomic) drivers and all the old stuff much more. But that can be done later on. Reviewed-by: Daniel Vetter <daniel.vetter@xxxxxxxx> > --- > drivers/gpu/drm/drm_irq.c | 16 ++++++++++++++++ > 1 file changed, 16 insertions(+) > > diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c > index aa2c74b..5c27ad3 100644 > --- a/drivers/gpu/drm/drm_irq.c > +++ b/drivers/gpu/drm/drm_irq.c > @@ -222,6 +222,21 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, > } > > /* > + * Within a drm_vblank_pre_modeset - drm_vblank_post_modeset > + * interval? If so then vblank irqs keep running and it will likely > + * happen that the hardware vblank counter is not trustworthy as it > + * might reset at some point in that interval and vblank timestamps > + * are not trustworthy either in that interval. Iow. this can result > + * in a bogus diff >> 1 which must be avoided as it would cause > + * random large forward jumps of the software vblank counter. > + */ > + if (diff > 1 && (vblank->inmodeset & 0x2)) { > + DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u" > + " due to pre-modeset.\n", pipe, diff); > + diff = 1; > + } > + > + /* > * Restrict the bump of the software vblank counter to a safe maximum > * value of +1 whenever there is the possibility that concurrent readers > * of vblank timestamps could be active at the moment, as the current > @@ -1573,6 +1588,7 @@ void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe) > if (vblank->inmodeset) { > spin_lock_irqsave(&dev->vbl_lock, irqflags); > dev->vblank_disable_allowed = true; > + drm_reset_vblank_timestamp(dev, pipe); > spin_unlock_irqrestore(&dev->vbl_lock, irqflags); > > if (vblank->inmodeset & 0x2) > -- > 1.9.1 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html