Given that the hardware may be left in a random condition by the BIOS,
it is conceivable that we then attempt to clear the DP_PIPEB_SELECT bit
without us ever enabling/attaching the DP encoder to a pipe. Thus
causing a NULL deference when we attempt to wait for a vblank on that
crtc.

Reported-and-tested-by: Bryan Christ <bryan.chr...@gmail.com>
References: https://bugs.freedesktop.org/show_bug.cgi?id=36314
Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
Cc: sta...@kernel.org
---
 drivers/gpu/drm/i915/intel_dp.c  |    3 +--
 drivers/gpu/drm/i915/intel_drv.h |    7 +++++++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0daefca..819afca 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1470,7 +1470,6 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
        if (!HAS_PCH_CPT(dev) &&
            I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
-               struct intel_crtc *intel_crtc = 
to_intel_crtc(intel_dp->base.base.crtc);
                /* Hardware workaround: leaving our transcoder select
                 * set to transcoder B while it's off will prevent the
                 * corresponding HDMI output on transcoder A.
@@ -1485,7 +1484,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
                /* Changes to enable or select take place the vblank
                 * after being written.
                 */
-               intel_wait_for_vblank(dev, intel_crtc->pipe);
+               intel_wait_for_crtc_vblank_safe(intel_dp->base.base.crtc);
        }
 
        I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f5b0d83..aeb1b98 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -290,6 +290,13 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct 
drm_device *dev,
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
 extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
+static inline void intel_wait_for_crtc_vblank_safe(struct drm_crtc *crtc)
+{
+       if (crtc)
+               intel_wait_for_vblank(crtc->dev, to_intel_crtc(crtc)->pipe);
+       else
+               msleep(50);
+}
 extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
 extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder 
*intel_encoder,
                                                   struct drm_connector 
*connector,
-- 
1.7.4.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to