فهرست منبع

disp: msm: sde: add sde data to va minidumps

VA minidumps supports to add any allocated variable or data to
minidumps. Add panic notifier and wrapper function to add
sde data to minidump va. Add event log, register log, register dumps,
debug bus and different sde variables and states info to minidump.

Change-Id: If54da0b7067df17877e4da645d82f1705baa3f6d
Signed-off-by: Andhavarapu Karthik <[email protected]>
Andhavarapu Karthik 4 سال پیش
والد
کامیت
76d171e611

+ 23 - 0
msm/sde/sde_encoder.c

@@ -5679,3 +5679,26 @@ bool sde_encoder_needs_dsc_disable(struct drm_encoder *drm_enc)
 	conn_state = to_sde_connector_state(conn->state);
 	return TOPOLOGY_DSC_MODE(conn_state->old_topology_name);
 }
+
+void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc)
+{
+	struct sde_encoder_virt *sde_enc;
+	struct sde_encoder_phys *phys_enc;
+	u32 i;
+
+	sde_enc = to_sde_encoder_virt(drm_enc);
+	for( i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
+	{
+		phys_enc = sde_enc->phys_encs[i];
+		if(phys_enc && phys_enc->ops.add_to_minidump)
+			phys_enc->ops.add_to_minidump(phys_enc);
+
+		phys_enc = sde_enc->phys_cmd_encs[i];
+		if(phys_enc && phys_enc->ops.add_to_minidump)
+			phys_enc->ops.add_to_minidump(phys_enc);
+
+		phys_enc = sde_enc->phys_vid_encs[i];
+		if(phys_enc && phys_enc->ops.add_to_minidump)
+			phys_enc->ops.add_to_minidump(phys_enc);
+	}
+}

+ 2 - 0
msm/sde/sde_encoder.h

@@ -642,4 +642,6 @@ static inline bool sde_encoder_is_widebus_enabled(struct drm_encoder *drm_enc)
 	sde_enc = to_sde_encoder_virt(drm_enc);
 	return sde_enc->mode_info.wide_bus_en;
 }
+
+void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc);
 #endif /* __SDE_ENCODER_H__ */

+ 2 - 0
msm/sde/sde_encoder_phys.h

