Home Home > GIT Browse > stable
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2019-02-15 10:23:48 +0100
committerJiri Slaby <jslaby@suse.cz>2019-02-15 10:24:15 +0100
commitfa5527e79d4a6b1d3a0f6cfaa14496c0d89b7143 (patch)
tree5da228d84c79a8a1ab40d23b53b55e5410cb934a
parentb2481606b2e0f63152d436451d8f4067ce34d2e8 (diff)
drm/i915: Try to sanitize bogus DPLL state left over by broken
SNB BIOSen (bnc#1012628).
-rw-r--r--patches.kernel.org/4.20.9-045-drm-i915-Try-to-sanitize-bogus-DPLL-state-left.patch141
-rw-r--r--series.conf1
2 files changed, 142 insertions, 0 deletions
diff --git a/patches.kernel.org/4.20.9-045-drm-i915-Try-to-sanitize-bogus-DPLL-state-left.patch b/patches.kernel.org/4.20.9-045-drm-i915-Try-to-sanitize-bogus-DPLL-state-left.patch
new file mode 100644
index 0000000000..b80fb9cec7
--- /dev/null
+++ b/patches.kernel.org/4.20.9-045-drm-i915-Try-to-sanitize-bogus-DPLL-state-left.patch
@@ -0,0 +1,141 @@
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+Date: Tue, 5 Feb 2019 16:18:46 +0200
+Subject: [PATCH] drm/i915: Try to sanitize bogus DPLL state left over by
+ broken SNB BIOSen
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+References: bnc#1012628
+Patch-mainline: 4.20.9
+Git-commit: d028a646e84b9b131e4ff2cb5bbdd3825d141028
+Git-commit: 7bed8adcd9f86231bb69bbc02f88ad89330f99e3
+
+commit d028a646e84b9b131e4ff2cb5bbdd3825d141028 upstream.
+
+Certain SNB machines (eg. ASUS K53SV) seem to have a broken BIOS
+which misprograms the hardware badly when encountering a suitably
+high resolution display. The programmed pipe timings are somewhat
+bonkers and the DPLL is totally misprogrammed (P divider == 0).
+That will result in atomic commit timeouts as apparently the pipe
+is sufficiently stuck to not signal vblank interrupts.
+
+IIRC something like this was also observed on some other SNB
+machine years ago (might have been a Dell XPS 8300) but a BIOS
+update cured it. Sadly looks like this was never fixed for the
+ASUS K53SV as the latest BIOS (K53SV.320 11/11/2011) is still
+broken.
+
+The quickest way to deal with this seems to be to shut down
+the pipe+ports+DPLL. Unfortunately doing this during the
+normal sanitization phase isn't quite soon enough as we
+already spew several WARNs about the bogus hardware state.
+But it's better than hanging the boot for a few dozen seconds.
+Since this is limited to a few old machines it doesn't seem
+entirely worthwile to try and rework the readout+sanitization
+code to handle it more gracefully.
+
+v2: Fix potential NULL deref (kbuild test robot)
+ Constify has_bogus_dpll_config()
+
+Cc: stable@vger.kernel.org # v4.20+
+Cc: Daniel Kamil Kozar <dkk089@gmail.com>
+Reported-by: Daniel Kamil Kozar <dkk089@gmail.com>
+Tested-by: Daniel Kamil Kozar <dkk089@gmail.com>
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109245
+Fixes: 516a49cc1946 ("drm/i915: Fix assert_plane() warning on bootup with external display")
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190111174950.10681-1-ville.syrjala@linux.intel.com
+Reviewed-by: Mika Kahola <mika.kahola@intel.com>
+(cherry picked from commit 7bed8adcd9f86231bb69bbc02f88ad89330f99e3)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20190205141846.6053-1-ville.syrjala@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+---
+ drivers/gpu/drm/i915/intel_display.c | 51 ++++++++++++++++++++++++----
+ 1 file changed, 45 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
+index c9878dd1f7cd..a8293a7bab8f 100644
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -15684,15 +15684,44 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
+ }
+ }
+
++static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
++{
++ struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
++
++ /*
++ * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram
++ * the hardware when a high res displays plugged in. DPLL P
++ * divider is zero, and the pipe timings are bonkers. We'll
++ * try to disable everything in that case.
++ *
++ * FIXME would be nice to be able to sanitize this state
++ * without several WARNs, but for now let's take the easy
++ * road.
++ */
++ return IS_GEN6(dev_priv) &&
++ crtc_state->base.active &&
++ crtc_state->shared_dpll &&
++ crtc_state->port_clock == 0;
++}
++
+ static void intel_sanitize_encoder(struct intel_encoder *encoder)
+ {
+ struct intel_connector *connector;
++ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
++ struct intel_crtc_state *crtc_state = crtc ?
++ to_intel_crtc_state(crtc->base.state) : NULL;
+
+ /* We need to check both for a crtc link (meaning that the
+ * encoder is active and trying to read from a pipe) and the
+ * pipe itself being active. */
+- bool has_active_crtc = encoder->base.crtc &&
+- to_intel_crtc(encoder->base.crtc)->active;
++ bool has_active_crtc = crtc_state &&
++ crtc_state->base.active;
++
++ if (crtc_state && has_bogus_dpll_config(crtc_state)) {
++ DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n",
++ pipe_name(crtc->pipe));
++ has_active_crtc = false;
++ }
+
+ connector = intel_encoder_find_connector(encoder);
+ if (connector && !has_active_crtc) {
+@@ -15703,15 +15732,25 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
+ /* Connector is active, but has no active pipe. This is
+ * fallout from our resume register restoring. Disable
+ * the encoder manually again. */
+- if (encoder->base.crtc) {
+- struct drm_crtc_state *crtc_state = encoder->base.crtc->state;
++ if (crtc_state) {
++ struct drm_encoder *best_encoder;
+
+ DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
+ encoder->base.base.id,
+ encoder->base.name);
+- encoder->disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
++
++ /* avoid oopsing in case the hooks consult best_encoder */
++ best_encoder = connector->base.state->best_encoder;
++ connector->base.state->best_encoder = &encoder->base;
++
++ if (encoder->disable)
++ encoder->disable(encoder, crtc_state,
++ connector->base.state);
+ if (encoder->post_disable)
+- encoder->post_disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
++ encoder->post_disable(encoder, crtc_state,
++ connector->base.state);
++
++ connector->base.state->best_encoder = best_encoder;
+ }
+ encoder->base.crtc = NULL;
+
+--
+2.20.1
+
diff --git a/series.conf b/series.conf
index 85a5083e3d..af1bf0b985 100644
--- a/series.conf
+++ b/series.conf
@@ -1127,6 +1127,7 @@
patches.kernel.org/4.20.9-042-drm-vmwgfx-Fix-an-uninitialized-fence-handle-v.patch
patches.kernel.org/4.20.9-043-drm-vmwgfx-Return-error-code-from-vmw_execbuf_.patch
patches.kernel.org/4.20.9-044-xfrm-Make-set-mark-default-behavior-backward-c.patch
+ patches.kernel.org/4.20.9-045-drm-i915-Try-to-sanitize-bogus-DPLL-state-left.patch
########################################################
# Build fixes that apply to the vanilla kernel too.