diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2020-12-29 08:10:30 -0800 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2020-12-29 08:10:30 -0800 |
commit | a9b2969cdfba576b80f829f614b9e6776d60c0b8 (patch) | |
tree | 9f83f42289dc1f049d19b57625886c8f0323ffe3 | |
parent | db31f54fab7d6eb09a591137f6a03f984082f71d (diff) | |
parent | a9dcc6e2b0be1866f0ae32aace73953108122194 (diff) | |
download | display-drivers-a9b2969cdfba576b80f829f614b9e6776d60c0b8.tar.gz |
Merge a9dcc6e2b0be1866f0ae32aace73953108122194 on remote branch
Change-Id: I8c9a0d1591fe29934493255dc3e6ccbfea2b9a45
-rw-r--r-- | msm/Makefile | 3 | ||||
-rw-r--r-- | msm/dp/dp_debug.c | 4 | ||||
-rw-r--r-- | msm/dp/dp_panel.c | 23 | ||||
-rw-r--r-- | msm/dp/dp_panel.h | 2 | ||||
-rw-r--r-- | msm/dsi/dsi_ctrl.c | 9 | ||||
-rw-r--r-- | msm/sde/sde_crtc.c | 106 | ||||
-rw-r--r-- | msm/sde/sde_crtc.h | 18 | ||||
-rw-r--r-- | msm/sde/sde_hw_util.c | 3 | ||||
-rw-r--r-- | msm/sde/sde_rm.c | 4 | ||||
-rw-r--r-- | msm/sde_dbg.c | 26 | ||||
-rw-r--r-- | msm/sde_dbg.h | 194 | ||||
-rw-r--r-- | msm/sde_dbg_evtlog.c | 48 | ||||
-rw-r--r-- | msm/sde_io_util.c | 3 |
13 files changed, 318 insertions, 125 deletions
diff --git a/msm/Makefile b/msm/Makefile index b7ac4dfb..51b0edbf 100644 --- a/msm/Makefile +++ b/msm/Makefile @@ -68,8 +68,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \ sde/sde_hw_ds.o \ sde/sde_fence.o \ sde/sde_hw_qdss.o \ - -msm_drm-$(CONFIG_DEBUG_FS) += sde_dbg.o \ + sde_dbg.o \ sde_dbg_evtlog.o \ msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \ diff --git a/msm/dp/dp_debug.c b/msm/dp/dp_debug.c index 0459adce..6303c1cf 100644 --- a/msm/dp/dp_debug.c +++ b/msm/dp/dp_debug.c @@ -154,7 +154,7 @@ static ssize_t dp_debug_write_edid(struct file *file, edid = debug->edid; bail: kfree(buf); - debug->panel->set_edid(debug->panel, edid); + debug->panel->set_edid(debug->panel, edid, debug->edid_size); /* * print edid status as this code is executed @@ -1628,7 +1628,7 @@ static void dp_debug_set_sim_mode(struct dp_debug_private *debug, bool sim) debug->aux->set_sim_mode(debug->aux, false, NULL, NULL); debug->dp_debug.sim_mode = false; - debug->panel->set_edid(debug->panel, 0); + debug->panel->set_edid(debug->panel, 0, 0); if (debug->edid) { devm_kfree(debug->dev, debug->edid); debug->edid = NULL; diff --git a/msm/dp/dp_panel.c b/msm/dp/dp_panel.c index 74f915b5..1c01b0ee 100644 --- a/msm/dp/dp_panel.c +++ b/msm/dp/dp_panel.c @@ -7,6 +7,7 @@ #include <linux/unistd.h> #include <drm/drm_fixed.h> #include "dp_debug.h" +#include <drm/drm_edid.h> #define DP_KHZ_TO_HZ 1000 #define DP_PANEL_DEFAULT_BPP 24 @@ -1937,7 +1938,25 @@ static int dp_panel_set_default_link_params(struct dp_panel *dp_panel) return 0; } -static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid) +static bool dp_panel_validate_edid(struct edid *edid, size_t edid_size) +{ + if (!edid || (edid_size < EDID_LENGTH)) + return false; + + if (EDID_LENGTH * (edid->extensions + 1) > edid_size) { + DP_ERR("edid size does not match allocated.\n"); + return false; + } + + if (!drm_edid_is_valid(edid)) { + DP_ERR("invalid edid.\n"); + return false; + } + return true; +} + +static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid, + size_t edid_size) { struct dp_panel_private *panel; @@ -1948,7 +1967,7 @@ static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid) panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - if (edid) { + if (edid && dp_panel_validate_edid((struct edid *)edid, edid_size)) { dp_panel->edid_ctrl->edid = (struct edid *)edid; panel->custom_edid = true; } else { diff --git a/msm/dp/dp_panel.h b/msm/dp/dp_panel.h index dbc5ba98..36629c3c 100644 --- a/msm/dp/dp_panel.h +++ b/msm/dp/dp_panel.h @@ -146,7 +146,7 @@ struct dp_panel { int (*get_modes)(struct dp_panel *dp_panel, struct drm_connector *connector, struct dp_display_mode *mode); void (*handle_sink_request)(struct dp_panel *dp_panel); - int (*set_edid)(struct dp_panel *dp_panel, u8 *edid); + int (*set_edid)(struct dp_panel *dp_panel, u8 *edid, size_t edid_size); int (*set_dpcd)(struct dp_panel *dp_panel, u8 *dpcd); int (*setup_hdr)(struct dp_panel *dp_panel, struct drm_msm_ext_hdr_metadata *hdr_meta, diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index bf316d5d..c92bfbce 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -263,6 +263,13 @@ static int dsi_ctrl_debugfs_deinit(struct dsi_ctrl *dsi_ctrl) static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl, struct dentry *parent) { + char dbg_name[DSI_DEBUG_NAME_LEN]; + + snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_ctrl", + dsi_ctrl->cell_index); + sde_dbg_reg_register_base(dbg_name, + dsi_ctrl->hw.base, + msm_iomap_size(dsi_ctrl->pdev, "dsi_ctrl")); return 0; } static int dsi_ctrl_debugfs_deinit(struct dsi_ctrl *dsi_ctrl) @@ -2063,7 +2070,6 @@ static struct platform_driver dsi_ctrl_driver = { }, }; -#if defined(CONFIG_DEBUG_FS) void dsi_ctrl_debug_dump(u32 *entries, u32 size) { @@ -2085,7 +2091,6 @@ void dsi_ctrl_debug_dump(u32 *entries, u32 size) mutex_unlock(&dsi_ctrl_list_lock); } -#endif /** * dsi_ctrl_get() - get a dsi_ctrl handle from an of_node * @of_node: of_node of the DSI controller. diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 3a5988a5..696dbff2 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -1725,8 +1725,12 @@ int sde_crtc_state_find_plane_fb_modes(struct drm_crtc_state *state, static void _sde_drm_fb_sec_dir_trans( struct sde_kms_smmu_state_data *smmu_state, uint32_t secure_level, - struct sde_mdss_cfg *catalog, bool old_valid_fb, int *ops) + struct sde_mdss_cfg *catalog, bool old_valid_fb, int *ops, + struct drm_crtc_state *old_crtc_state) { + struct sde_crtc_state *old_cstate = to_sde_crtc_state(old_crtc_state); + int old_secure_session = old_cstate->secure_session; + /* secure display usecase */ if ((smmu_state->state == ATTACHED) && (secure_level == SDE_DRM_SEC_ONLY)) { @@ -1747,6 +1751,10 @@ static void _sde_drm_fb_sec_dir_trans( smmu_state->secure_level = secure_level; smmu_state->transition_type = PRE_COMMIT; *ops |= SDE_KMS_OPS_SECURE_STATE_CHANGE; + if (old_secure_session == + SDE_SECURE_VIDEO_SESSION) + *ops |= (SDE_KMS_OPS_WAIT_FOR_TX_DONE | + SDE_KMS_OPS_CLEANUP_PLANE_FB); } } @@ -1872,7 +1880,7 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc, switch (translation_mode) { case SDE_DRM_FB_SEC_DIR_TRANS: _sde_drm_fb_sec_dir_trans(smmu_state, secure_level, - catalog, old_valid_fb, &ops); + catalog, old_valid_fb, &ops, old_crtc_state); if (clone_mode && (ops & SDE_KMS_OPS_SECURE_STATE_CHANGE)) ops |= SDE_KMS_OPS_WAIT_FOR_TX_DONE; break; @@ -4347,6 +4355,55 @@ static int _sde_crtc_check_secure_single_encoder(struct drm_crtc *crtc, return 0; } +static int _sde_crtc_check_secure_transition(struct drm_crtc *crtc, + struct drm_crtc_state *state, bool is_video_mode) +{ + struct sde_crtc_state *old_cstate = to_sde_crtc_state(crtc->state); + struct sde_crtc_state *new_cstate = to_sde_crtc_state(state); + int old_secure_session = old_cstate->secure_session; + int new_secure_session = new_cstate->secure_session; + int ret = 0; + + /* + * Direct transition from Secure Camera to Secure UI(&viceversa) + * is not allowed + */ + if ((old_secure_session == SDE_SECURE_CAMERA_SESSION && + new_secure_session == SDE_SECURE_UI_SESSION) || + (old_secure_session == SDE_SECURE_UI_SESSION && + new_secure_session == SDE_SECURE_CAMERA_SESSION)) { + SDE_EVT32(DRMID(crtc), old_secure_session, + new_secure_session, SDE_EVTLOG_ERROR); + ret = -EINVAL; + } + + /* + * In video mode, null commit is required for transition between + * secure video & secure camera + */ + if (is_video_mode && + ((old_secure_session == SDE_SECURE_CAMERA_SESSION && + new_secure_session == SDE_SECURE_VIDEO_SESSION) || + (old_secure_session == SDE_SECURE_VIDEO_SESSION && + new_secure_session == SDE_SECURE_CAMERA_SESSION))) { + SDE_EVT32(DRMID(crtc), old_secure_session, + new_secure_session, SDE_EVTLOG_ERROR); + ret = -EINVAL; + } + + if (old_secure_session != new_secure_session) + SDE_EVT32(DRMID(crtc), old_secure_session, + new_secure_session); + + SDE_DEBUG("old session: %d new session : %d\n", + old_secure_session, new_secure_session); + if (ret) + SDE_ERROR("invalid transition old:%d new:%d\n", + old_secure_session, new_secure_session); + + return ret; +} + static int _sde_crtc_check_secure_state_smmu_translation(struct drm_crtc *crtc, struct drm_crtc_state *state, struct sde_kms *sde_kms, int secure, int fb_ns, int fb_sec, int fb_sec_dir) @@ -4361,19 +4418,8 @@ static int _sde_crtc_check_secure_state_smmu_translation(struct drm_crtc *crtc, MSM_DISPLAY_VIDEO_MODE); } - /* - * Secure display to secure camera needs without direct - * transition is currently not allowed - */ - if (fb_sec_dir && secure == SDE_DRM_SEC_NON_SEC && - smmu_state->state != ATTACHED && - smmu_state->secure_level == SDE_DRM_SEC_ONLY) { - - SDE_EVT32(DRMID(crtc), fb_ns, fb_sec_dir, - smmu_state->state, smmu_state->secure_level, - secure); + if (_sde_crtc_check_secure_transition(crtc, state, is_video_mode)) goto sec_err; - } /* * In video mode check for null commit before transition @@ -4439,6 +4485,33 @@ static int _sde_crtc_check_secure_conn(struct drm_crtc *crtc, return 0; } +static int _sde_crtc_populate_secure_session(struct drm_crtc_state *state, + int secure, int fb_ns, int fb_sec, int fb_sec_dir) +{ + struct sde_crtc_state *cstate = to_sde_crtc_state(state); + + if (secure == SDE_DRM_SEC_ONLY && fb_sec_dir && !fb_sec && !fb_ns) + cstate->secure_session = SDE_SECURE_UI_SESSION; + else if (secure == SDE_DRM_SEC_NON_SEC && fb_sec_dir && !fb_sec) + cstate->secure_session = SDE_SECURE_CAMERA_SESSION; + else if (secure == SDE_DRM_SEC_NON_SEC && !fb_sec_dir && fb_sec) + cstate->secure_session = SDE_SECURE_VIDEO_SESSION; + else if (secure == SDE_DRM_SEC_NON_SEC && !fb_sec_dir && + !fb_sec && fb_ns) + cstate->secure_session = SDE_NON_SECURE_SESSION; + else if (!fb_sec_dir && !fb_sec && !fb_ns) + cstate->secure_session = SDE_NULL_SESSION; + else { + SDE_ERROR( + "invalid session sec:%d fb_sec_dir:%d fb_sec:%d fb_ns:%d\n", + cstate->secure_session, fb_sec_dir, + fb_sec, fb_ns); + return -EINVAL; + } + + return 0; +} + static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, struct drm_crtc_state *state, struct plane_state pstates[], int cnt) @@ -4469,6 +4542,11 @@ static int _sde_crtc_check_secure_state(struct drm_crtc *crtc, if (rc) return rc; + rc = _sde_crtc_populate_secure_session(state, secure, + fb_ns, fb_sec, fb_sec_dir); + if (rc) + return rc; + rc = _sde_crtc_check_secure_blend_config(crtc, state, pstates, cstate, sde_kms, cnt, secure, fb_ns, fb_sec, fb_sec_dir); if (rc) diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 8ac8b9b0..cb93c90f 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -36,6 +36,22 @@ #define SDE_CRTC_FRAME_EVENT_SIZE (4 * 2) /** + * enum sde_session_type: session type + * @SDE_SECURE_UI_SESSION: secure UI usecase + * @SDE_SECURE_CAMERA_SESSION: secure camera usecase + * @SDE_SECURE_VIDEO_SESSION: secure video usecase + * @SDE_NON_SECURE_SESSION: non secure usecase + * @SDE_NULL_SESSION: null commit usecase + */ +enum sde_session_type { + SDE_SECURE_UI_SESSION, + SDE_SECURE_CAMERA_SESSION, + SDE_SECURE_VIDEO_SESSION, + SDE_NON_SECURE_SESSION, + SDE_NULL_SESSION, +}; + +/** * enum sde_crtc_client_type: crtc client type * @RT_CLIENT: RealTime client like video/cmd mode display * voting through apps rsc @@ -384,6 +400,7 @@ struct sde_crtc { * @ds_cfg: Destination scaler config * @scl3_lut_cfg: QSEED3 lut config * @new_perf: new performance state being requested + * @secure_session: Indicates the type of secure session */ struct sde_crtc_state { struct drm_crtc_state base; @@ -413,6 +430,7 @@ struct sde_crtc_state { struct sde_hw_scaler3_lut_cfg scl3_lut_cfg; struct sde_core_perf_params new_perf; + int secure_session; }; enum sde_crtc_irq_state { diff --git a/msm/sde/sde_hw_util.c b/msm/sde/sde_hw_util.c index ff4b5dfd..8b65855d 100644 --- a/msm/sde/sde_hw_util.c +++ b/msm/sde/sde_hw_util.c @@ -76,7 +76,10 @@ void sde_reg_write(struct sde_hw_blk_reg_map *c, if (c->log_mask & sde_hw_util_log_mask) SDE_DEBUG_DRIVER("[%s:0x%X] <= 0x%X\n", name, c->blk_off + reg_off, val); + SDE_EVT32_REGWRITE(c->blk_off, reg_off, val); writel_relaxed(val, c->base_off + c->blk_off + reg_off); + SDE_REG_LOG(c->log_mask ? ilog2(c->log_mask)+1 : 0, + val, c->blk_off + reg_off); } int sde_reg_read(struct sde_hw_blk_reg_map *c, u32 reg_off) diff --git a/msm/sde/sde_rm.c b/msm/sde/sde_rm.c index 7f3716b8..76e908b4 100644 --- a/msm/sde/sde_rm.c +++ b/msm/sde/sde_rm.c @@ -2126,8 +2126,8 @@ struct sde_rm_rsvp *_sde_rm_poll_get_rsvp_nxt_locked(struct sde_rm *rm, usleep_range(sleep, sleep * 2); mutex_lock(&rm->rm_lock); } - - return rsvp_nxt; + /* make sure to get latest rsvp_next to avoid use after free issues */ + return _sde_rm_get_rsvp_nxt(rm, enc); } int sde_rm_reserve( diff --git a/msm/sde_dbg.c b/msm/sde_dbg.c index a72c7e38..2723d01c 100644 --- a/msm/sde_dbg.c +++ b/msm/sde_dbg.c @@ -197,6 +197,7 @@ struct sde_dbg_regbuf { /** * struct sde_dbg_base - global sde debug base structure * @evtlog: event log instance + * @reglog: reg log instance * @reg_base_list: list of register dumping regions * @dev: device pointer * @mutex: mutex to serialize access to serialze dumps, debugfs access @@ -212,11 +213,13 @@ struct sde_dbg_regbuf { * @dsi_dbg_bus: dump dsi debug bus register * @regbuf: buffer data to track the register dumping in hw recovery * @cur_evt_index: index used for tracking event logs dump in hw recovery + * @cur_reglog_index: index used for tracking register logs dump in hw recovery * @dbgbus_dump_idx: index used for tracking dbg-bus dump in hw recovery * @vbif_dbgbus_dump_idx: index for tracking vbif dumps in hw recovery */ static struct sde_dbg_base { struct sde_dbg_evtlog *evtlog; + struct sde_dbg_reglog *reglog; struct list_head reg_base_list; void *reg_dump_addr; struct device *dev; @@ -239,6 +242,7 @@ static struct sde_dbg_base { struct sde_dbg_regbuf regbuf; u32 cur_evt_index; + u32 cur_reglog_index; u32 dbgbus_dump_idx; u32 vbif_dbgbus_dump_idx; enum sde_dbg_dump_context dump_mode; @@ -247,6 +251,9 @@ static struct sde_dbg_base { /* sde_dbg_base_evtlog - global pointer to main sde event log for macro use */ struct sde_dbg_evtlog *sde_dbg_base_evtlog; +/* sde_dbg_base_reglog - global pointer to main sde reg log for macro use */ +struct sde_dbg_reglog *sde_dbg_base_reglog; + static void _sde_debug_bus_xbar_dump(void __iomem *mem_base, struct sde_debug_bus_entry *entry, u32 val) { @@ -3720,7 +3727,7 @@ void sde_dbg_ctrl(const char *name, ...) va_end(args); } - +#ifdef CONFIG_DEBUG_FS /* * sde_dbg_debugfs_open - debugfs open handler for evtlog dump * @inode: debugfs inode @@ -4662,6 +4669,15 @@ int sde_dbg_debugfs_register(struct device *dev) return 0; } +#else + +int sde_dbg_debugfs_register(struct device *dev) +{ + return 0; +} + +#endif + static void _sde_dbg_debugfs_destroy(void) { } @@ -4727,6 +4743,12 @@ int sde_dbg_init(struct device *dev) sde_dbg_base_evtlog = sde_dbg_base.evtlog; + sde_dbg_base.reglog = sde_reglog_init(); + if (IS_ERR_OR_NULL(sde_dbg_base.reglog)) + return PTR_ERR(sde_dbg_base.reglog); + + sde_dbg_base_reglog = sde_dbg_base.reglog; + INIT_WORK(&sde_dbg_base.dump_work, _sde_dump_work); sde_dbg_base.work_panic = false; sde_dbg_base.panic_on_err = DEFAULT_PANIC; @@ -4771,6 +4793,8 @@ void sde_dbg_destroy(void) sde_dbg_base_evtlog = NULL; sde_evtlog_destroy(sde_dbg_base.evtlog); sde_dbg_base.evtlog = NULL; + sde_reglog_destroy(sde_dbg_base.reglog); + sde_dbg_base.reglog = NULL; sde_dbg_reg_base_destroy(); mutex_destroy(&sde_dbg_base.mutex); } diff --git a/msm/sde_dbg.h b/msm/sde_dbg.h index e336f323..61764c04 100644 --- a/msm/sde_dbg.h +++ b/msm/sde_dbg.h @@ -35,6 +35,7 @@ enum sde_dbg_evtlog_flag { SDE_EVTLOG_IRQ = BIT(1), SDE_EVTLOG_VERBOSE = BIT(2), SDE_EVTLOG_EXTERNAL = BIT(3), + SDE_EVTLOG_REGWRITE = BIT(4), SDE_EVTLOG_ALWAYS = -1 }; @@ -49,6 +50,34 @@ enum sde_dbg_dump_context { SDE_DBG_DUMP_CLK_ENABLED_CTX, }; +/* + * Define blocks for register write logging. + */ +#define SDE_REG_LOG_DEFAULT 0 +#define SDE_REG_LOG_NONE 1 +#define SDE_REG_LOG_CDM 2 +#define SDE_REG_LOG_DSPP 3 +#define SDE_REG_LOG_INTF 4 +#define SDE_REG_LOG_LM 5 +#define SDE_REG_LOG_CTL 6 +#define SDE_REG_LOG_PINGPONG 7 +#define SDE_REG_LOG_SSPP 8 +#define SDE_REG_LOG_WB 9 +#define SDE_REG_LOG_TOP 10 +#define SDE_REG_LOG_VBIF 11 +#define SDE_REG_LOG_DSC 12 +#define SDE_REG_LOG_ROT 13 +#define SDE_REG_LOG_DS 14 +#define SDE_REG_LOG_REGDMA 15 +#define SDE_REG_LOG_UIDLE 16 +#define SDE_REG_LOG_SID 16 +#define SDE_REG_LOG_QDSS 17 +/* + * 0-32 are reserved for sde_reg_write due to log masks + * Additional blocks are assigned from 33 to avoid conflict + */ +#define SDE_REG_LOG_RSCC 33 + #define SDE_EVTLOG_DEFAULT_ENABLE (SDE_EVTLOG_CRITICAL | SDE_EVTLOG_IRQ | \ SDE_EVTLOG_EXTERNAL) @@ -103,6 +132,44 @@ struct sde_dbg_evtlog { extern struct sde_dbg_evtlog *sde_dbg_base_evtlog; +/* + * reglog keeps this number of entries in memory for debug purpose. This + * number must be greater than number of possible writes in at least one + * single commit. + */ +#define SDE_REGLOG_ENTRY 1024 + +struct sde_dbg_reglog_log { + s64 time; + u32 pid; + u32 addr; + u32 val; + u8 blk_id; +}; + +/** + * @last_dump: Index of last entry to be output during reglog dumps + * @filter_list: Linked list of currently active filter strings + */ +struct sde_dbg_reglog { + struct sde_dbg_reglog_log logs[SDE_REGLOG_ENTRY]; + u32 first; + u32 last; + u32 last_dump; + u32 curr; + u32 next; + u32 enable; + u32 enable_mask; + spinlock_t spin_lock; +}; + +extern struct sde_dbg_reglog *sde_dbg_base_reglog; + +/** + * SDE_REG_LOG - Write register write to the register log + */ +#define SDE_REG_LOG(blk_id, val, addr) sde_reglog_log(blk_id, val, addr) + /** * SDE_EVT32 - Write a list of 32bit values to the event log, default area * ... - variable arguments @@ -134,6 +201,13 @@ extern struct sde_dbg_evtlog *sde_dbg_base_evtlog; #define SDE_EVT32_EXTERNAL(...) sde_evtlog_log(sde_dbg_base_evtlog, __func__, \ __LINE__, SDE_EVTLOG_EXTERNAL, ##__VA_ARGS__, \ SDE_EVTLOG_DATA_LIMITER) +/** + * SDE_EVT32_REGWRITE - Write a list of 32bit values for register writes logging + * ... - variable arguments + */ +#define SDE_EVT32_REGWRITE(...) sde_evtlog_log(sde_dbg_base_evtlog, __func__, \ + __LINE__, SDE_EVTLOG_REGWRITE, ##__VA_ARGS__, \ + SDE_EVTLOG_DATA_LIMITER) /** * SDE_DBG_DUMP - trigger dumping of all sde_dbg facilities @@ -175,7 +249,6 @@ extern struct sde_dbg_evtlog *sde_dbg_base_evtlog; #define SDE_DBG_CTRL(...) sde_dbg_ctrl(__func__, ##__VA_ARGS__, \ SDE_DBG_DUMP_DATA_LIMITER) -#if defined(CONFIG_DEBUG_FS) /** * sde_evtlog_init - allocate a new event log object @@ -184,6 +257,12 @@ extern struct sde_dbg_evtlog *sde_dbg_base_evtlog; struct sde_dbg_evtlog *sde_evtlog_init(void); /** + * sde_reglog_init - allocate a new reg log object + * Returns: reglog or -ERROR + */ +struct sde_dbg_reglog *sde_reglog_init(void); + +/** * sde_evtlog_destroy - destroy previously allocated event log * @evtlog: pointer to evtlog * Returns: none @@ -191,6 +270,13 @@ struct sde_dbg_evtlog *sde_evtlog_init(void); void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog); /** + * sde_reglog_destroy - destroy previously allocated reg log + * @reglog: pointer to reglog + * Returns: none + */ +void sde_reglog_destroy(struct sde_dbg_reglog *reglog); + +/** * sde_evtlog_log - log an entry into the event log. * log collection may be enabled/disabled entirely via debugfs * log area collection may be filtered by user provided flags via debugfs. @@ -204,6 +290,15 @@ void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, const char *name, int line, int flag, ...); /** + * sde_reglog_log - log an entry into the reg log. + * log collection may be enabled/disabled entirely via debugfs + * log area collection may be filtered by user provided flags via debugfs. + * @reglog: pointer to evtlog + * Returns: none + */ +void sde_reglog_log(u8 blk_id, u32 val, u32 addr); + +/** * sde_evtlog_dump_all - print all entries in event log to kernel log * @evtlog: pointer to evtlog * Returns: none @@ -371,101 +466,4 @@ void sde_rsc_debug_dump(u32 mux_sel); */ void dsi_ctrl_debug_dump(u32 *entries, u32 size); -#else -static inline struct sde_dbg_evtlog *sde_evtlog_init(void) -{ - return NULL; -} - -static inline void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog) -{ -} - -static inline void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, - const char *name, int line, int flag, ...) -{ -} - -static inline void sde_evtlog_dump_all(struct sde_dbg_evtlog *evtlog) -{ -} - -static inline bool sde_evtlog_is_enabled(struct sde_dbg_evtlog *evtlog, - u32 flag) -{ - return false; -} - -static inline ssize_t sde_evtlog_dump_to_buffer(struct sde_dbg_evtlog *evtlog, - char *evtlog_buf, ssize_t evtlog_buf_size, - bool update_last_entry) -{ - return 0; -} - -static inline void sde_dbg_init_dbg_buses(u32 hwversion) -{ -} - -static inline int sde_dbg_init(struct device *dev) -{ - return 0; -} - -static inline int sde_dbg_debugfs_register(struct device *dev) -{ - return 0; -} - -static inline void sde_dbg_destroy(void) -{ -} - -static inline void sde_dbg_dump(enum sde_dbg_dump_context mode, - const char *name, ...) -{ -} - -static inline void sde_dbg_ctrl(const char *name, ...) -{ -} - -static inline int sde_dbg_reg_register_base(const char *name, - void __iomem *base, size_t max_offset) -{ - return 0; -} - -static inline void sde_dbg_reg_register_dump_range(const char *base_name, - const char *range_name, u32 offset_start, u32 offset_end, - uint32_t xin_id) -{ -} - -static inline void sde_dbg_set_sde_top_offset(u32 blk_off) -{ -} - -static inline void sde_evtlog_set_filter( - struct sde_dbg_evtlog *evtlog, char *filter) -{ -} - -static inline int sde_evtlog_get_filter(struct sde_dbg_evtlog *evtlog, - int index, char *buf, size_t bufsz) -{ - return -EINVAL; -} - -static inline void sde_rsc_debug_dump(u32 mux_sel) -{ -} - -static inline void dsi_ctrl_debug_dump(u32 *entries, u32 size) -{ -} - -#endif /* defined(CONFIG_DEBUG_FS) */ - - #endif /* SDE_DBG_H_ */ diff --git a/msm/sde_dbg_evtlog.c b/msm/sde_dbg_evtlog.c index 71ec3283..ddb4c996 100644 --- a/msm/sde_dbg_evtlog.c +++ b/msm/sde_dbg_evtlog.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "sde_dbg:[%s] " fmt, __func__ @@ -101,6 +101,31 @@ exit: spin_unlock_irqrestore(&evtlog->spin_lock, flags); } +void sde_reglog_log(u8 blk_id, u32 val, u32 addr) +{ + unsigned long flags; + struct sde_dbg_reglog_log *log; + struct sde_dbg_reglog *reglog = sde_dbg_base_reglog; + + if (!reglog) + return; + + spin_lock_irqsave(®log->spin_lock, flags); + + log = ®log->logs[reglog->curr]; + + log->blk_id = blk_id; + log->val = val; + log->addr = addr; + log->time = local_clock(); + log->pid = current->pid; + + reglog->curr = (reglog->curr + 1) % SDE_REGLOG_ENTRY; + reglog->last++; + + spin_unlock_irqrestore(®log->spin_lock, flags); +} + /* always dump the last entries which are not dumped yet */ static bool _sde_evtlog_dump_calc_range(struct sde_dbg_evtlog *evtlog, bool update_last_entry, bool full_dump) @@ -211,6 +236,19 @@ struct sde_dbg_evtlog *sde_evtlog_init(void) return evtlog; } +struct sde_dbg_reglog *sde_reglog_init(void) +{ + struct sde_dbg_reglog *reglog; + + reglog = kzalloc(sizeof(*reglog), GFP_KERNEL); + if (!reglog) + return ERR_PTR(-ENOMEM); + + spin_lock_init(®log->spin_lock); + + return reglog; +} + int sde_evtlog_get_filter(struct sde_dbg_evtlog *evtlog, int index, char *buf, size_t bufsz) { @@ -312,3 +350,11 @@ void sde_evtlog_destroy(struct sde_dbg_evtlog *evtlog) } kfree(evtlog); } + +void sde_reglog_destroy(struct sde_dbg_reglog *reglog) +{ + if (!reglog) + return; + + kfree(reglog); +} diff --git a/msm/sde_io_util.c b/msm/sde_io_util.c index 09649c59..ad6e89f7 100644 --- a/msm/sde_io_util.c +++ b/msm/sde_io_util.c @@ -9,6 +9,7 @@ #include <linux/regulator/consumer.h> #include <linux/delay.h> #include <linux/sde_io_util.h> +#include "sde_dbg.h" #define MAX_I2C_CMDS 16 void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug) @@ -33,7 +34,9 @@ void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug) DEV_DBG("[%08x] => %08x [%08x]\n", (u32)(unsigned long)(io->base + offset), value, in_val); + SDE_EVT32_REGWRITE(io->base, offset, value, in_val); } + SDE_REG_LOG(SDE_REG_LOG_RSCC, value, offset); } /* dss_reg_w */ EXPORT_SYMBOL(dss_reg_w); |