From 5c972394c0d93c587482dd5fb172dab6939235f2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 11 Dec 2015 19:45:03 -0800 Subject: [PATCH 1/8] drm: Use the driver's gem_object_free function from CMA helpers. VC4 wraps the CMA objects in its own structures, so it needs to do its own teardown (waiting for GPU to finish, updating bo_stats tracking). The other CMA drivers are using drm_gem_cma_free_object as their gem_free_object, so this should be a no-op for them. Signed-off-by: Eric Anholt (cherry picked from commit a8812101ce0faa865c1b75e461d5f05d8a43b9e3) --- drivers/gpu/drm/drm_fb_cma_helper.c | 6 +++--- drivers/gpu/drm/drm_gem_cma_helper.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 5c1aca443e54f8..99b5673e37c8ad 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -279,7 +279,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, if (!fbi) { dev_err(dev->dev, "Failed to allocate framebuffer info.\n"); ret = -ENOMEM; - goto err_drm_gem_cma_free_object; + goto err_gem_free_object; } fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1); @@ -322,8 +322,8 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, drm_fb_cma_destroy(fb); err_framebuffer_release: framebuffer_release(fbi); -err_drm_gem_cma_free_object: - drm_gem_cma_free_object(&obj->base); +err_gem_free_object: + dev->driver->gem_free_object(&obj->base); return ret; } diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index a2f13aadf8ca19..27cc420e22b3c7 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, return cma_obj; error: - drm_gem_cma_free_object(&cma_obj->base); + drm->driver->gem_free_object(&cma_obj->base); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(drm_gem_cma_create); @@ -171,7 +171,7 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv, return cma_obj; err_handle_create: - drm_gem_cma_free_object(gem_obj); + drm->driver->gem_free_object(gem_obj); return ERR_PTR(ret); } From 22bce4bf11e627b4cecded84027f1cb41407e4c4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 22 Jan 2016 13:06:39 -0800 Subject: [PATCH 2/8] drm/vc4: Add a debugfs node for tracking execution state. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + drivers/gpu/drm/vc4/vc4_drv.h | 1 + drivers/gpu/drm/vc4/vc4_gem.c | 14 ++++++++++++++ 3 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c index d76ad10b07fda3..a99aa8676af774 100644 --- a/drivers/gpu/drm/vc4/vc4_debugfs.c +++ b/drivers/gpu/drm/vc4/vc4_debugfs.c @@ -17,6 +17,7 @@ static const struct drm_info_list vc4_debugfs_list[] = { {"bo_stats", vc4_bo_stats_debugfs, 0}, + {"gem_exec", vc4_gem_exec_debugfs, 0}, {"hdmi_regs", vc4_hdmi_debugfs_regs, 0}, {"hvs_regs", vc4_hvs_debugfs_regs, 0}, {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0}, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 03e037e0dc77ab..d3850e89ce4994 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -403,6 +403,7 @@ void vc4_job_handle_completed(struct vc4_dev *vc4); int vc4_queue_seqno_cb(struct drm_device *dev, struct vc4_seqno_cb *cb, uint64_t seqno, void (*func)(struct vc4_seqno_cb *cb)); +int vc4_gem_exec_debugfs(struct seq_file *m, void *arg); /* vc4_hdmi.c */ extern struct platform_driver vc4_hdmi_driver; diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 39f29e7593342d..1243f4ecee6ea5 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -31,6 +31,20 @@ #include "vc4_regs.h" #include "vc4_trace.h" +#ifdef CONFIG_DEBUG_FS +int vc4_gem_exec_debugfs(struct seq_file *m, void *unused) +{ + struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_device *dev = node->minor->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + + seq_printf(m, "Emitted seqno: 0x%016llx\n", vc4->emit_seqno); + seq_printf(m, "Finished seqno: 0x%016llx\n", vc4->finished_seqno); + + return 0; +} +#endif /* CONFIG_DEBUG_FS */ + static void vc4_queue_hangcheck(struct drm_device *dev) { From 1f38d7592039d31a260b58e61496a92785e5fed1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 25 Jan 2016 13:03:33 -0800 Subject: [PATCH 3/8] drm/vc4: Include vc4_drm.h in uapi in downstream build. Signed-off-by: Eric Anholt --- include/uapi/drm/Kbuild | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild index 2d9a25daab0542..8cb3dbba85241f 100644 --- a/include/uapi/drm/Kbuild +++ b/include/uapi/drm/Kbuild @@ -14,6 +14,7 @@ header-y += radeon_drm.h header-y += savage_drm.h header-y += sis_drm.h header-y += tegra_drm.h +header-y += vc4_drm.h header-y += via_drm.h header-y += vmwgfx_drm.h header-y += msm_drm.h From a10d1c219fa9d4a1d90ec54dc4e5602b0e57639a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 25 Jan 2016 13:05:00 -0800 Subject: [PATCH 4/8] drm/vc4: Validate that WAIT_BO padding is cleared. This is ABI future-proofing if we ever want to extend the pad to mean something. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_gem.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 1243f4ecee6ea5..849d3749268767 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -761,6 +761,9 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_gem_object *gem_obj; struct vc4_bo *bo; + if (args->pad != 0) + return -EINVAL; + gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (!gem_obj) { DRM_ERROR("Failed to look up GEM BO %d\n", args->handle); From d43ffe190e03d1afaa1aab285a6d5e3beb43f2b8 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 25 Jan 2016 13:52:41 -0800 Subject: [PATCH 5/8] drm/vc4: Fix the clear color for the first tile rendered. Apparently in hardware (as opposed to simulation), the clear colors need to be uploaded before the render config, otherwise they won't take effect. Fixes igt's vc4_wait_bo/used-bo-* subtests. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_render_cl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c index 8a2a312e2c1bb6..dea97f45e5aff4 100644 --- a/drivers/gpu/drm/vc4/vc4_render_cl.c +++ b/drivers/gpu/drm/vc4/vc4_render_cl.c @@ -321,15 +321,6 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec, list_add_tail(&to_vc4_bo(&setup->rcl->base)->unref_head, &exec->unref_list); - rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG); - rcl_u32(setup, - (setup->color_write ? (setup->color_write->paddr + - args->color_write.offset) : - 0)); - rcl_u16(setup, args->width); - rcl_u16(setup, args->height); - rcl_u16(setup, args->color_write.bits); - /* The tile buffer gets cleared when the previous tile is stored. If * the clear values changed between frames, then the tile buffer has * stale clear values in it, so we have to do a store in None mode (no @@ -349,6 +340,15 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec, rcl_u32(setup, 0); /* no address, since we're in None mode */ } + rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG); + rcl_u32(setup, + (setup->color_write ? (setup->color_write->paddr + + args->color_write.offset) : + 0)); + rcl_u16(setup, args->width); + rcl_u16(setup, args->height); + rcl_u16(setup, args->color_write.bits); + for (y = min_y_tile; y <= max_y_tile; y++) { for (x = min_x_tile; x <= max_x_tile; x++) { bool first = (x == min_x_tile && y == min_y_tile); From 7fd4b07778384aa7494b4da7c4efdac3a58a79f6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 25 Jan 2016 14:13:12 -0800 Subject: [PATCH 6/8] drm/vc4: Return an ERR_PTR from BO creation instead of NULL. Fixes igt vc4_create_bo/create-bo-0 by returning -EINVAL from the ioctl instead of -ENOMEM. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_bo.c | 23 +++++++++++++---------- drivers/gpu/drm/vc4/vc4_gem.c | 4 ++-- drivers/gpu/drm/vc4/vc4_irq.c | 2 +- drivers/gpu/drm/vc4/vc4_render_cl.c | 4 ++-- drivers/gpu/drm/vc4/vc4_validate.c | 4 ++-- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 6247ff88e6156f..847757914c4eb7 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -213,10 +213,10 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, size_t size = roundup(unaligned_size, PAGE_SIZE); struct vc4_dev *vc4 = to_vc4_dev(dev); struct drm_gem_cma_object *cma_obj; - int pass; + int pass, ret; if (size == 0) - return NULL; + return ERR_PTR(-EINVAL); /* First, try to get a vc4_bo from the kernel BO cache. */ if (from_cache) { @@ -247,14 +247,17 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, * unreferenced BOs to the cache, and then * free the cache. */ - vc4_wait_for_seqno(dev, vc4->emit_seqno, ~0ull, true); + ret = vc4_wait_for_seqno(dev, vc4->emit_seqno, ~0ull, + true); + if (ret) + return ERR_PTR(ret); vc4_job_handle_completed(vc4); vc4_bo_cache_purge(dev); break; case 3: DRM_ERROR("Failed to allocate from CMA:\n"); vc4_bo_stats_dump(vc4); - return NULL; + return ERR_PTR(-ENOMEM); } } @@ -276,8 +279,8 @@ int vc4_dumb_create(struct drm_file *file_priv, args->size = args->pitch * args->height; bo = vc4_bo_create(dev, args->size, false); - if (!bo) - return -ENOMEM; + if (IS_ERR(bo)) + return PTR_ERR(bo); ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); drm_gem_object_unreference_unlocked(&bo->base.base); @@ -460,8 +463,8 @@ int vc4_create_bo_ioctl(struct drm_device *dev, void *data, * get zeroed, and that might leak data between users. */ bo = vc4_bo_create(dev, args->size, false); - if (!bo) - return -ENOMEM; + if (IS_ERR(bo)) + return PTR_ERR(bo); ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); drm_gem_object_unreference_unlocked(&bo->base.base); @@ -513,8 +516,8 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, } bo = vc4_bo_create(dev, args->size, true); - if (!bo) - return -ENOMEM; + if (IS_ERR(bo)) + return PTR_ERR(bo); ret = copy_from_user(bo->base.vaddr, (void __user *)(uintptr_t)args->data, diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 849d3749268767..f8c003aee6e8ba 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -593,9 +593,9 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec) } bo = vc4_bo_create(dev, exec_size, true); - if (!bo) { + if (IS_ERR(bo)) { DRM_ERROR("Couldn't allocate BO for binning\n"); - ret = PTR_ERR(exec->exec_bo); + ret = PTR_ERR(bo); goto fail; } exec->exec_bo = &bo->base; diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index b68060e758dbd2..78a21357fb2de9 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -57,7 +57,7 @@ vc4_overflow_mem_work(struct work_struct *work) struct vc4_bo *bo; bo = vc4_bo_create(dev, 256 * 1024, true); - if (!bo) { + if (IS_ERR(bo)) { DRM_ERROR("Couldn't allocate binner overflow mem\n"); return; } diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c index dea97f45e5aff4..0f12418725e552 100644 --- a/drivers/gpu/drm/vc4/vc4_render_cl.c +++ b/drivers/gpu/drm/vc4/vc4_render_cl.c @@ -316,8 +316,8 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec, size += xtiles * ytiles * loop_body_size; setup->rcl = &vc4_bo_create(dev, size, true)->base; - if (!setup->rcl) - return -ENOMEM; + if (IS_ERR(setup->rcl)) + return PTR_ERR(setup->rcl); list_add_tail(&to_vc4_bo(&setup->rcl->base)->unref_head, &exec->unref_list); diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c index 0fb5b994b9ddb1..839696007e9752 100644 --- a/drivers/gpu/drm/vc4/vc4_validate.c +++ b/drivers/gpu/drm/vc4/vc4_validate.c @@ -401,8 +401,8 @@ validate_tile_binning_config(VALIDATE_ARGS) tile_bo = vc4_bo_create(dev, exec->tile_alloc_offset + tile_alloc_size, true); exec->tile_bo = &tile_bo->base; - if (!exec->tile_bo) - return -ENOMEM; + if (IS_ERR(exec->tile_bo)) + return PTR_ERR(exec->tile_bo); list_add_tail(&tile_bo->unref_head, &exec->unref_list); /* tile alloc address. */ From 775847370e897ef3d12dfe6c2cbc460b1c4b3f19 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 25 Jan 2016 14:32:41 -0800 Subject: [PATCH 7/8] drm/vc4: Fix -ERESTARTSYS error return from BO waits. This caused the wait ioctls to claim that waiting had completed when we actually got interrupted by a signal before it was done. Fixes broken rendering throttling that produced serious lag in X window dragging. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_gem.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index f8c003aee6e8ba..dc3044d8d71f7e 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -352,12 +352,10 @@ vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns, finish_wait(&vc4->job_wait_queue, &wait); trace_vc4_wait_for_seqno_end(dev, seqno); - if (ret && ret != -ERESTARTSYS) { + if (ret && ret != -ERESTARTSYS) DRM_ERROR("timeout waiting for render thread idle\n"); - return ret; - } - return 0; + return ret; } static void From d9233f8090ae5a91adc6d1291f566f03bd99b302 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 25 Jan 2016 14:33:50 -0800 Subject: [PATCH 8/8] drm/vc4: Drop error message on seqno wait timeouts. These ioctls end up getting exposed to userspace, and having normal user requests print DRM errors is obviously wrong. The message was originally to give us some idea of what happened when a hang occurred, but we have a DRM_INFO from reset for that. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_gem.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index dc3044d8d71f7e..a6fa63f0e8a182 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -352,9 +352,6 @@ vc4_wait_for_seqno(struct drm_device *dev, uint64_t seqno, uint64_t timeout_ns, finish_wait(&vc4->job_wait_queue, &wait); trace_vc4_wait_for_seqno_end(dev, seqno); - if (ret && ret != -ERESTARTSYS) - DRM_ERROR("timeout waiting for render thread idle\n"); - return ret; }