From 445c38ef473b57dabbc71cfc7fa491b6136a456d Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Wed, 17 May 2017 17:44:55 +0800 Subject: drm/rockchip: vop: support vop dump when iommu page fault Change-Id: I164fc7e8cb7392143959d53709bcdf61713fb3d8 Signed-off-by: Mark Yao --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 26 +++++++++ drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 82 +++++++++++++++++++---------- 3 files changed, 82 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index c65d88919d73..07b3bc67af55 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -775,6 +775,29 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev, priv->crtc_funcs[pipe]->disable_vblank(crtc); } +static int rockchip_drm_fault_handler(struct iommu_domain *iommu, + struct device *dev, + unsigned long iova, int flags, void *arg) +{ + struct drm_device *drm_dev = arg; + struct rockchip_drm_private *priv = drm_dev->dev_private; + struct drm_crtc *crtc; + + drm_for_each_crtc(crtc, drm_dev) { + int pipe = drm_crtc_index(crtc); + + if (priv->crtc_funcs[pipe] && + priv->crtc_funcs[pipe]->regs_dump) + priv->crtc_funcs[pipe]->regs_dump(crtc, NULL); + + if (priv->crtc_funcs[pipe] && + priv->crtc_funcs[pipe]->debugfs_dump) + priv->crtc_funcs[pipe]->debugfs_dump(crtc, NULL); + } + + return 0; +} + static int rockchip_drm_init_iommu(struct drm_device *drm_dev) { struct rockchip_drm_private *private = drm_dev->dev_private; @@ -797,6 +820,9 @@ static int rockchip_drm_init_iommu(struct drm_device *drm_dev) drm_mm_init(&private->mm, start, end - start + 1); mutex_init(&private->mm_lock); + iommu_set_fault_handler(private->domain, rockchip_drm_fault_handler, + drm_dev); + return 0; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index f41cf66dfd91..0cb9d0962bc0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -45,6 +45,7 @@ struct rockchip_crtc_funcs { void (*wait_for_update)(struct drm_crtc *crtc); void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file *file_priv); int (*debugfs_dump)(struct drm_crtc *crtc, struct seq_file *s); + void (*regs_dump)(struct drm_crtc *crtc, struct seq_file *s); enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc, const struct drm_display_mode *mode, int output_type); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 706fc973e94f..0999af2744c6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1465,6 +1465,14 @@ static int vop_crtc_loader_protect(struct drm_crtc *crtc, bool on) return 0; } +#define DEBUG_PRINT(args...) \ + do { \ + if (s) \ + seq_printf(s, args); \ + else \ + printk(args); \ + } while (0) + static int vop_plane_info_dump(struct seq_file *s, struct drm_plane *plane) { struct vop_win *win = to_vop_win(plane); @@ -1474,27 +1482,27 @@ static int vop_plane_info_dump(struct seq_file *s, struct drm_plane *plane) struct drm_framebuffer *fb = state->fb; int i; - seq_printf(s, " win%d-%d: %s\n", win->win_id, win->area_id, - pstate->enable ? "ACTIVE" : "DISABLED"); + DEBUG_PRINT(" win%d-%d: %s\n", win->win_id, win->area_id, + pstate->enable ? "ACTIVE" : "DISABLED"); if (!fb) return 0; src = &pstate->src; dest = &pstate->dest; - seq_printf(s, "\tformat: %s%s\n", drm_get_format_name(fb->pixel_format), - fb->modifier[0] == DRM_FORMAT_MOD_ARM_AFBC ? "[AFBC]" : ""); - seq_printf(s, "\tzpos: %d\n", pstate->zpos); - seq_printf(s, "\tsrc: pos[%dx%d] rect[%dx%d]\n", src->x1 >> 16, - src->y1 >> 16, drm_rect_width(src) >> 16, - drm_rect_height(src) >> 16); - seq_printf(s, "\tdst: pos[%dx%d] rect[%dx%d]\n", dest->x1, dest->y1, - drm_rect_width(dest), drm_rect_height(dest)); + DEBUG_PRINT("\tformat: %s%s\n", drm_get_format_name(fb->pixel_format), + fb->modifier[0] == DRM_FORMAT_MOD_ARM_AFBC ? "[AFBC]" : ""); + DEBUG_PRINT("\tzpos: %d\n", pstate->zpos); + DEBUG_PRINT("\tsrc: pos[%dx%d] rect[%dx%d]\n", src->x1 >> 16, + src->y1 >> 16, drm_rect_width(src) >> 16, + drm_rect_height(src) >> 16); + DEBUG_PRINT("\tdst: pos[%dx%d] rect[%dx%d]\n", dest->x1, dest->y1, + drm_rect_width(dest), drm_rect_height(dest)); for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { dma_addr_t fb_addr = rockchip_fb_get_dma_addr(fb, i); - seq_printf(s, "\tbuf[%d]: addr: %pad pitch: %d offset: %d\n", - i, &fb_addr, fb->pitches[i], fb->offsets[i]); + DEBUG_PRINT("\tbuf[%d]: addr: %pad pitch: %d offset: %d\n", + i, &fb_addr, fb->pitches[i], fb->offsets[i]); } return 0; @@ -1510,25 +1518,25 @@ static int vop_crtc_debugfs_dump(struct drm_crtc *crtc, struct seq_file *s) struct drm_plane *plane; int i; - seq_printf(s, "VOP [%s]: %s\n", dev_name(vop->dev), - crtc_state->active ? "ACTIVE" : "DISABLED"); + DEBUG_PRINT("VOP [%s]: %s\n", dev_name(vop->dev), + crtc_state->active ? "ACTIVE" : "DISABLED"); if (!crtc_state->active) return 0; - seq_printf(s, " Connector: %s\n", - drm_get_connector_name(state->output_type)); - seq_printf(s, "\tbus_format[%x] output_mode[%x]\n", - state->bus_format, state->output_mode); - seq_printf(s, " Display mode: %dx%d%s%d\n", - mode->hdisplay, mode->vdisplay, interlaced ? "i" : "p", - drm_mode_vrefresh(mode)); - seq_printf(s, "\tclk[%d] real_clk[%d] type[%x] flag[%x]\n", - mode->clock, mode->crtc_clock, mode->type, mode->flags); - seq_printf(s, "\tH: %d %d %d %d\n", mode->hdisplay, mode->hsync_start, - mode->hsync_end, mode->htotal); - seq_printf(s, "\tV: %d %d %d %d\n", mode->vdisplay, mode->vsync_start, - mode->vsync_end, mode->vtotal); + DEBUG_PRINT(" Connector: %s\n", + drm_get_connector_name(state->output_type)); + DEBUG_PRINT("\tbus_format[%x] output_mode[%x]\n", + state->bus_format, state->output_mode); + DEBUG_PRINT(" Display mode: %dx%d%s%d\n", + mode->hdisplay, mode->vdisplay, interlaced ? "i" : "p", + drm_mode_vrefresh(mode)); + DEBUG_PRINT("\tclk[%d] real_clk[%d] type[%x] flag[%x]\n", + mode->clock, mode->crtc_clock, mode->type, mode->flags); + DEBUG_PRINT("\tH: %d %d %d %d\n", mode->hdisplay, mode->hsync_start, + mode->hsync_end, mode->htotal); + DEBUG_PRINT("\tV: %d %d %d %d\n", mode->vdisplay, mode->vsync_start, + mode->vsync_end, mode->vtotal); for (i = 0; i < vop->num_wins; i++) { plane = &vop->win[i].base; @@ -1538,6 +1546,25 @@ static int vop_crtc_debugfs_dump(struct drm_crtc *crtc, struct seq_file *s) return 0; } +static void vop_crtc_regs_dump(struct drm_crtc *crtc, struct seq_file *s) +{ + struct vop *vop = to_vop(crtc); + struct drm_crtc_state *crtc_state = crtc->state; + int dump_len = vop->len > 0x400 ? 0x400 : vop->len; + int i; + + if (!crtc_state->active) + return; + + for (i = 0; i < dump_len; i += 4) { + if (i % 16 == 0) + DEBUG_PRINT("\n0x%08x: ", i); + DEBUG_PRINT("%08x ", vop_readl(vop, i)); + } +} + +#undef DEBUG_PRINT + static enum drm_mode_status vop_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode, int output_type) @@ -1574,6 +1601,7 @@ static const struct rockchip_crtc_funcs private_crtc_funcs = { .wait_for_update = vop_crtc_wait_for_update, .cancel_pending_vblank = vop_crtc_cancel_pending_vblank, .debugfs_dump = vop_crtc_debugfs_dump, + .regs_dump = vop_crtc_regs_dump, .mode_valid = vop_crtc_mode_valid, }; -- cgit v1.2.3