瀏覽代碼

disp: msm: dsi: Panic on getting continuous ESD check failures

During stability stress testing, there are many instances where
the panel is unreachable which results in the ESD check mechanism
failing continuously with PANEL_DEAD events. There are two possible
reasons. Either the device is bad or DSI controller is hung. As of
today, logs/xlog is flooded and info on root cause is missed in the
logs. To catch the root cause for such issues, this patch induces
forced crash when there are five consecutive ESD check failures.

Change-Id: Id0a5762ac977f8a209af651f65cbe9da199cb8d0
Signed-off-by: Lipsa Rout <[email protected]>
Lipsa Rout 4 年之前
父節點
當前提交
93fa9bdf60
共有 2 個文件被更改,包括 32 次插入1 次删除
  1. 3 0
      msm/dsi/dsi_display.h
  2. 29 1
      msm/sde/sde_connector.c

+ 3 - 0
msm/dsi/dsi_display.h

@@ -184,6 +184,7 @@ struct dsi_display_ext_bridge {
  * @misr_frame_count  Number of frames to accumulate the MISR value
  * @esd_trigger       field indicating ESD trigger through debugfs
  * @poms_te_work      POMS delayed work for disabling panel TE
+ * @esd_fail_count    Count of continuous ESD check failures
  * @te_source         vsync source pin information
  * @clk_gating_config Clocks for which clock gating needs to be enabled
  * @queue_cmd_waits   Indicates if wait for dma commands done has to be queued.
@@ -277,6 +278,8 @@ struct dsi_display {
 
 	struct dsi_display_boot_param *boot_disp;
 
+	u32 esd_fail_count;
+
 	u32 te_source;
 	u32 clk_gating_config;
 	bool queue_cmd_waits;

+ 29 - 1
msm/sde/sde_connector.c

@@ -2380,6 +2380,8 @@ static void _sde_connector_report_panel_dead(struct sde_connector *conn,
 	bool skip_pre_kickoff)
 {
 	struct drm_event event;
+	struct dsi_display *display;
+	u32 const max_conseq_esd_fail_count = 5;
 
 	if (!conn)
 		return;
@@ -2402,6 +2404,17 @@ static void _sde_connector_report_panel_dead(struct sde_connector *conn,
 	SDE_EVT32(SDE_EVTLOG_ERROR);
 	SDE_ERROR("esd check failed report PANEL_DEAD conn_id: %d enc_id: %d\n",
 			conn->base.base.id, conn->encoder->base.id);
+
+	if (conn->connector_type != DRM_MODE_CONNECTOR_DSI)
+		return;
+
+	display = (struct dsi_display *)conn->display;
+	display->esd_fail_count++;
+	if (display->esd_fail_count == max_conseq_esd_fail_count) {
+		SDE_ERROR("Triggered reset on multiple PANEL_DEAD instances\n");
+		SDE_DBG_DUMP("all", "dbg_bus", "dsi_dbg_bus",
+			"vbif_dbg_bus", "panic");
+	}
 }
 
 int sde_connector_esd_status(struct drm_connector *conn)
@@ -2439,8 +2452,16 @@ int sde_connector_esd_status(struct drm_connector *conn)
 		SDE_DEBUG("Successfully received TE from panel\n");
 		ret = 0;
 	}
-	SDE_EVT32(ret);
 
+	if (sde_conn->connector_type == DRM_MODE_CONNECTOR_DSI) {
+		/* Reset esd_fail_count on recovery */
+		if (!ret)
+			display->esd_fail_count = 0;
+		SDE_EVT32(ret, display->esd_fail_count);
+		return ret;
+	}
+
+	SDE_EVT32(ret);
 	return ret;
 }
 
@@ -2449,6 +2470,7 @@ static void sde_connector_check_status_work(struct work_struct *work)
 	struct sde_connector *conn;
 	int rc = 0;
 	struct device *dev;
+	struct dsi_display *display;
 
 	conn = container_of(to_delayed_work(work),
 			struct sde_connector, status_work);
@@ -2481,6 +2503,12 @@ static void sde_connector_check_status_work(struct work_struct *work)
 			conn->esd_status_interval : STATUS_CHECK_INTERVAL_MS;
 		schedule_delayed_work(&conn->status_work,
 			msecs_to_jiffies(interval));
+
+		/* Successful ESD check */
+		if (conn->connector_type == DRM_MODE_CONNECTOR_DSI) {
+			display = conn->display;
+			display->esd_fail_count = 0;
+		}
 		return;
 	}