@@ -134,6 +134,7 @@ struct sde_encoder_virt_ops {
  * @setup_vsync_source:		Configure vsync source selection for cmd mode.
  * @get_underrun_line_count:	Obtain and log current internal vertical line
  *                              count and underrun line count
+ * @add_to_minidump:		Add this phys_enc data to minidumps
  */
 
 struct sde_encoder_phys_ops {
@@ -186,6 +187,7 @@ struct sde_encoder_phys_ops {
 	void (*setup_vsync_source)(struct sde_encoder_phys *phys, u32 vsync_source,
 			struct msm_display_info *disp_info);
 	u32 (*get_underrun_line_count)(struct sde_encoder_phys *phys);
+	void (*add_to_minidump)(struct sde_encoder_phys *phys);
 };
 
 /**

+ 9 - 0
msm/sde/sde_encoder_phys_cmd.c

@@ -1872,6 +1872,14 @@ static void sde_encoder_phys_cmd_setup_vsync_source(struct sde_encoder_phys *phy
 				vsync_source);
 }
 
+void sde_encoder_phys_cmd_add_enc_to_minidump(struct sde_encoder_phys *phys_enc)
+{
+	struct sde_encoder_phys_cmd *cmd_enc;
+	cmd_enc =  to_sde_encoder_phys_cmd(phys_enc);
+
+	sde_mini_dump_add_va_region("sde_enc_phys_cmd", sizeof(*cmd_enc), cmd_enc);
+}
+
 static void sde_encoder_phys_cmd_init_ops(struct sde_encoder_phys_ops *ops)
 {
 	ops->prepare_commit = sde_encoder_phys_cmd_prepare_commit;
@@ -1903,6 +1911,7 @@ static void sde_encoder_phys_cmd_init_ops(struct sde_encoder_phys_ops *ops)
 	ops->setup_vsync_source = sde_encoder_phys_cmd_setup_vsync_source;
 	ops->setup_misr = sde_encoder_helper_setup_misr;
 	ops->collect_misr = sde_encoder_helper_collect_misr;
+	ops->add_to_minidump = sde_encoder_phys_cmd_add_enc_to_minidump;
 }
 
 static inline bool sde_encoder_phys_cmd_intf_te_supported(

+ 9 - 0
msm/sde/sde_encoder_phys_vid.c

@@ -1289,6 +1289,14 @@ static int sde_encoder_phys_vid_wait_for_active(
 	return -EINVAL;
 }
 
+void sde_encoder_phys_vid_add_enc_to_minidump(struct sde_encoder_phys *phys_enc)
+{
+	struct sde_encoder_phys_vid *vid_enc;
+	vid_enc =  to_sde_encoder_phys_vid(phys_enc);
+
+	sde_mini_dump_add_va_region("sde_enc_phys_vid", sizeof(*vid_enc), vid_enc);
+}
+
 static void sde_encoder_phys_vid_init_ops(struct sde_encoder_phys_ops *ops)
 {
 	ops->is_master = sde_encoder_phys_vid_is_master;
@@ -1317,6 +1325,7 @@ static void sde_encoder_phys_vid_init_ops(struct sde_encoder_phys_ops *ops)
 	ops->prepare_commit = sde_encoder_phys_vid_prepare_for_commit;
 	ops->get_underrun_line_count =
 		sde_encoder_phys_vid_get_underrun_line_count;
+	ops->add_to_minidump = sde_encoder_phys_vid_add_enc_to_minidump;
 }
 
 struct sde_encoder_phys *sde_encoder_phys_vid_init(

+ 9 - 0
msm/sde/sde_encoder_phys_wb.c

@@ -1933,6 +1933,14 @@ static void sde_encoder_phys_wb_destroy(struct sde_encoder_phys *phys_enc)
 	kfree(wb_enc);
 }
 
+void sde_encoder_phys_wb_add_enc_to_minidump(struct sde_encoder_phys *phys_enc)
+{
+	struct sde_encoder_phys_wb *wb_enc;
+	wb_enc =  to_sde_encoder_phys_wb(phys_enc);
+
+	sde_mini_dump_add_va_region("sde_enc_phys_wb", sizeof(*wb_enc), wb_enc);
+}
+
 /**
  * sde_encoder_phys_wb_init_ops - initialize writeback operations
  * @ops:	Pointer to encoder operation table
@@ -1955,6 +1963,7 @@ static void sde_encoder_phys_wb_init_ops(struct sde_encoder_phys_ops *ops)
 	ops->trigger_start = sde_encoder_helper_trigger_start;
 	ops->hw_reset = sde_encoder_helper_hw_reset;
 	ops->irq_control = sde_encoder_phys_wb_irq_ctrl;
+	ops->add_to_minidump = sde_encoder_phys_wb_add_enc_to_minidump;
 }
 
 /**

+ 34 - 0
msm/sde/sde_kms.c

@@ -4862,3 +4862,37 @@ int sde_kms_handle_recovery(struct drm_encoder *encoder)
 	SDE_EVT32(DRMID(encoder), MSM_ENC_ACTIVE_REGION);
 	return sde_encoder_wait_for_event(encoder, MSM_ENC_ACTIVE_REGION);
 }
+
+void sde_kms_add_data_to_minidump_va(struct sde_kms *sde_kms)
+{
+	struct msm_drm_private *priv;
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_state *cstate;
+	struct sde_connector *sde_conn;
+	struct sde_connector_state *conn_state;
+	u32 i;
+
+	priv = sde_kms->dev->dev_private;
+
+	sde_mini_dump_add_va_region("sde_kms", sizeof(*sde_kms), sde_kms);
+
+	for (i = 0; i < priv->num_crtcs; i++) {
+		sde_crtc = to_sde_crtc(priv->crtcs[i]);
+		cstate = to_sde_crtc_state(priv->crtcs[i]->state);
+		sde_mini_dump_add_va_region("sde_crtc", sizeof(*sde_crtc), sde_crtc);
+		sde_mini_dump_add_va_region("crtc_state", sizeof(*cstate), cstate);
+	}
+
+	for (i = 0; i < priv->num_planes; i++)
+		sde_plane_add_data_to_minidump_va(priv->planes[i]);
+
+	for (i = 0; i < priv->num_encoders; i++)
+		sde_encoder_add_data_to_minidump_va(priv->encoders[i]);
+
+	for (i = 0; i < priv->num_connectors; i++) {
+		sde_conn = to_sde_connector(priv->connectors[i]);
+		conn_state = to_sde_connector_state(priv->connectors[i]->state);
+		sde_mini_dump_add_va_region("sde_conn", sizeof(*sde_conn), sde_conn);
+		sde_mini_dump_add_va_region("conn_state", sizeof(*conn_state), conn_state);
+	}
+}

+ 2 - 0
msm/sde/sde_kms.h

@@ -765,4 +765,6 @@ int sde_kms_vm_trusted_prepare_commit(struct sde_kms *sde_kms,
  */
 int sde_kms_vm_primary_prepare_commit(struct sde_kms *sde_kms,
 					   struct drm_atomic_state *state);
+
+void sde_kms_add_data_to_minidump_va(struct sde_kms *sde_kms);
 #endif /* __sde_kms_H__ */

+ 11 - 0
msm/sde/sde_plane.c

@@ -4845,3 +4845,14 @@ clean_plane:
 exit:
 	return ERR_PTR(ret);
 }
+
+void sde_plane_add_data_to_minidump_va(struct drm_plane *plane)
+{
+	struct sde_plane *sde_plane;
+	struct sde_plane_state *pstate;
+
+	sde_plane = to_sde_plane(plane);
+	pstate = to_sde_plane_state(plane->state);
+	sde_mini_dump_add_va_region("sde_plane", sizeof(*sde_plane), sde_plane);
+	sde_mini_dump_add_va_region("plane_state", sizeof(*pstate), pstate);
+}

+ 1 - 0
msm/sde/sde_plane.h

@@ -358,4 +358,5 @@ bool sde_plane_is_cache_required(struct drm_plane *plane,
 void sde_plane_static_img_control(struct drm_plane *plane,
 		enum sde_crtc_cache_state state);
 
+void sde_plane_add_data_to_minidump_va(struct drm_plane *plane);
 #endif /* _SDE_PLANE_H_ */

+ 91 - 0
msm/sde_dbg.c

@@ -18,6 +18,7 @@
 
 #include "sde_dbg.h"
 #include "sde/sde_hw_catalog.h"
+#include "sde/sde_kms.h"
 
 #define SDE_DBG_BASE_MAX		10
 
@@ -577,6 +578,95 @@ static u32 _sde_dbg_get_reg_dump_size(void)
 	return size;
 }
 
+#if IS_ENABLED(CONFIG_QCOM_VA_MINIDUMP)
+static void sde_dbg_add_dbg_buses_to_minidump_va(void)
+{
+	static struct sde_dbg_base *dbg = &sde_dbg_base;
+
+	sde_mini_dump_add_va_region("sde_dbgbus", dbg->dbgbus_sde.cmn.content_size*sizeof(u32),
+			dbg->dbgbus_sde.cmn.dumped_content);
+
+	sde_mini_dump_add_va_region("vbif_dbgbus", dbg->dbgbus_vbif_rt.cmn.content_size*sizeof(u32),
+			dbg->dbgbus_vbif_rt.cmn.dumped_content);
+
+	sde_mini_dump_add_va_region("dsi_dbgbus", dbg->dbgbus_dsi.cmn.content_size*sizeof(u32),
+			dbg->dbgbus_dsi.cmn.dumped_content);
+
+	sde_mini_dump_add_va_region("lutdma_dbgbus",
+			dbg->dbgbus_lutdma.cmn.content_size*sizeof(u32),
+			dbg->dbgbus_lutdma.cmn.dumped_content);
+
+	sde_mini_dump_add_va_region("rsc_dbgbus", dbg->dbgbus_rsc.cmn.content_size*sizeof(u32),
+			dbg->dbgbus_rsc.cmn.dumped_content);
+
+	sde_mini_dump_add_va_region("dp_dbgbus", dbg->dbgbus_dp.cmn.content_size*sizeof(u32),
+			dbg->dbgbus_dp.cmn.dumped_content);
+}
+
+static int sde_md_notify_handler(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	struct device *dev = sde_dbg_base.dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *ddev = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = ddev->dev_private;
+	struct sde_kms *sde_kms = to_sde_kms(priv->kms);
+	struct sde_dbg_base *dbg_base = &sde_dbg_base;
+	u32 reg_dump_size = _sde_dbg_get_reg_dump_size();
+
+	sde_mini_dump_add_va_region("msm_drm_priv", sizeof(*priv), priv);
+	sde_mini_dump_add_va_region("sde_evtlog",
+			sizeof(*sde_dbg_base_evtlog), sde_dbg_base_evtlog);
+	sde_mini_dump_add_va_region("sde_reglog",
+			sizeof(*sde_dbg_base_reglog), sde_dbg_base_reglog);
+
+	sde_mini_dump_add_va_region("sde_reg_dump", reg_dump_size, dbg_base->reg_dump_base);
+
+	sde_dbg_add_dbg_buses_to_minidump_va();
+	sde_kms_add_data_to_minidump_va(sde_kms);
+
+	return 0;
+}
+
+static struct notifier_block sde_md_notify_blk = {
+	.notifier_call = sde_md_notify_handler,
+	.priority = INT_MAX,
+};
+
+static int sde_register_md_panic_notifer()
+{
+	qcom_va_md_register("display", &sde_md_notify_blk);
+	return 0;
+}
+
+void sde_mini_dump_add_va_region(const char *name, u32 size, void *virt_addr)
+{
+	struct va_md_entry md_entry;
+	int ret;
+
+	strlcpy(md_entry.owner, name, sizeof(md_entry.owner));
+	md_entry.vaddr = (uintptr_t)virt_addr;
+	md_entry.size = size;
+
+	ret = qcom_va_md_add_region(&md_entry);
+	if (ret < 0)
+		SDE_ERROR("va minudmp add entry failed for %s, returned %d\n",
+			name, ret);
+
+	return;
+}
+#else
+static int sde_register_md_panic_notifer()
+{
+	return 0;
+}
+
+void sde_mini_dump_add_va_region(const char *name, u32 size, void *virt_addr)
+{
+	return;
+}
+#endif
+
 static int _sde_dump_reg_range_cmp(void *priv, struct list_head *a,
 		struct list_head *b)
 {
@@ -2309,6 +2399,7 @@ int sde_dbg_init(struct device *dev)
 	sde_dbg_base.enable_dbgbus_dump = SDE_DBG_DEFAULT_DUMP_MODE;
 	sde_dbg_base.dump_blk_mask = SDE_DBG_BUILT_IN_ALL;
 	memset(&sde_dbg_base.regbuf, 0, sizeof(sde_dbg_base.regbuf));
+	sde_register_md_panic_notifer();
 
 	pr_info("evtlog_status: enable:%d, panic:%d, dump:%d\n",
 		sde_dbg_base.evtlog->enable, sde_dbg_base.panic_on_err,

+ 10 - 0
msm/sde_dbg.h

@@ -9,6 +9,7 @@
 #include <stdarg.h>
 #include <linux/debugfs.h>
 #include <linux/list.h>
+#include <soc/qcom/minidump.h>
 
 /* select an uncommon hex value for the limiter */
 #define SDE_EVTLOG_DATA_LIMITER	(0xC0DEBEEF)
@@ -270,6 +271,15 @@ extern struct sde_dbg_reglog *sde_dbg_base_reglog;
 #define SDE_DBG_CTRL(...) sde_dbg_ctrl(__func__, ##__VA_ARGS__, \
 		SDE_DBG_DUMP_DATA_LIMITER)
 
+/**
+ * sde_mini_dump_add_va_region - add required va memory region to minidump.
+ * @size:	size of the memory region to be added
+ * @name:	minidump partition name
+ * @virt_addr:	pointer to memory region
+ * Returns:	none
+ */
+void sde_mini_dump_add_va_region(const char *name, u32 size, void *virt_addr);
+
 /**
  * sde_evtlog_init - allocate a new event log object
  * Returns:	evtlog or -ERROR