소스 검색

disp: msm: sde: dump clock state before entering suspend

Add debug capability to dump clocks before entering pm suspend.
This will help debug invalid register access when clocks are off
during adversarial test cases.

Change-Id: I80d19b751a3b9a1de0cc64699a21a1852d614ced
Signed-off-by: Amine Najahi <[email protected]>
Amine Najahi 5 년 전
부모
커밋
8479ed7278
6개의 변경된 파일101개의 추가작업 그리고 0개의 파일을 삭제
  1. 7 0
      msm/dsi/dsi_clk.h
  2. 21 0
      msm/dsi/dsi_clk_manager.c
  3. 38 0
      msm/dsi/dsi_display.c
  4. 8 0
      msm/dsi/dsi_display.h
  5. 26 0
      msm/sde/sde_kms.c
  6. 1 0
      msm/sde/sde_kms.h

+ 7 - 0
msm/dsi/dsi_clk.h

@@ -322,4 +322,11 @@ int dsi_clk_prepare_enable(struct dsi_clk_link_set *clk);
  * @clk:       list of src clocks.
  */
 void dsi_clk_disable_unprepare(struct dsi_clk_link_set *clk);
+
+/**
+ * dsi_display_dump_clk_handle_state() - dump client clock state
+ * @client:       DSI clock client pointer.
+ */
+int dsi_display_dump_clk_handle_state(void *client);
+
 #endif /* _DSI_CLK_H_ */

+ 21 - 0
msm/dsi/dsi_clk_manager.c

@@ -1396,6 +1396,27 @@ void dsi_display_clk_mngr_update_splash_status(void *clk_mgr, bool status)
 	mngr->is_cont_splash_enabled = status;
 }
 
+int dsi_display_dump_clk_handle_state(void *client)
+{
+	struct dsi_clk_mngr *mngr;
+	struct dsi_clk_client_info *c = client;
+
+	if (!c || !c->mngr) {
+		DSI_ERR("Invalid params\n");
+		return -EINVAL;
+	}
+
+	mngr = c->mngr;
+	mutex_lock(&mngr->clk_mutex);
+	DSI_INFO("[%s]%s: Core (ref=%d, state=%d), Link (ref=%d, state=%d)\n",
+			mngr->name, c->name, c->core_refcount,
+			c->core_clk_state, c->link_refcount,
+			c->link_clk_state);
+	mutex_unlock(&mngr->clk_mutex);
+
+	return 0;
+}
+
 void *dsi_display_clk_mngr_register(struct dsi_clk_info *info)
 {
 	struct dsi_clk_mngr *mngr;

+ 38 - 0
msm/dsi/dsi_display.c

@@ -7799,6 +7799,44 @@ int dsi_display_update_pps(char *pps_cmd, void *disp)
 	return 0;
 }
 
+int dsi_display_dump_clks_state(struct dsi_display *display)
+{
+	int rc = 0;
+
+	if (!display) {
+		DSI_ERR("invalid display argument\n");
+		return -EINVAL;
+	}
+
+	if (!display->clk_mngr) {
+		DSI_ERR("invalid clk manager\n");
+		return -EINVAL;
+	}
+
+	if (!display->dsi_clk_handle || !display->mdp_clk_handle) {
+		DSI_ERR("invalid clk handles\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&display->display_lock);
+	rc = dsi_display_dump_clk_handle_state(display->dsi_clk_handle);
+	if (rc) {
+		DSI_ERR("failed to dump dsi clock state\n");
+		goto end;
+	}
+
+	rc = dsi_display_dump_clk_handle_state(display->mdp_clk_handle);
+	if (rc) {
+		DSI_ERR("failed to dump mdp clock state\n");
+		goto end;
+	}
+
+end:
+	mutex_unlock(&display->display_lock);
+
+	return rc;
+}
+
 int dsi_display_unprepare(struct dsi_display *display)
 {
 	int rc = 0, i;

+ 8 - 0
msm/dsi/dsi_display.h

@@ -732,4 +732,12 @@ int dsi_display_cont_splash_config(void *display);
 int dsi_display_get_panel_vfp(void *display,
 	int h_active, int v_active);
 
+/**
+ * dsi_display_dump_clks_state() - dump clocks state to console
+ * @display:         Handle to display
+ *
+ * Return: Zero on Success
+ */
+int dsi_display_dump_clks_state(struct dsi_display *display);
+
 #endif /* _DSI_DISPLAY_H_ */

+ 26 - 0
msm/sde/sde_kms.c

@@ -154,6 +154,9 @@ static int _sde_debugfs_init(struct sde_kms *sde_kms)
 		debugfs_create_u32("qdss", 0600, debugfs_root,
 				(u32 *)&sde_kms->qdss_enabled);
 
+	debugfs_create_u32("pm_suspend_clk_dump", 0600, debugfs_root,
+			(u32 *)&sde_kms->pm_suspend_clk_dump);
+
 	return 0;
 }
 
@@ -165,6 +168,20 @@ static void _sde_debugfs_destroy(struct sde_kms *sde_kms)
 		sde_debugfs_core_irq_destroy(sde_kms);
 	}
 }
+
+static int _sde_kms_dump_clks_state(struct sde_kms *sde_kms)
+{
+	int i;
+	struct device *dev = sde_kms->dev->dev;
+
+	SDE_INFO("runtime PM suspended:%d", pm_runtime_suspended(dev));
+
+	for (i = 0; i < sde_kms->dsi_display_count; i++)
+		dsi_display_dump_clks_state(sde_kms->dsi_displays[i]);
+
+	return 0;
+}
+
 #else
 static int _sde_debugfs_init(struct sde_kms *sde_kms)
 {
@@ -174,6 +191,11 @@ static int _sde_debugfs_init(struct sde_kms *sde_kms)
 static void _sde_debugfs_destroy(struct sde_kms *sde_kms)
 {
 }
+
+static int _sde_kms_dump_clks_state(struct sde_kms *sde_kms)
+{
+	return 0;
+}
 #endif
 
 static int sde_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
@@ -2827,6 +2849,10 @@ unlock:
 	pm_runtime_put_sync(dev);
 	pm_runtime_get_noresume(dev);
 
+	/* dump clock state before entering suspend */
+	if (sde_kms->pm_suspend_clk_dump)
+		_sde_kms_dump_clks_state(sde_kms);
+
 	return ret;
 }
 

+ 1 - 0
msm/sde/sde_kms.h

@@ -306,6 +306,7 @@ struct sde_kms {
 
 	bool first_kickoff;
 	bool qdss_enabled;
+	bool pm_suspend_clk_dump;
 
 	cpumask_t irq_cpu_mask;
 	struct dev_pm_qos_request pm_qos_irq_req[NR_CPUS];