Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Estimate and update missed vblanks.

The frame counter may have got reset between disabling and enabling vblank
interrupts due to DMC putting the hardware to DC5/6 states if PSR was
active. The frame counter could also have stalled if PSR was active in case
there was no DMC. The frame counter resetting has a user visible impact
of screen freezes.

Make use of drm_vblank_restore() to compute missed vblanks for the duration
in which vblank interrupts were disabled and update the vblank counter with
this value as diff. There's no need to check if PSR was actually active in
the interrupt disabled duration, so simplify the check to a feature check.

Enabling vblank interrupts wakes up the hardware from DC5/6 and prevents it
from going back again as long as the there are pending interrupts. So, we
don't have to explicity disallow DC5/6 after enabling vblank interrupts to
keep the counter running.

This change is not applicable to CHV, as enabling interrupts does not
prevent the hardware from activating PSR.

v2: Added comments(Rodrigo) and rewrote commit message.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-10-dhinakaran.pandiyan@intel.com

authored by

Dhinakaran Pandiyan and committed by
Rodrigo Vivi
2e8bf223 d0bb96b4

+12
+12
drivers/gpu/drm/i915/i915_irq.c
··· 2951 2951 ilk_enable_display_irq(dev_priv, bit); 2952 2952 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2953 2953 2954 + /* Even though there is no DMC, frame counter can get stuck when 2955 + * PSR is active as no frames are generated. 2956 + */ 2957 + if (HAS_PSR(dev_priv)) 2958 + drm_vblank_restore(dev, pipe); 2959 + 2954 2960 return 0; 2955 2961 } 2956 2962 ··· 2968 2962 spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 2969 2963 bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); 2970 2964 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 2965 + 2966 + /* Even if there is no DMC, frame counter can get stuck when 2967 + * PSR is active as no frames are generated, so check only for PSR. 2968 + */ 2969 + if (HAS_PSR(dev_priv)) 2970 + drm_vblank_restore(dev, pipe); 2971 2971 2972 2972 return 0; 2973 2973 }