Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31acbcc4 authored by Chris Wilson's avatar Chris Wilson Committed by Keith Packard
Browse files

drm/i915/dp: Be paranoid in case we disable a DP before it is attached



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: default avatarBryan Christ <bryan.christ@gmail.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=36314


Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=36456


Reported-and-tested-by: default avatarBo Wang <bo.b.wang@intel.com>
Cc: stable@kernel.org
Signed-off-by: default avatarKeith Packard <keithp@keithp.com>
parent 2dd251f0
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -1470,7 +1470,8 @@ 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);
		struct drm_crtc *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 +1486,19 @@ 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);
		if (crtc == NULL) {
			/* We can arrive here never having been attached
			 * to a CRTC, for instance, due to inheriting
			 * random state from the BIOS.
			 *
			 * If the pipe is not running, play safe and
			 * wait for the clocks to stabilise before
			 * continuing.
			 */
			POSTING_READ(intel_dp->output_reg);
			msleep(50);
		} else
			intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
	}

	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);