diff options
| author | Lloyd Atkinson <latkinso@codeaurora.org> | 2016-09-06 08:34:13 -0400 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-11-18 12:26:29 -0800 |
| commit | b6f15c90b6a4e5998dbcf0d7187693f3cd5010ca (patch) | |
| tree | aea61dad0ce0dc61308db49288a3a658e10ea949 /drivers/gpu | |
| parent | 90607cb04fc744925cd1039c82b8cdf120ef8ddd (diff) | |
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>
Diffstat (limited to 'drivers/gpu')
21 files changed, 460 insertions, 398 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index f756c0c59ffa..bb95fad7d7b8 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -43,7 +43,8 @@ msm_drm-y := \ 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) @@ -124,7 +125,6 @@ msm_drm-$(CONFIG_DRM_MSM) += \ 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 014d4715f3f6..46e262f09780 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -240,6 +240,8 @@ static int msm_unload(struct drm_device *dev) priv->vram.paddr, &attrs); } + sde_evtlog_destroy(); + component_unbind_all(dev->dev, dev); dev->dev_private = NULL; @@ -391,6 +393,12 @@ static int msm_load(struct drm_device *dev, unsigned long flags) if (ret) goto fail; + 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: kms = mdp4_kms_init(dev); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 78c6120eb2a5..ed19330f91bc 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -50,7 +50,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) @@ -327,25 +326,10 @@ struct msm_drm_private { struct msm_vblank_ctrl vblank_ctrl; - 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; }; @@ -368,6 +352,7 @@ int msm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool async); int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu); +void msm_unregister_all_mmu(struct drm_device *dev); int msm_wait_fence(struct drm_device *dev, uint32_t fence, ktime_t *timeout, bool interruptible); diff --git a/drivers/gpu/drm/msm/msm_evtlog.c b/drivers/gpu/drm/msm/msm_evtlog.c deleted file mode 100644 index f501f55da329..000000000000 --- a/drivers/gpu/drm/msm/msm_evtlog.c +++ /dev/null @@ -1,176 +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. - */ - -#define pr_fmt(fmt) "msm_evtlog:[%s] " fmt, __func__ - -#include "msm_evtlog.h" -#include <linux/slab.h> -#include <linux/sched.h> -#include <asm-generic/current.h> -#include <linux/uaccess.h> -#include <linux/debugfs.h> - -#include "sde_trace.h" - -#define SIZE_MASK(x) (x - 1) - -static int msm_evtlog_debugfs_dump(struct seq_file *s, void *data) -{ - struct msm_evtlog *log = s->private; - unsigned long cnt; /* # of samples since clear */ - unsigned long n; /* # of samples to print, also head index */ - unsigned long i; - struct timespec timespec; - - /** - * Prints in chronological order, oldest -> newest - * Note due to lock-less design, the first few printed entries - * may be corrupted by new writer not oldest. - * This is a tradeoff for speed of sampling - */ - cnt = atomic_read(&log->cnt); - if (!cnt) - return 0; - - n = cnt & SIZE_MASK(log->size); - - /** - * If not full, print from first log - * (which is index 1 since atomic_inc_return is prefix operator) - */ - i = (cnt < log->size) ? 0 : n; - - seq_puts(s, "time_ns, pid, func, line, val1, val2, msg\n"); - do { - i = (i + 1) & SIZE_MASK(log->size); - timespec = ktime_to_timespec(log->events[i].ktime); - seq_printf(s, "[%5lu.%06lu], %d, %s, %d, %llu, %llu, %s\n", - timespec.tv_sec, - timespec.tv_nsec / 1000, - log->events[i].pid, - log->events[i].func, - log->events[i].line, - log->events[i].val1, - log->events[i].val2, - log->events[i].msg); - } while (i != n); - - return 0; -} - -static int msm_evtlog_debugfs_open_dump(struct inode *inode, struct file *file) -{ - return single_open(file, msm_evtlog_debugfs_dump, inode->i_private); -} - -static ssize_t msm_evtlog_debugfs_write( - struct file *file, - const char __user *user_buf, - size_t size, - loff_t *ppos) -{ - struct seq_file *s = file->private_data; - struct msm_evtlog *log = s->private; - char buf[64]; - int buf_size; - - buf_size = min(size, (sizeof(buf) - 1)); - if (strncpy_from_user(buf, user_buf, buf_size) < 0) - return -EFAULT; - buf[buf_size] = 0; - - if (strcmp(buf, "0") == 0) - atomic_set(&log->cnt, 0); - - return size; - -} - -static const struct file_operations msm_evtlog_fops = { - .open = msm_evtlog_debugfs_open_dump, - .read = seq_read, - .write = msm_evtlog_debugfs_write, - .llseek = seq_lseek, - .release = single_release, -}; - -int msm_evtlog_init( - struct msm_evtlog *log, - int size, - struct dentry *parent) -{ - if (!log || size < 1) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - memset(log, 0, sizeof(*log)); - log->size = roundup_pow_of_two(size); - log->events = kcalloc(log->size, sizeof(struct msm_evtlog_evt), - GFP_KERNEL); - - if (!log->events) { - pr_err("Insufficient memory\n"); - return -ENOMEM; - } - - atomic_set(&log->cnt, 0); - - log->dentry = debugfs_create_file("evtlog", S_IRUGO | S_IWUSR, parent, - log, &msm_evtlog_fops); - - if (IS_ERR_OR_NULL(log->dentry)) { - int rc = PTR_ERR(log->dentry); - - pr_err("debugfs create file failed, rc=%d\n", rc); - kfree(log->events); - return rc; - } - - return 0; -} - -void msm_evtlog_destroy(struct msm_evtlog *log) -{ - debugfs_remove(log->dentry); - - /* Caller needs to make sure that log sampling has stopped */ - kfree(log->events); - -} - -void msm_evtlog_sample( - struct msm_evtlog *log, - const char *func, - const char *msg, - uint64_t val1, - uint64_t val2, - uint32_t line) -{ - unsigned long i; - - /** - * Since array sized with pow of 2, roll to 0 when cnt overflows - * mod the value with the size to get current idx into array - */ - i = (unsigned long)(atomic_inc_return(&log->cnt)) & - SIZE_MASK(log->size); - log->events[i].ktime = ktime_get(); - log->events[i].func = func; - log->events[i].msg = msg; - log->events[i].val1 = val1; - log->events[i].val2 = val2; - log->events[i].line = line; - log->events[i].pid = current->pid; - - trace_sde_evtlog(func, line, val1, val2); -} diff --git a/drivers/gpu/drm/msm/msm_evtlog.h b/drivers/gpu/drm/msm/msm_evtlog.h deleted file mode 100644 index 83512899b1e9..000000000000 --- 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 6bc69cb1e578..ac9997c238cd 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -519,7 +519,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, "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 a75c2fc07f04..b2853e874d92 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 @@ static int _sde_core_irq_enable(struct sde_kms *sde_kms, int irq_idx) 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 @@ static int _sde_core_irq_disable(struct sde_kms *sde_kms, int irq_idx) 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 @@ int sde_core_irq_register_callback(struct sde_kms *sde_kms, int irq_idx, 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 @@ int sde_core_irq_unregister_callback(struct sde_kms *sde_kms, int irq_idx, 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 8766617415f1..8cade4dbfb23 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -309,7 +309,7 @@ void sde_crtc_prepare_commit(struct drm_crtc *crtc, 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; @@ -358,7 +358,7 @@ static void _sde_crtc_complete_flip(struct drm_crtc *crtc, 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); } } @@ -378,7 +378,7 @@ static void sde_crtc_vblank_cb(void *data) 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, @@ -395,7 +395,7 @@ void sde_crtc_complete_commit(struct drm_crtc *crtc, 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); @@ -994,7 +994,7 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en) 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, @@ -1375,8 +1375,8 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) 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 3598b2b03913..79dc48a6c899 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -286,7 +286,7 @@ static int sde_encoder_virt_atomic_check( 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 @@ static int sde_encoder_virt_atomic_check( 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 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, 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 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) 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 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) 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]; @@ -578,7 +577,7 @@ void sde_encoder_register_vblank_callback(struct drm_encoder *drm_enc, 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; @@ -608,7 +607,7 @@ static void sde_encoder_handle_phys_enc_ready_for_kickoff( 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); } } @@ -643,7 +642,7 @@ static inline void _sde_encoder_trigger_flush(struct drm_encoder *drm_enc, 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); } /** @@ -678,9 +677,7 @@ void sde_encoder_helper_trigger_start(struct sde_encoder_phys *phys_enc) } 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); } /** @@ -746,7 +743,7 @@ void sde_encoder_schedule_kickoff(struct drm_encoder *drm_enc) 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; @@ -767,7 +764,7 @@ void sde_encoder_schedule_kickoff(struct drm_encoder *drm_enc) } 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 24e85289fae8..9dcd4d4114b3 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 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx) 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 @@ static int sde_encoder_phys_cmd_control_vblank_irq( __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 @@ static void sde_encoder_phys_cmd_prepare_for_kickoff( "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 f043a4a02904..e67e7473f0e0 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( @@ -501,7 +499,7 @@ static int sde_encoder_phys_vid_control_vblank_irq( __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) @@ -686,18 +684,20 @@ static int sde_encoder_phys_vid_wait_for_commit_done( 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; } @@ -735,7 +735,7 @@ static void sde_encoder_phys_vid_handle_post_kickoff( * 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 418abf2c4c31..9b621c41b939 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 @@ static int sde_encoder_phys_wb_wait_for_commit_done( 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 @@ static int sde_encoder_phys_wb_wait_for_commit_done( 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 @@ static void sde_encoder_phys_wb_prepare_for_kickoff( /* 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 @@ static void sde_encoder_phys_wb_handle_post_kickoff( 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 23e5614ac1d6..6db6f989006f 100644 --- a/drivers/gpu/drm/msm/sde/sde_fence.c +++ b/drivers/gpu/drm/msm/sde/sde_fence.c @@ -105,14 +105,15 @@ exit: /** * 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 @@ int sde_fence_init(void *dev, 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 @@ int sde_fence_prepare(struct sde_fence *fence) 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 @@ int sde_fence_create(struct sde_fence *fence, uint64_t *val, int offset) 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 @@ void sde_fence_signal(struct sde_fence *fence, bool is_error) 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 b5980b4e5b32..113d16b916f7 100644 --- a/drivers/gpu/drm/msm/sde/sde_fence.h +++ b/drivers/gpu/drm/msm/sde/sde_fence.h @@ -85,30 +85,30 @@ static inline uint32_t sde_sync_get_name_prefix(void *fence) /** * 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 @@ int sde_fence_create(struct sde_fence *fence, uint64_t *val, int offset); */ 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 40a594df7c5b..e60d6c2ab789 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_prepare_commit(struct msm_kms *kms, 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 @@ static void sde_complete_commit(struct msm_kms *kms, 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 @@ static void sde_wait_for_commit_done(struct msm_kms *kms, * 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 @@ struct msm_kms *sde_kms_init(struct drm_device *dev) * '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 0ce002b1dd73..af5c9538f75b 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 d97d89624689..dd8cd05511f3 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -491,10 +491,7 @@ int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms) 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 e1e63dda5437..075e9d69af8f 100644 --- a/drivers/gpu/drm/msm/sde/sde_rm.c +++ b/drivers/gpu/drm/msm/sde/sde_rm.c @@ -92,29 +92,50 @@ struct sde_rm_hw_blk { 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 @@ static int _sde_rm_reserve_lms( 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 @@ static int _sde_rm_reserve_ctls( 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 @@ static int _sde_rm_reserve_cdm( 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 @@ static int _sde_rm_reserve_intf_or_wb( } 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 @@ static int _sde_rm_populate_requirements( 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 @@ static int _sde_rm_commit_rsvp( 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 @@ int sde_rm_reserve( 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 @@ int sde_rm_reserve( 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 @@ int sde_rm_reserve( 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 4e6c0ebf04e2..31ac9f39f62e 100644 --- a/drivers/gpu/drm/msm/sde/sde_vbif.c +++ b/drivers/gpu/drm/msm/sde/sde_vbif.c @@ -198,7 +198,7 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms, 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 000000000000..f543168d3855 --- /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 000000000000..d27e1446e0c1 --- /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); +} |
