drm/msm/sde: match xlog features in evtlog
Upgrade event log facility with xlog feature set which supports
variable arguments and other features required. evtlog now
registers debugfs at /sys/kernel/debug/dri/0/evtlog. It can be
enabled by echo 1 into the enable node, and dumped using the
dump node. Move evtlog support into sde layer since only sde
uses it.
Change-Id: I51f8577a0e626ab53601e07a16cefe8da90125e1
Signed-off-by: Lloyd Atkinson <latkinso@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index cb3b6ab..8ef30cc 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -44,7 +44,8 @@
sde/sde_connector.o \
sde/sde_backlight.o \
sde/sde_color_processing.o \
- sde/sde_vbif.o
+ sde/sde_vbif.o \
+ sde_dbg_evtlog.o
# use drm gpu driver only if qcom_kgsl driver not available
ifneq ($(CONFIG_QCOM_KGSL),y)
@@ -136,7 +137,6 @@
msm_perf.o \
msm_rd.o \
msm_ringbuffer.o \
- msm_evtlog.o \
msm_prop.o
obj-$(CONFIG_DRM_MSM) += msm_drm.o
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index d127f2c..e6d8ffe 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -248,7 +248,9 @@
priv->vram.paddr, attrs);
}
- component_unbind_all(dev, ddev);
+ sde_evtlog_destroy();
+
+ component_unbind_all(dev->dev, dev);
msm_mdss_destroy(ddev);
@@ -431,7 +433,11 @@
if (ret)
goto fail;
- msm_gem_shrinker_init(ddev);
+ ret = sde_evtlog_init(dev->primary->debugfs_root);
+ if (ret) {
+ dev_err(dev->dev, "failed to init evtlog: %d\n", ret);
+ goto fail;
+ }
switch (get_mdp_ver(pdev)) {
case KMS_MDP4:
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 6ff191f..d8de7e0 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -44,7 +44,6 @@
#include <drm/msm_drm.h>
#include <drm/drm_gem.h>
-#include "msm_evtlog.h"
#include "sde_power_handle.h"
#define GET_MAJOR_REV(rev) ((rev) >> 28)
@@ -317,28 +316,10 @@
struct msm_vblank_ctrl vblank_ctrl;
- /* task holding struct_mutex.. currently only used in submit path
- * to detect and reject faults from copy_from_user() for submit
- * ioctl.
- */
- struct task_struct *struct_mutex_task;
-
- struct msm_evtlog evtlog;
+ /* list of clients waiting for events */
+ struct list_head client_event_list;
};
-/* Helper macro for accessing msm_drm_private's event log */
-#define MSM_EVTMSG(dev, msg, x, y) do { \
- if ((dev) && ((struct drm_device *)(dev))->dev_private) \
- msm_evtlog_sample(&((struct msm_drm_private *) \
- ((struct drm_device *) \
- (dev))->dev_private)->evtlog, __func__,\
- (msg), (uint64_t)(x), (uint64_t)(y), \
- __LINE__); \
- } while (0)
-
-/* Helper macro for accessing msm_drm_private's event log */
-#define MSM_EVT(dev, x, y) MSM_EVTMSG((dev), 0, (x), (y))
-
struct msm_format {
uint32_t pixel_format;
};
@@ -363,6 +344,7 @@
struct drm_atomic_state *state, bool nonblock);
int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
+void msm_unregister_all_mmu(struct drm_device *dev);
void msm_gem_submit_free(struct msm_gem_submit *submit);
int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/msm/msm_evtlog.h b/drivers/gpu/drm/msm/msm_evtlog.h
deleted file mode 100644
index 8351289..0000000
--- a/drivers/gpu/drm/msm/msm_evtlog.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef MSM_MSM_EVTLOG_H_
-#define MSM_MSM_EVTLOG_H_
-
-#include <linux/ktime.h>
-#include <linux/atomic.h>
-#include <linux/dcache.h>
-
-/**
- * struct msm_evtlog_evt - Event log entry
- * @ktime: Timestamp of event
- * @func: Calling function name
- * @msg: User provided string
- * @val1: User provided value
- * @val2: User provided value
- * @line: Line number of caller
- * @pid: Process id of logger
- */
-struct msm_evtlog_evt {
- ktime_t ktime;
- const char *func;
- const char *msg;
- uint64_t val1;
- uint64_t val2;
- uint32_t line;
- uint32_t pid;
-};
-
-/**
- * struct msm_evtlog - current driver state information
- * @events: Pointer to dynamically allocated event log buffer
- * @cnt: Atomic number of events since clear. Can be used to calculate
- * the current index. Note: The count does not wrap.
- * Reset the event log by setting to zero.
- * Used for lock-less producer synchronization.
- * @size: Size of events array. Must be power of 2 to facilitate fast
- * increments by using a bitmask to get rollover.
- * @dentry: Filesystem entry of debugfs registration
- */
-struct msm_evtlog {
- struct msm_evtlog_evt *events;
- atomic_t cnt;
- unsigned long size;
- struct dentry *dentry;
-};
-
-/**
- * msm_evtlog_init() - Create an event log, registered with debugfs.
- * @log: Event log handle
- * @size: Max # of events in buffer. Will be rounded up to power of 2.
- * @parent: Parent directory entry for debugfs registration
- *
- * Return: error code.
- */
-int msm_evtlog_init(struct msm_evtlog *log, int size, struct dentry *parent);
-
-/**
- * msm_evtlog_destroy() - Destroy event log
- * @log: Event log handle
- *
- * Unregisters debugfs node and frees memory.
- * Caller needs to make sure that log sampling has stopped.
- */
-void msm_evtlog_destroy(struct msm_evtlog *log);
-
-/**
- * msm_evtlog_sample() - Add entry to the event log
- * @evtlog: Event log handle
- * @func: Calling function name
- * @msg: User provided string
- * @val1: User provided value
- * @val2: User provided value
- * @line: Line number of caller
- */
-void msm_evtlog_sample(
- struct msm_evtlog *log,
- const char *func,
- const char *msg,
- uint64_t val1,
- uint64_t val2,
- uint32_t line);
-
-#endif /* MSM_MSM_EVTLOG_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 6bc69cb..ac9997c 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -519,7 +519,8 @@
"conn%u",
c_conn->base.base.id);
- rc = sde_fence_init(dev, &c_conn->retire_fence, c_conn->name);
+ rc = sde_fence_init(&c_conn->retire_fence, c_conn->name,
+ c_conn->base.base.id);
if (rc) {
SDE_ERROR("failed to init fence, %d\n", rc);
goto error_cleanup_conn;
diff --git a/drivers/gpu/drm/msm/sde/sde_core_irq.c b/drivers/gpu/drm/msm/sde/sde_core_irq.c
index 0d100e7..502a7fa 100644
--- a/drivers/gpu/drm/msm/sde/sde_core_irq.c
+++ b/drivers/gpu/drm/msm/sde/sde_core_irq.c
@@ -95,7 +95,7 @@
atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx]));
spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
- MSM_EVTMSG(sde_kms->dev, NULL, irq_idx,
+ SDE_EVT32(irq_idx,
atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx]));
if (atomic_inc_return(&sde_kms->irq_obj.enable_counts[irq_idx]) == 1) {
ret = sde_kms->hw_intr->ops.enable_irq(
@@ -157,7 +157,7 @@
atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx]));
spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
- MSM_EVTMSG(sde_kms->dev, NULL, irq_idx,
+ SDE_EVT32(irq_idx,
atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx]));
if (atomic_dec_return(&sde_kms->irq_obj.enable_counts[irq_idx]) == 0) {
ret = sde_kms->hw_intr->ops.disable_irq(
@@ -218,7 +218,7 @@
SDE_DEBUG("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
- MSM_EVTMSG(sde_kms->dev, NULL, irq_idx, register_irq_cb);
+ SDE_EVT32(irq_idx, register_irq_cb);
list_del_init(®ister_irq_cb->list);
list_add_tail(®ister_irq_cb->list,
&sde_kms->irq_obj.irq_cb_tbl[irq_idx]);
@@ -246,7 +246,7 @@
SDE_DEBUG("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
- MSM_EVTMSG(sde_kms->dev, NULL, irq_idx, register_irq_cb);
+ SDE_EVT32(irq_idx, register_irq_cb);
list_del_init(®ister_irq_cb->list);
/* empty callback list but interrupt is still enabled */
if (list_empty(&sde_kms->irq_obj.irq_cb_tbl[irq_idx]) &&
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 0c0a5c3..237d9f4 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -310,7 +310,7 @@
sde_crtc = to_sde_crtc(crtc);
cstate = to_sde_crtc_state(crtc->state);
- MSM_EVT(crtc->dev, crtc->base.id, 0);
+ SDE_EVT32(DRMID(crtc));
/* identify connectors attached to this crtc */
cstate->is_rt = false;
@@ -359,7 +359,7 @@
sde_crtc->event = NULL;
DRM_DEBUG_VBL("%s: send event: %pK\n",
sde_crtc->name, event);
- MSM_EVT(crtc->dev, crtc->base.id, 0);
+ SDE_EVT32(DRMID(crtc));
drm_crtc_send_vblank_event(crtc, event);
}
}
@@ -379,7 +379,7 @@
drm_crtc_handle_vblank(crtc);
DRM_DEBUG_VBL("crtc%d\n", crtc->base.id);
- MSM_EVT(crtc->dev, crtc->base.id, 0);
+ SDE_EVT32_IRQ(DRMID(crtc));
}
void sde_crtc_complete_commit(struct drm_crtc *crtc,
@@ -396,7 +396,7 @@
sde_crtc = to_sde_crtc(crtc);
cstate = to_sde_crtc_state(crtc->state);
- MSM_EVT(crtc->dev, crtc->base.id, 0);
+ SDE_EVT32(DRMID(crtc));
/* signal output fence(s) at end of commit */
sde_fence_signal(&sde_crtc->output_fence, 0);
@@ -995,7 +995,7 @@
if (encoder->crtc != crtc)
continue;
- MSM_EVT(crtc->dev, crtc->base.id, en);
+ SDE_EVT32(DRMID(crtc), en);
if (en)
sde_encoder_register_vblank_callback(encoder,
@@ -1376,8 +1376,8 @@
snprintf(sde_crtc->name, SDE_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
/* initialize output fence support */
- sde_fence_init(dev, &sde_crtc->output_fence, sde_crtc->name);
mutex_init(&sde_crtc->crtc_lock);
+ sde_fence_init(&sde_crtc->output_fence, sde_crtc->name, crtc->base.id);
/* initialize debugfs support */
_sde_crtc_init_debugfs(sde_crtc, kms);
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 365d6f1..4032b98 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -286,7 +286,7 @@
sde_kms = to_sde_kms(priv->kms);
mode = &crtc_state->mode;
adj_mode = &crtc_state->adjusted_mode;
- MSM_EVT(drm_enc->dev, 0, 0);
+ SDE_EVT32(DRMID(drm_enc));
/* perform atomic check on the first physical encoder (master) */
for (i = 0; i < sde_enc->num_phys_encs; i++) {
@@ -317,7 +317,7 @@
drm_mode_set_crtcinfo(adj_mode, 0);
}
- MSM_EVT(drm_enc->dev, adj_mode->flags, adj_mode->private_flags);
+ SDE_EVT32(DRMID(drm_enc), adj_mode->flags, adj_mode->private_flags);
return ret;
}
@@ -346,7 +346,7 @@
sde_kms = to_sde_kms(priv->kms);
connector_list = &sde_kms->dev->mode_config.connector_list;
- MSM_EVT(drm_enc->dev, 0, 0);
+ SDE_EVT32(DRMID(drm_enc));
list_for_each_entry(conn_iter, connector_list, head)
if (conn_iter->encoder == drm_enc)
@@ -417,8 +417,7 @@
sde_kms = to_sde_kms(priv->kms);
SDE_DEBUG_ENC(sde_enc, "\n");
-
- MSM_EVT(drm_enc->dev, 0, 0);
+ SDE_EVT32(DRMID(drm_enc));
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
@@ -472,7 +471,7 @@
priv = drm_enc->dev->dev_private;
sde_kms = to_sde_kms(priv->kms);
- MSM_EVT(drm_enc->dev, 0, 0);
+ SDE_EVT32(DRMID(drm_enc));
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
@@ -576,7 +575,7 @@
return;
}
SDE_DEBUG_ENC(sde_enc, "\n");
- MSM_EVT(drm_enc->dev, enable, 0);
+ SDE_EVT32(DRMID(drm_enc), enable);
spin_lock_irqsave(&sde_enc->spin_lock, lock_flags);
sde_enc->crtc_vblank_cb = vbl_cb;
@@ -606,7 +605,7 @@
sde_enc->pending_kickoff_mask &= ~(1 << i);
mask = sde_enc->pending_kickoff_mask;
spin_unlock_irqrestore(&sde_enc->spin_lock, lock_flags);
- MSM_EVT(drm_enc->dev, i, mask);
+ SDE_EVT32(DRMID(drm_enc), i, mask);
}
}
@@ -641,7 +640,7 @@
ctl->ops.update_pending_flush(ctl, extra_flush_bits);
ctl->ops.trigger_flush(ctl);
- MSM_EVT(drm_enc->dev, drm_enc->base.id, ctl->idx);
+ SDE_EVT32(DRMID(drm_enc), ctl->idx);
}
/**
@@ -676,9 +675,7 @@
}
if (phys_enc && phys_enc->parent)
- MSM_EVT(phys_enc->parent->dev,
- phys_enc->parent->base.id,
- ctl_idx);
+ SDE_EVT32(DRMID(phys_enc->parent), ctl_idx);
}
/**
@@ -744,7 +741,7 @@
sde_enc = to_sde_encoder_virt(drm_enc);
SDE_DEBUG_ENC(sde_enc, "\n");
- MSM_EVT(drm_enc->dev, 0, 0);
+ SDE_EVT32(DRMID(drm_enc));
spin_lock_irqsave(&sde_enc->spin_lock, lock_flags);
sde_enc->pending_kickoff_mask = 0;
@@ -765,7 +762,7 @@
}
spin_lock_irqsave(&sde_enc->spin_lock, lock_flags);
- MSM_EVT(drm_enc->dev, sde_enc->pending_kickoff_mask, 0);
+ SDE_EVT32(DRMID(drm_enc), sde_enc->pending_kickoff_mask);
spin_unlock_irqrestore(&sde_enc->spin_lock, lock_flags);
/* Wait for the busy phys encs to be ready */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 3be4d27..37b949d 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -34,8 +34,6 @@
#define to_sde_encoder_phys_cmd(x) \
container_of(x, struct sde_encoder_phys_cmd, base)
-#define DEV(phy_enc) (phy_enc->parent->dev)
-
#define WAIT_TIMEOUT_MSEC 100
/*
@@ -111,7 +109,8 @@
phys_enc = &cmd_enc->base;
new_pending_cnt = atomic_dec_return(&cmd_enc->pending_cnt);
- MSM_EVT(DEV(phys_enc), phys_enc->hw_pp->idx, new_pending_cnt);
+ SDE_EVT32_IRQ(DRMID(phys_enc->parent), phys_enc->hw_pp->idx,
+ new_pending_cnt);
/* Signal any waiting atomic commit thread */
wake_up_all(&cmd_enc->pp_tx_done_wq);
@@ -384,7 +383,7 @@
__builtin_return_address(0),
enable, atomic_read(&phys_enc->vblank_refcount));
- MSM_EVTMSG(phys_enc->parent->dev, NULL, enable,
+ SDE_EVT32(DRMID(phys_enc->parent), enable,
atomic_read(&phys_enc->vblank_refcount));
if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
@@ -575,7 +574,8 @@
"pp %d needs to wait, new_pending_cnt %d",
phys_enc->hw_pp->idx - PINGPONG_0,
new_pending_cnt);
- MSM_EVT(DEV(phys_enc), phys_enc->hw_pp->idx, new_pending_cnt);
+ SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx,
+ new_pending_cnt);
}
static void sde_encoder_phys_cmd_init_ops(
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index e45a62d..89b0d8e 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -36,8 +36,6 @@
#define to_sde_encoder_phys_vid(x) \
container_of(x, struct sde_encoder_phys_vid, base)
-#define DEV(phy_enc) (phy_enc->parent->dev)
-
#define WAIT_TIMEOUT_MSEC 100
static bool sde_encoder_phys_vid_is_master(
@@ -500,7 +498,7 @@
__builtin_return_address(0),
enable, atomic_read(&phys_enc->vblank_refcount));
- MSM_EVTMSG(phys_enc->parent->dev, NULL, enable,
+ SDE_EVT32(DRMID(phys_enc->parent), enable,
atomic_read(&phys_enc->vblank_refcount));
if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
@@ -685,18 +683,20 @@
return -EWOULDBLOCK;
}
- MSM_EVTMSG(DEV(phys_enc), "waiting", 0, 0);
+ SDE_EVT32(DRMID(phys_enc->parent), vid_enc->hw_intf->idx,
+ SDE_EVTLOG_FUNC_ENTRY);
ret = wait_for_completion_timeout(&vid_enc->vblank_completion,
msecs_to_jiffies(WAIT_TIMEOUT_MSEC));
if (!ret) {
SDE_DEBUG_VIDENC(vid_enc, "wait %u ms timed out\n",
WAIT_TIMEOUT_MSEC);
- MSM_EVTMSG(DEV(phys_enc), "wait_timeout", 0, 0);
+ SDE_EVT32(DRMID(phys_enc->parent), WAIT_TIMEOUT_MSEC);
return -ETIMEDOUT;
}
- MSM_EVTMSG(DEV(phys_enc), "wait_done", 0, 0);
+ SDE_EVT32(DRMID(phys_enc->parent), vid_enc->hw_intf->idx,
+ SDE_EVTLOG_FUNC_EXIT);
return 0;
}
@@ -734,7 +734,7 @@
* Video encoders need to turn on their interfaces now
*/
if (phys_enc->enable_state == SDE_ENC_ENABLING) {
- MSM_EVT(DEV(phys_enc), 0, 0);
+ SDE_EVT32(DRMID(phys_enc->parent), vid_enc->hw_intf->idx);
spin_lock_irqsave(&phys_enc->spin_lock, lock_flags);
vid_enc->hw_intf->ops.enable_timing(vid_enc->hw_intf, 1);
spin_unlock_irqrestore(&phys_enc->spin_lock, lock_flags);
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
index 1e5e186..970969b 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
@@ -31,7 +31,7 @@
#define to_sde_encoder_phys_wb(x) \
container_of(x, struct sde_encoder_phys_wb, base)
-#define DEV(phy_enc) (phy_enc->parent->dev)
+#define WBID(wb_enc) ((wb_enc) ? wb_enc->wb_dev->wb_idx : -1)
/**
* sde_encoder_phys_wb_is_master - report wb always as master encoder
@@ -676,13 +676,14 @@
if (WARN_ON(phys_enc->enable_state != SDE_ENC_ENABLED))
return -EWOULDBLOCK;
- MSM_EVT(DEV(phys_enc), wb_enc->frame_count, 0);
+ SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc), wb_enc->frame_count);
ret = wait_for_completion_timeout(&wb_enc->wbdone_complete,
msecs_to_jiffies(wb_enc->wbdone_timeout));
if (!ret) {
- MSM_EVT(DEV(phys_enc), wb_enc->frame_count, 0);
+ SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc),
+ wb_enc->frame_count);
irq_status = sde_core_irq_read(phys_enc->sde_kms,
wb_enc->irq_idx, true);
@@ -720,7 +721,8 @@
wb_enc->wb_dev->wb_idx - WB_0, wb_time);
}
- MSM_EVT(DEV(phys_enc), wb_enc->frame_count, wb_time);
+ SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc), wb_enc->frame_count,
+ wb_time);
return rc;
}
@@ -760,7 +762,8 @@
/* vote for iommu/clk/bus */
wb_enc->start_time = ktime_get();
- MSM_EVT(DEV(phys_enc), *need_to_wait, wb_enc->kickoff_count);
+ SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc), *need_to_wait,
+ wb_enc->kickoff_count);
}
/**
@@ -774,7 +777,7 @@
SDE_DEBUG("[wb:%d]\n", wb_enc->hw_wb->idx - WB_0);
- MSM_EVT(DEV(phys_enc), 0, 0);
+ SDE_EVT32(DRMID(phys_enc->parent), WBID(wb_enc));
}
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_fence.c b/drivers/gpu/drm/msm/sde/sde_fence.c
index 23e5614..6db6f98 100644
--- a/drivers/gpu/drm/msm/sde/sde_fence.c
+++ b/drivers/gpu/drm/msm/sde/sde_fence.c
@@ -105,14 +105,15 @@
/**
* SDE_FENCE_TIMELINE_NAME - macro for accessing s/w timeline's name
* @fence: Pointer to sde fence structure
+ * @drm_id: ID number of owning DRM Object
* Returns: Pointer to timeline name string
*/
#define SDE_FENCE_TIMELINE_NAME(fence) \
(((struct sw_sync_timeline *)fence->timeline)->obj.name)
-int sde_fence_init(void *dev,
- struct sde_fence *fence,
- const char *name)
+int sde_fence_init(struct sde_fence *fence,
+ const char *name,
+ uint32_t drm_id)
{
if (!fence) {
SDE_ERROR("invalid argument(s)\n");
@@ -125,9 +126,9 @@
return -ENOMEM;
}
- fence->dev = dev;
fence->commit_count = 0;
fence->done_count = 0;
+ fence->drm_id = drm_id;
mutex_init(&fence->fence_lock);
return 0;
@@ -155,10 +156,7 @@
mutex_lock(&fence->fence_lock);
++fence->commit_count;
- MSM_EVTMSG(fence->dev,
- SDE_FENCE_TIMELINE_NAME(fence),
- fence->commit_count,
- fence->done_count);
+ SDE_EVT32(fence->drm_id, fence->commit_count, fence->done_count);
mutex_unlock(&fence->fence_lock);
return 0;
}
@@ -187,10 +185,7 @@
trigger_value);
*val = fd;
- MSM_EVTMSG(fence->dev,
- SDE_FENCE_TIMELINE_NAME(fence),
- trigger_value,
- fd);
+ SDE_EVT32(fence->drm_id, trigger_value, fd);
mutex_unlock(&fence->fence_lock);
if (fd >= 0)
@@ -228,11 +223,10 @@
else
sw_sync_timeline_inc(fence->timeline, (int)val);
}
- MSM_EVTMSG(fence->dev,
- SDE_FENCE_TIMELINE_NAME(fence),
- fence->done_count,
- ((struct sw_sync_timeline *)
- fence->timeline)->value);
+
+ SDE_EVT32(fence->drm_id, fence->done_count,
+ ((struct sw_sync_timeline *) fence->timeline)->value);
+
mutex_unlock(&fence->fence_lock);
}
#endif
diff --git a/drivers/gpu/drm/msm/sde/sde_fence.h b/drivers/gpu/drm/msm/sde/sde_fence.h
index b5980b4..113d16b 100644
--- a/drivers/gpu/drm/msm/sde/sde_fence.h
+++ b/drivers/gpu/drm/msm/sde/sde_fence.h
@@ -85,30 +85,30 @@
/**
* struct sde_fence - output fence container structure
* @timeline: Pointer to fence timeline
- * @dev: Pointer to drm device structure
* @commit_count: Number of detected commits since bootup
* @done_count: Number of completed commits since bootup
+ * @drm_id: ID number of owning DRM Object
* @fence_lock: Mutex object to protect local fence variables
*/
struct sde_fence {
void *timeline;
- void *dev;
int32_t commit_count;
int32_t done_count;
+ uint32_t drm_id;
struct mutex fence_lock;
};
#if IS_ENABLED(CONFIG_SW_SYNC)
/**
* sde_fence_init - initialize fence object
- * @dev: Pointer to drm device structure
* @fence: Pointer to crtc fence object
+ * @drm_id: ID number of owning DRM Object
* @name: Timeline name
* Returns: Zero on success
*/
-int sde_fence_init(void *dev,
- struct sde_fence *fence,
- const char *name);
+int sde_fence_init(struct sde_fence *fence,
+ const char *name,
+ uint32_t drm_id);
/**
* sde_fence_deinit - deinit fence container
@@ -139,9 +139,9 @@
*/
void sde_fence_signal(struct sde_fence *fence, bool is_error);
#else
-static inline int sde_fence_init(void *dev,
- struct sde_fence *fence,
- const char *name)
+static inline int sde_fence_init(struct sde_fence *fence,
+ const char *name,
+ uint32_t drm_id)
{
/* do nothing */
return 0;
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index e8816e6..77691a1 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -244,16 +244,16 @@
static void sde_commit(struct msm_kms *kms, struct drm_atomic_state *old_state)
{
- struct sde_kms *sde_kms = to_sde_kms(kms);
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int i;
- MSM_EVT(sde_kms->dev, 0, 0);
-
- for_each_crtc_in_state(old_state, crtc, old_crtc_state, i)
- if (crtc->state->active)
+ for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+ if (crtc->state->active) {
+ SDE_EVT32(DRMID(crtc));
sde_crtc_commit_kickoff(crtc);
+ }
+ }
}
static void sde_complete_commit(struct msm_kms *kms,
@@ -270,7 +270,7 @@
sde_crtc_complete_commit(crtc, old_crtc_state);
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
- MSM_EVT(sde_kms->dev, 0, 0);
+ SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
}
static void sde_wait_for_commit_done(struct msm_kms *kms,
@@ -303,7 +303,7 @@
* For example, wait for vsync in case of video mode panels
* This should be a no-op for command mode panels
*/
- MSM_EVT(crtc->dev, crtc->base.id, 0);
+ SDE_EVT32(DRMID(crtc));
ret = sde_encoder_wait_for_commit_done(encoder);
if (ret && ret != -EWOULDBLOCK) {
DRM_ERROR("wait for commit done returned %d\n", ret);
@@ -906,9 +906,6 @@
* 'primary' is already created.
*/
sde_debugfs_init(sde_kms);
- msm_evtlog_init(&priv->evtlog, SDE_EVTLOG_SIZE,
- sde_debugfs_get_root(sde_kms));
- MSM_EVT(dev, 0, 0);
/*
* modeset_init should create the DRM related objects i.e. CRTCs,
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index c35a32d..c77647e 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -16,6 +16,7 @@
#include "msm_drv.h"
#include "msm_kms.h"
#include "msm_mmu.h"
+#include "sde_dbg.h"
#include "sde_hw_catalog.h"
#include "sde_hw_ctl.h"
#include "sde_hw_lm.h"
@@ -26,6 +27,8 @@
#include "sde_power_handle.h"
#include "sde_irq.h"
+#define DRMID(x) ((x) ? (x)->base.id : -1)
+
/**
* SDE_DEBUG - macro for kms/plane/crtc/encoder/connector logs
* @fmt: Pointer to format string
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index ee98bb0..8dc31a5 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -491,10 +491,7 @@
prefix = sde_sync_get_name_prefix(input_fence);
ret = sde_sync_wait(input_fence, wait_ms);
- MSM_EVT(plane->dev,
- plane->base.id,
- (uint64_t)-ret << (sizeof(uint32_t) * CHAR_BIT)
- | prefix);
+ SDE_EVT32(DRMID(plane), -ret, prefix);
switch (ret) {
case 0:
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index e1e63dd..075e9d6 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -92,29 +92,50 @@
void *hw;
};
-static void _sde_rm_print_rsvps(struct sde_rm *rm, const char *msg)
+/**
+ * sde_rm_dbg_rsvp_stage - enum of steps in making reservation for event logging
+ */
+enum sde_rm_dbg_rsvp_stage {
+ SDE_RM_STAGE_BEGIN,
+ SDE_RM_STAGE_AFTER_CLEAR,
+ SDE_RM_STAGE_AFTER_RSVPNEXT,
+ SDE_RM_STAGE_FINAL
+};
+
+static void _sde_rm_print_rsvps(
+ struct sde_rm *rm,
+ enum sde_rm_dbg_rsvp_stage stage)
{
struct sde_rm_rsvp *rsvp;
struct sde_rm_hw_blk *blk;
enum sde_hw_blk_type type;
- SDE_DEBUG("%s\n", msg);
+ SDE_DEBUG("%d\n", stage);
- list_for_each_entry(rsvp, &rm->rsvps, list)
- SDE_DEBUG("%s rsvp[s%ue%u] topology %d\n", msg, rsvp->seq,
+ list_for_each_entry(rsvp, &rm->rsvps, list) {
+ SDE_DEBUG("%d rsvp[s%ue%u] topology %d\n", stage, rsvp->seq,
rsvp->enc_id, rsvp->topology);
+ SDE_EVT32(stage, rsvp->seq, rsvp->enc_id, rsvp->topology);
+ }
for (type = 0; type < SDE_HW_BLK_MAX; type++) {
list_for_each_entry(blk, &rm->hw_blks[type], list) {
if (!blk->rsvp && !blk->rsvp_nxt)
continue;
- SDE_DEBUG("%s rsvp[s%ue%u->s%ue%u] %s %d\n", msg,
+ SDE_DEBUG("%d rsvp[s%ue%u->s%ue%u] %s %d\n", stage,
(blk->rsvp) ? blk->rsvp->seq : 0,
(blk->rsvp) ? blk->rsvp->enc_id : 0,
(blk->rsvp_nxt) ? blk->rsvp_nxt->seq : 0,
(blk->rsvp_nxt) ? blk->rsvp_nxt->enc_id : 0,
blk->type_name, blk->id);
+
+ SDE_EVT32(stage,
+ (blk->rsvp) ? blk->rsvp->seq : 0,
+ (blk->rsvp) ? blk->rsvp->enc_id : 0,
+ (blk->rsvp_nxt) ? blk->rsvp_nxt->seq : 0,
+ (blk->rsvp_nxt) ? blk->rsvp_nxt->enc_id : 0,
+ blk->type, blk->id);
}
}
}
@@ -623,13 +644,11 @@
lm[i]->rsvp_nxt = rsvp;
pp[i]->rsvp_nxt = rsvp;
- MSM_EVTMSG(rm->dev, lm[i]->type_name, rsvp->enc_id, lm[i]->id);
- MSM_EVTMSG(rm->dev, pp[i]->type_name, rsvp->enc_id, pp[i]->id);
- if (dspp[i]) {
+ if (dspp[i])
dspp[i]->rsvp_nxt = rsvp;
- MSM_EVTMSG(rm->dev, dspp[i]->type_name, rsvp->enc_id,
- dspp[i]->id);
- }
+
+ SDE_EVT32(lm[i]->type, rsvp->enc_id, lm[i]->id, pp[i]->id,
+ dspp[i] ? dspp[i]->id : 0);
}
return 0;
@@ -678,8 +697,7 @@
for (i = 0; i < ARRAY_SIZE(ctls) && i < reqs->num_ctl; i++) {
ctls[i]->rsvp_nxt = rsvp;
- MSM_EVTMSG(rm->dev, ctls[i]->type_name, rsvp->enc_id,
- ctls[i]->id);
+ SDE_EVT32(ctls[i]->type, rsvp->enc_id, ctls[i]->id);
}
return 0;
@@ -716,8 +734,7 @@
continue;
iter.blk->rsvp_nxt = rsvp;
- MSM_EVTMSG(rm->dev, iter.blk->type_name, rsvp->enc_id,
- iter.blk->id);
+ SDE_EVT32(iter.blk->type, rsvp->enc_id, iter.blk->id);
break;
}
@@ -751,8 +768,7 @@
}
iter.blk->rsvp_nxt = rsvp;
- MSM_EVTMSG(rm->dev, iter.blk->type_name,
- rsvp->enc_id, iter.blk->id);
+ SDE_EVT32(iter.blk->type, rsvp->enc_id, iter.blk->id);
break;
}
@@ -951,9 +967,10 @@
mode->hdisplay, rm->lm_max_width);
SDE_DEBUG("num_lm %d num_ctl %d topology_name %d\n", reqs->num_lm,
reqs->num_ctl, reqs->top_name);
- MSM_EVT(rm->dev, mode->hdisplay, rm->lm_max_width);
- MSM_EVT(rm->dev, reqs->num_lm, reqs->top_ctrl);
- MSM_EVT(rm->dev, reqs->top_name, 0);
+ SDE_DEBUG("num_lm %d topology_name %d\n", reqs->num_lm,
+ reqs->top_name);
+ SDE_EVT32(mode->hdisplay, rm->lm_max_width, reqs->num_lm,
+ reqs->top_ctrl, reqs->top_name, reqs->num_ctl);
return 0;
}
@@ -1111,7 +1128,7 @@
if (!ret) {
SDE_DEBUG("rsrv enc %d topology %d\n", rsvp->enc_id,
rsvp->topology);
- MSM_EVT(rm->dev, rsvp->enc_id, rsvp->topology);
+ SDE_EVT32(rsvp->enc_id, rsvp->topology);
}
return ret;
@@ -1151,9 +1168,9 @@
SDE_DEBUG("reserving hw for conn %d enc %d crtc %d test_only %d\n",
conn_state->connector->base.id, enc->base.id,
crtc_state->crtc->base.id, test_only);
- MSM_EVT(rm->dev, enc->base.id, conn_state->connector->base.id);
+ SDE_EVT32(enc->base.id, conn_state->connector->base.id);
- _sde_rm_print_rsvps(rm, "begin_reserve");
+ _sde_rm_print_rsvps(rm, SDE_RM_STAGE_BEGIN);
ret = _sde_rm_populate_requirements(rm, enc, crtc_state,
conn_state, &reqs);
@@ -1188,14 +1205,14 @@
rsvp_cur->seq, rsvp_cur->enc_id);
_sde_rm_release_rsvp(rm, rsvp_cur, conn_state->connector);
rsvp_cur = NULL;
- _sde_rm_print_rsvps(rm, "post_clear");
+ _sde_rm_print_rsvps(rm, SDE_RM_STAGE_AFTER_CLEAR);
}
/* Check the proposed reservation, store it in hw's "next" field */
ret = _sde_rm_make_next_rsvp(rm, enc, crtc_state, conn_state,
rsvp_nxt, &reqs);
- _sde_rm_print_rsvps(rm, "new_rsvp_next");
+ _sde_rm_print_rsvps(rm, SDE_RM_STAGE_AFTER_RSVPNEXT);
if (ret) {
SDE_ERROR("failed to reserve hw resources: %d\n", ret);
@@ -1219,7 +1236,7 @@
ret = _sde_rm_commit_rsvp(rm, rsvp_nxt, conn_state);
}
- _sde_rm_print_rsvps(rm, "final");
+ _sde_rm_print_rsvps(rm, SDE_RM_STAGE_FINAL);
return ret;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_vbif.c b/drivers/gpu/drm/msm/sde/sde_vbif.c
index 6060bde..3171fcb 100644
--- a/drivers/gpu/drm/msm/sde/sde_vbif.c
+++ b/drivers/gpu/drm/msm/sde/sde_vbif.c
@@ -198,7 +198,7 @@
ret = _sde_vbif_wait_for_xin_halt(vbif, params->xin_id);
if (ret)
- MSM_EVT(sde_kms->dev, vbif->idx, params->xin_id);
+ SDE_EVT32(vbif->idx, params->xin_id);
vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);
diff --git a/drivers/gpu/drm/msm/sde_dbg.h b/drivers/gpu/drm/msm/sde_dbg.h
new file mode 100644
index 0000000..f543168
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde_dbg.h
@@ -0,0 +1,55 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef SDE_DBG_H_
+#define SDE_DBG_H_
+
+#include <stdarg.h>
+#include <linux/debugfs.h>
+#include <linux/list.h>
+
+#define SDE_EVTLOG_DATA_LIMITER (-1)
+#define SDE_EVTLOG_FUNC_ENTRY 0x1111
+#define SDE_EVTLOG_FUNC_EXIT 0x2222
+
+enum sde_dbg_evtlog_flag {
+ SDE_EVTLOG_DEFAULT = BIT(0),
+ SDE_EVTLOG_IRQ = BIT(1),
+ SDE_EVTLOG_ALL = BIT(7)
+};
+
+/**
+ * SDE_EVT32 - Write an list of 32bit values as an event into the event log
+ * ... - variable arguments
+ */
+#define SDE_EVT32(...) sde_evtlog(__func__, __LINE__, SDE_EVTLOG_DEFAULT, \
+ ##__VA_ARGS__, SDE_EVTLOG_DATA_LIMITER)
+#define SDE_EVT32_IRQ(...) sde_evtlog(__func__, __LINE__, SDE_EVTLOG_IRQ, \
+ ##__VA_ARGS__, SDE_EVTLOG_DATA_LIMITER)
+
+
+#if defined(CONFIG_DEBUG_FS)
+
+int sde_evtlog_init(struct dentry *debugfs_root);
+void sde_evtlog_destroy(void);
+void sde_evtlog(const char *name, int line, int flag, ...);
+#else
+
+static inline int sde_evtlog_init(struct dentry *debugfs_root)
+{
+ return 0;
+}
+static inline void sde_evtlog(const char *name, int line, flag, ...) { }
+void sde_evtlog_destroy(void) { }
+#endif
+
+#endif /* SDE_DBG_H_ */
diff --git a/drivers/gpu/drm/msm/sde_dbg_evtlog.c b/drivers/gpu/drm/msm/sde_dbg_evtlog.c
new file mode 100644
index 0000000..d27e144
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde_dbg_evtlog.c
@@ -0,0 +1,275 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "sde_evtlog:[%s] " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/ktime.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/dma-buf.h>
+
+#include "sde_dbg.h"
+#include "sde_trace.h"
+
+#ifdef CONFIG_DRM_SDE_EVTLOG_DEBUG
+#define EVTLOG_DEFAULT_ENABLE 1
+#else
+#define EVTLOG_DEFAULT_ENABLE 0
+#endif
+
+#define EVTLOG_DEFAULT_PANIC 1
+
+/*
+ * evtlog will print this number of entries when it is called through
+ * sysfs node or panic. This prevents kernel log from evtlog message
+ * flood.
+ */
+#define SDE_EVTLOG_PRINT_ENTRY 256
+
+/*
+ * evtlog keeps this number of entries in memory for debug purpose. This
+ * number must be greater than print entry to prevent out of bound evtlog
+ * entry array access.
+ */
+#define SDE_EVTLOG_ENTRY (SDE_EVTLOG_PRINT_ENTRY * 4)
+#define SDE_EVTLOG_MAX_DATA 15
+#define SDE_EVTLOG_BUF_MAX 512
+#define SDE_EVTLOG_BUF_ALIGN 32
+
+DEFINE_SPINLOCK(sde_evtloglock);
+
+struct tlog {
+ u32 counter;
+ s64 time;
+ const char *name;
+ int line;
+ u32 data[SDE_EVTLOG_MAX_DATA];
+ u32 data_cnt;
+ int pid;
+};
+
+static struct sde_dbg_evtlog {
+ struct tlog logs[SDE_EVTLOG_ENTRY];
+ u32 first;
+ u32 last;
+ u32 curr;
+ struct dentry *evtlog;
+ u32 evtlog_enable;
+ u32 panic_on_err;
+} sde_dbg_evtlog;
+
+static inline bool sde_evtlog_is_enabled(u32 flag)
+{
+ return (flag & sde_dbg_evtlog.evtlog_enable) ||
+ (flag == SDE_EVTLOG_ALL && sde_dbg_evtlog.evtlog_enable);
+}
+
+void sde_evtlog(const char *name, int line, int flag, ...)
+{
+ unsigned long flags;
+ int i, val = 0;
+ va_list args;
+ struct tlog *log;
+
+ if (!sde_evtlog_is_enabled(flag))
+ return;
+
+ spin_lock_irqsave(&sde_evtloglock, flags);
+ log = &sde_dbg_evtlog.logs[sde_dbg_evtlog.curr];
+ log->time = ktime_to_us(ktime_get());
+ log->name = name;
+ log->line = line;
+ log->data_cnt = 0;
+ log->pid = current->pid;
+
+ va_start(args, flag);
+ for (i = 0; i < SDE_EVTLOG_MAX_DATA; i++) {
+
+ val = va_arg(args, int);
+ if (val == SDE_EVTLOG_DATA_LIMITER)
+ break;
+
+ log->data[i] = val;
+ }
+ va_end(args);
+ log->data_cnt = i;
+ sde_dbg_evtlog.curr = (sde_dbg_evtlog.curr + 1) % SDE_EVTLOG_ENTRY;
+ sde_dbg_evtlog.last++;
+
+ trace_sde_evtlog(name, line, i > 0 ? log->data[0] : 0,
+ i > 1 ? log->data[1] : 0);
+
+ spin_unlock_irqrestore(&sde_evtloglock, flags);
+}
+
+/* always dump the last entries which are not dumped yet */
+static bool __sde_evtlog_dump_calc_range(void)
+{
+ static u32 next;
+ bool need_dump = true;
+ unsigned long flags;
+ struct sde_dbg_evtlog *evtlog = &sde_dbg_evtlog;
+
+ spin_lock_irqsave(&sde_evtloglock, flags);
+
+ evtlog->first = next;
+
+ if (evtlog->last == evtlog->first) {
+ need_dump = false;
+ goto dump_exit;
+ }
+
+ if (evtlog->last < evtlog->first) {
+ evtlog->first %= SDE_EVTLOG_ENTRY;
+ if (evtlog->last < evtlog->first)
+ evtlog->last += SDE_EVTLOG_ENTRY;
+ }
+
+ if ((evtlog->last - evtlog->first) > SDE_EVTLOG_PRINT_ENTRY) {
+ pr_warn("evtlog buffer overflow before dump: %d\n",
+ evtlog->last - evtlog->first);
+ evtlog->first = evtlog->last - SDE_EVTLOG_PRINT_ENTRY;
+ }
+ next = evtlog->first + 1;
+
+dump_exit:
+ spin_unlock_irqrestore(&sde_evtloglock, flags);
+
+ return need_dump;
+}
+
+static ssize_t sde_evtlog_dump_entry(char *evtlog_buf, ssize_t evtlog_buf_size)
+{
+ int i;
+ ssize_t off = 0;
+ struct tlog *log, *prev_log;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sde_evtloglock, flags);
+
+ log = &sde_dbg_evtlog.logs[sde_dbg_evtlog.first %
+ SDE_EVTLOG_ENTRY];
+
+ prev_log = &sde_dbg_evtlog.logs[(sde_dbg_evtlog.first - 1) %
+ SDE_EVTLOG_ENTRY];
+
+ off = snprintf((evtlog_buf + off), (evtlog_buf_size - off), "%s:%-4d",
+ log->name, log->line);
+
+ if (off < SDE_EVTLOG_BUF_ALIGN) {
+ memset((evtlog_buf + off), 0x20, (SDE_EVTLOG_BUF_ALIGN - off));
+ off = SDE_EVTLOG_BUF_ALIGN;
+ }
+
+ off += snprintf((evtlog_buf + off), (evtlog_buf_size - off),
+ "=>[%-8d:%-11llu:%9llu][%-4d]:", sde_dbg_evtlog.first,
+ log->time, (log->time - prev_log->time), log->pid);
+
+ for (i = 0; i < log->data_cnt; i++)
+ off += snprintf((evtlog_buf + off), (evtlog_buf_size - off),
+ "%x ", log->data[i]);
+
+ off += snprintf((evtlog_buf + off), (evtlog_buf_size - off), "\n");
+
+ spin_unlock_irqrestore(&sde_evtloglock, flags);
+
+ return off;
+}
+
+static void sde_evtlog_dump_all(void)
+{
+ char evtlog_buf[SDE_EVTLOG_BUF_MAX];
+
+ while (__sde_evtlog_dump_calc_range()) {
+ sde_evtlog_dump_entry(evtlog_buf, SDE_EVTLOG_BUF_MAX);
+ pr_info("%s", evtlog_buf);
+ }
+}
+
+static int sde_evtlog_dump_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t sde_evtlog_dump_read(struct file *file, char __user *buff,
+ size_t count, loff_t *ppos)
+{
+ ssize_t len = 0;
+ char evtlog_buf[SDE_EVTLOG_BUF_MAX];
+
+ if (__sde_evtlog_dump_calc_range()) {
+ len = sde_evtlog_dump_entry(evtlog_buf, SDE_EVTLOG_BUF_MAX);
+ if (copy_to_user(buff, evtlog_buf, len))
+ return -EFAULT;
+ *ppos += len;
+ }
+
+ return len;
+}
+
+static ssize_t sde_evtlog_dump_write(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ sde_evtlog_dump_all();
+
+ if (sde_dbg_evtlog.panic_on_err)
+ panic("sde");
+
+ return count;
+}
+
+static const struct file_operations sde_evtlog_fops = {
+ .open = sde_evtlog_dump_open,
+ .read = sde_evtlog_dump_read,
+ .write = sde_evtlog_dump_write,
+};
+
+int sde_evtlog_init(struct dentry *debugfs_root)
+{
+ int i;
+
+ sde_dbg_evtlog.evtlog = debugfs_create_dir("evt_dbg", debugfs_root);
+ if (IS_ERR_OR_NULL(sde_dbg_evtlog.evtlog)) {
+ pr_err("debugfs_create_dir fail, error %ld\n",
+ PTR_ERR(sde_dbg_evtlog.evtlog));
+ sde_dbg_evtlog.evtlog = NULL;
+ return -ENODEV;
+ }
+
+ for (i = 0; i < SDE_EVTLOG_ENTRY; i++)
+ sde_dbg_evtlog.logs[i].counter = i;
+
+ debugfs_create_file("dump", 0644, sde_dbg_evtlog.evtlog, NULL,
+ &sde_evtlog_fops);
+ debugfs_create_u32("enable", 0644, sde_dbg_evtlog.evtlog,
+ &sde_dbg_evtlog.evtlog_enable);
+ debugfs_create_u32("panic", 0644, sde_dbg_evtlog.evtlog,
+ &sde_dbg_evtlog.panic_on_err);
+
+ sde_dbg_evtlog.evtlog_enable = EVTLOG_DEFAULT_ENABLE;
+ sde_dbg_evtlog.panic_on_err = EVTLOG_DEFAULT_PANIC;
+
+ pr_info("evtlog_status: enable:%d, panic:%d\n",
+ sde_dbg_evtlog.evtlog_enable, sde_dbg_evtlog.panic_on_err);
+
+ return 0;
+}
+
+void sde_evtlog_destroy(void)
+{
+ debugfs_remove(sde_dbg_evtlog.evtlog);
+}