summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2020-12-29 08:10:30 -0800
committerLinux Build Service Account <lnxbuild@localhost>2020-12-29 08:10:30 -0800
commita9b2969cdfba576b80f829f614b9e6776d60c0b8 (patch)
tree9f83f42289dc1f049d19b57625886c8f0323ffe3
parentdb31f54fab7d6eb09a591137f6a03f984082f71d (diff)
parenta9dcc6e2b0be1866f0ae32aace73953108122194 (diff)
downloaddisplay-drivers-a9b2969cdfba576b80f829f614b9e6776d60c0b8.tar.gz
Merge a9dcc6e2b0be1866f0ae32aace73953108122194 on remote branch
Change-Id: I8c9a0d1591fe29934493255dc3e6ccbfea2b9a45
-rw-r--r--msm/Makefile3
-rw-r--r--msm/dp/dp_debug.c4
-rw-r--r--msm/dp/dp_panel.c23
-rw-r--r--msm/dp/dp_panel.h2
-rw-r--r--msm/dsi/dsi_ctrl.c9
-rw-r--r--msm/sde/sde_crtc.c106
-rw-r--r--msm/sde/sde_crtc.h18
-rw-r--r--msm/sde/sde_hw_util.c3
-rw-r--r--msm/sde/sde_rm.c4
-rw-r--r--msm/sde_dbg.c26
-rw-r--r--msm/sde_dbg.h194
-rw-r--r--msm/sde_dbg_evtlog.c48
-rw-r--r--msm/sde_io_util.c3
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(&reglog->spin_lock, flags);
+
+ log = &reglog->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(&reglog->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(&reglog->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);