From 76d171e61195a11bf8efc70e4972d17334a40c82 Mon Sep 17 00:00:00 2001 From: Andhavarapu Karthik Date: Mon, 21 Jun 2021 10:44:50 +0530 Subject: [PATCH] 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 --- msm/sde/sde_encoder.c | 23 +++++++++ msm/sde/sde_encoder.h | 2 + msm/sde/sde_encoder_phys.h | 2 + msm/sde/sde_encoder_phys_cmd.c | 9 ++++ msm/sde/sde_encoder_phys_vid.c | 9 ++++ msm/sde/sde_encoder_phys_wb.c | 9 ++++ msm/sde/sde_kms.c | 34 +++++++++++++ msm/sde/sde_kms.h | 2 + msm/sde/sde_plane.c | 11 ++++ msm/sde/sde_plane.h | 1 + msm/sde_dbg.c | 91 ++++++++++++++++++++++++++++++++++ msm/sde_dbg.h | 10 ++++ 12 files changed, 203 insertions(+) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index db4e47cdd7..1620e52fb5 100644 --- a/msm/sde/sde_encoder.c +++ b/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); + } +} diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index afc68f632e..5765ea5153 100644 --- a/msm/sde/sde_encoder.h +++ b/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__ */ diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 291fe0254a..b7f8024357 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/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); }; /** diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index ff889745bf..b9edcc4e27 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/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( diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index f4a5097a80..42cfe5dc29 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/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( diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index ba72738f4f..0340bbace5 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/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; } /** diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index a6020506c0..705aa1c770 100644 --- a/msm/sde/sde_kms.c +++ b/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); + } +} diff --git a/msm/sde/sde_kms.h b/msm/sde/sde_kms.h index fe78d4c727..6181357298 100644 --- a/msm/sde/sde_kms.h +++ b/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__ */ diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index d1c0af05c8..53b7b04b71 100644 --- a/msm/sde/sde_plane.c +++ b/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); +} diff --git a/msm/sde/sde_plane.h b/msm/sde/sde_plane.h index a0a22afe45..56617b9a25 100644 --- a/msm/sde/sde_plane.h +++ b/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_ */ diff --git a/msm/sde_dbg.c b/msm/sde_dbg.c index db605c265c..6605e8572a 100755 --- a/msm/sde_dbg.c +++ b/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, diff --git a/msm/sde_dbg.h b/msm/sde_dbg.h index fe68f49920..b5fae91cc8 100644 --- a/msm/sde_dbg.h +++ b/msm/sde_dbg.h @@ -9,6 +9,7 @@ #include #include #include +#include /* 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