[PATCH] FIXME: drm/i915/cx0: Check and increase timeout threshold

Mika Kahola mika.kahola at intel.com
Wed Aug 16 11:37:50 UTC 2023


From: Gustavo Sousa <gustavo.sousa at intel.com>

When a timeout happens in the bus, bump the threshold on the message bus
timer in an attempt to allow progress on the bus.

FIXME:
    Two comments here:

    1) Timeouts have been seen in one machine when reading SRAM
       registers. While this change "fixes" the timeout issues, further
       investigation is necessary to understand what is causing the
       timeout.

    2) Is this something we would want to keep in the code regardless of
       the outcome of (1)? Could it be useful for potential future
       timeout issues?

v2: Rebase

BSpec: 65156
Signed-off-by: Gustavo Sousa <gustavo.sousa at intel.com>
Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
Signed-off-by: Mika Kahola <mika.kahola at intel.com>
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 41 +++++++++++++++++++
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 13 ++++++
 2 files changed, 54 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 1b00ef2c6185..0cb310755c9a 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/log2.h>
+#include <linux/minmax.h>
 #include <linux/math64.h>
 #include "i915_reg.h"
 #include "intel_cx0_phy.h"
@@ -29,6 +30,8 @@
 #define INTEL_CX0_LANE1		BIT(1)
 #define INTEL_CX0_BOTH_LANES	(INTEL_CX0_LANE1 | INTEL_CX0_LANE0)
 
+#define INTEL_CX0_MSGBUS_TIMER_VAL_MAX	0x200
+
 bool intel_is_c10phy(struct drm_i915_private *i915, enum phy phy)
 {
 	if (IS_METEORLAKE(i915) && (phy < PHY_C))
@@ -103,6 +106,43 @@ static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, i
 	intel_clear_response_ready_flag(i915, port, lane);
 }
 
+/*
+ * Check if there was a timeout detected by the hardware in the message bus
+ * and bump the threshold if so.
+ */
+static void intel_cx0_bus_check_and_bump_timer(struct drm_i915_private *i915,
+					       enum port port, int lane)
+{
+	enum phy phy = intel_port_to_phy(i915, port);
+	i915_reg_t reg;
+	u32 val;
+	u32 timer_val;
+
+	reg = XELPDP_PORT_MSGBUS_TIMER(port, lane);
+	val = intel_de_read(i915, reg);
+
+	if (!(val & XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT)) {
+		drm_warn(&i915->drm,
+			 "PHY %c lane %d: hardware did not detect a timeout\n",
+			 phy_name(phy), lane);
+		return;
+	}
+
+	timer_val = REG_FIELD_GET(XELPDP_PORT_MSGBUS_TIMER_VAL_MASK, val);
+
+	if (timer_val == INTEL_CX0_MSGBUS_TIMER_VAL_MAX)
+		return;
+
+	timer_val = min(2 * timer_val, (u32)INTEL_CX0_MSGBUS_TIMER_VAL_MAX);
+	val &= ~XELPDP_PORT_MSGBUS_TIMER_VAL_MASK;
+	val |= REG_FIELD_PREP(XELPDP_PORT_MSGBUS_TIMER_VAL_MASK, timer_val);
+
+	drm_dbg_kms(&i915->drm,
+		    "PHY %c lane %d: increasing msgbus timer threshold to %#x\n",
+		    phy_name(phy), lane, timer_val);
+	intel_de_write(i915, reg, val);
+}
+
 static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port,
 				  int command, int lane, u32 *val)
 {
@@ -116,6 +156,7 @@ static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port,
 					 XELPDP_MSGBUS_TIMEOUT_SLOW, val)) {
 		drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for message ACK. Status: 0x%x\n",
 			    phy_name(phy), *val);
+		intel_cx0_bus_check_and_bump_timer(i915, port, lane);
 		intel_cx0_bus_reset(i915, port, lane);
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index cb5d1be2ba19..e88743ca62e6 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -110,6 +110,19 @@
 #define   CX0_P4PG_STATE_DISABLE			0xC
 #define   CX0_P2_STATE_RESET				0x2
 
+#define _XELPDP_PORT_MSGBUS_TIMER_LN0_A			0x640d8
+#define _XELPDP_PORT_MSGBUS_TIMER_LN0_B			0x641d8
+#define _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC1		0x16f258
+#define _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC2		0x16f458
+#define XELPDP_PORT_MSGBUS_TIMER(idx, lane)		_MMIO(_PICK_EVEN_2RANGES(idx, PORT_TC1, \
+										 _XELPDP_PORT_MSGBUS_TIMER_LN0_A, \
+										 _XELPDP_PORT_MSGBUS_TIMER_LN0_B, \
+										 _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC1, \
+										 _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC2) + (lane) * 4)
+#define   XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT		REG_BIT(31)
+#define   XELPDP_PORT_MSGBUS_TIMER_VAL_MASK		REG_GENMASK(23, 0)
+#define   XELPDP_PORT_MSGBUS_TIMER_VAL(val)		REG_FIELD_PREP(XELPDP_PORT_MSGBUS_TIMER_VAL_MASK, val)
+
 #define _XELPDP_PORT_CLOCK_CTL_A			0x640E0
 #define _XELPDP_PORT_CLOCK_CTL_B			0x641E0
 #define _XELPDP_PORT_CLOCK_CTL_USBC1			0x16F260
-- 
2.34.1



More information about the Intel-gfx-trybot mailing list