drm/i915: Lower RM timeout to avoid DSI hard hangs
authorUma Shankar <uma.shankar@intel.com>
Tue, 7 Aug 2018 15:45:35 +0000 (21:15 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Nov 2019 18:16:23 +0000 (19:16 +0100)
commit 1d85a299c4db57c55e0229615132c964d17aa765 upstream.

In BXT/APL, device 2 MMIO reads from MIPI controller requires its PLL
to be turned ON. When MIPI PLL is turned off (MIPI Display is not
active or connected), and someone (host or GT engine) tries to read
MIPI registers, it causes hard hang. This is a hardware restriction
or limitation.

Driver by itself doesn't read MIPI registers when MIPI display is off.
But any userspace application can submit unprivileged batch buffer for
execution. In that batch buffer there can be mmio reads. And these
reads are allowed even for unprivileged applications. If these
register reads are for MIPI DSI controller and MIPI display is not
active during that time, then the MMIO read operation causes system
hard hang and only way to recover is hard reboot. A genuine
process/application won't submit batch buffer like this and doesn't
cause any issue. But on a compromised system, a malign userspace
process/app can generate such batch buffer and can trigger system
hard hang (denial of service attack).

The fix is to lower the internal MMIO timeout value to an optimum
value of 950us as recommended by hardware team. If the timeout is
beyond 1ms (which will hit for any value we choose if MMIO READ on a
DSI specific register is performed without PLL ON), it causes the
system hang. But if the timeout value is lower than it will be below
the threshold (even if timeout happens) and system will not get into
a hung state. This will avoid a system hang without losing any
programming or GT interrupts, taking the worst case of lowest CDCLK
frequency and early DC5 abort into account.

Signed-off-by: Uma Shankar <uma.shankar@intel.com>
Reviewed-by: Jon Bloomfield <jon.bloomfield@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_pm.c

index 31c92f86e43ddd775fb3b51c76af943b323cab79..cd504bc31e7413303a52f95955834eb9b7622a27 100644 (file)
@@ -5939,6 +5939,10 @@ enum {
 #define SKL_CSR_DC5_DC6_COUNT  _MMIO(0x8002C)
 #define BXT_CSR_DC3_DC5_COUNT  _MMIO(0x80038)
 
+/* Display Internal Timeout Register */
+#define RM_TIMEOUT             _MMIO(0x42060)
+#define  MMIO_TIMEOUT_US(us)   ((us) << 0)
+
 /* interrupts */
 #define DE_MASTER_IRQ_CONTROL   (1 << 31)
 #define DE_SPRITEB_FLIP_DONE    (1 << 29)
index 05427d2924574fd23d18f7167f1ae1a3846fd332..39147d40dcc068458ae61deead8dd2080fef47af 100644 (file)
@@ -105,6 +105,13 @@ static void bxt_init_clock_gating(struct drm_device *dev)
        if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER))
                I915_WRITE(GEN9_CLKGATE_DIS_0, I915_READ(GEN9_CLKGATE_DIS_0) |
                           PWM1_GATING_DIS | PWM2_GATING_DIS);
+       /*
+        * Lower the display internal timeout.
+        * This is needed to avoid any hard hangs when DSI port PLL
+        * is off and a MMIO access is attempted by any privilege
+        * application, using batch buffers or any other means.
+        */
+       I915_WRITE(RM_TIMEOUT, MMIO_TIMEOUT_US(950));
 }
 
 static void i915_pineview_get_mem_freq(struct drm_device *dev)