From 0338f0d0d70a26adc2236148bb5a78f1fa8c7f99 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 1 Nov 2017 20:35:33 +0200 Subject: drm: Print the fb dimensions when the src coord check fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When debugging bad plane source coordinates it helps to have an idea of what the framebuffer dimensions are. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Signed-off-by: Gustavo Padovan Link: https://patchwork.freedesktop.org/patch/msgid/20171101183533.28466-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_framebuffer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/drm_framebuffer.c') diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index af279844d7ce..40e6565105ac 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -78,11 +78,12 @@ int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y, src_h > fb_height || src_y > fb_height - src_h) { DRM_DEBUG_KMS("Invalid source coordinates " - "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", + "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n", src_w >> 16, ((src_w & 0xffff) * 15625) >> 10, src_h >> 16, ((src_h & 0xffff) * 15625) >> 10, src_x >> 16, ((src_x & 0xffff) * 15625) >> 10, - src_y >> 16, ((src_y & 0xffff) * 15625) >> 10); + src_y >> 16, ((src_y & 0xffff) * 15625) >> 10, + fb->width, fb->height); return -ENOSPC; } -- cgit v1.2.3 From 846c7dfc1193eb2f9866fe2fa0ae7d45c72f95b9 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 1 Nov 2017 16:04:33 +0100 Subject: drm/atomic: Try to preserve the crtc enabled state in drm_atomic_remove_fb, v2. This introduces a slight behavioral change to rmfb. Instead of disabling a crtc when the primary plane is disabled, we try to preserve it. Apart from old versions of the vmwgfx xorg driver, there is nothing depending on rmfb disabling a crtc. Vmwgfx' and simple kms helper atomic implementation rejects CRTC enabled without plane, so we can do this safely. If the atomic commit is rejected by the driver then we will still fall back to the old behavior and turn off the crtc. Changes since v1: - Restart completely when rmfb with crtc on fails (Sean Paul). Signed-off-by: Maarten Lankhorst Cc: Sean Paul Cc: Daniel Vetter Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20171101150433.10777-1-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/drm_framebuffer.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/drm_framebuffer.c') diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 40e6565105ac..2305e7800b45 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -765,14 +765,18 @@ static int atomic_remove_fb(struct drm_framebuffer *fb) struct drm_plane *plane; struct drm_connector *conn; struct drm_connector_state *conn_state; - int i, ret = 0; + int i, ret; unsigned plane_mask; + bool disable_crtcs = false; - state = drm_atomic_state_alloc(dev); - if (!state) - return -ENOMEM; - +retry_disable: drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(dev); + if (!state) { + ret = -ENOMEM; + goto out; + } state->acquire_ctx = &ctx; retry: @@ -793,7 +797,7 @@ retry: goto unlock; } - if (plane_state->crtc->primary == plane) { + if (disable_crtcs && plane_state->crtc->primary == plane) { struct drm_crtc_state *crtc_state; crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc); @@ -818,6 +822,7 @@ retry: plane->old_fb = plane->fb; } + /* This list is only filled when disable_crtcs is set. */ for_each_new_connector_in_state(state, conn, conn_state, i) { ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); @@ -840,9 +845,15 @@ unlock: drm_atomic_state_put(state); +out: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); + if (ret == -EINVAL && !disable_crtcs) { + disable_crtcs = true; + goto retry_disable; + } + return ret; } -- cgit v1.2.3 From 45d58b40292b16ab847497dcd299e315a2ad7956 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Tue, 7 Nov 2017 20:13:40 +0100 Subject: drm/framebuffer: Add framebuffer debugfs file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add debugfs file that dumps info about the framebuffers and its planes. Also dump info about any connected gem object(s). Reviewed-by: Daniel Vetter Signed-off-by: Noralf Trønnes Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20171107191348.17555-5-noralf@tronnes.org --- drivers/gpu/drm/drm_debugfs.c | 6 ++++ drivers/gpu/drm/drm_framebuffer.c | 59 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_gem.c | 17 +++++++++++ drivers/gpu/drm/drm_internal.h | 7 +++++ include/drm/drm_drv.h | 15 ++++++++++ 5 files changed, 104 insertions(+) (limited to 'drivers/gpu/drm/drm_framebuffer.c') diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index c1807d5754b2..550f29de6c1f 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -158,6 +158,12 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, } } + ret = drm_framebuffer_debugfs_init(minor); + if (ret) { + DRM_ERROR("Failed to create framebuffer debugfs file\n"); + return ret; + } + if (dev->driver->debugfs_init) { ret = dev->driver->debugfs_init(minor); if (ret) { diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 2305e7800b45..0153000373ae 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -25,7 +25,9 @@ #include #include #include +#include +#include "drm_internal.h" #include "drm_crtc_internal.h" /** @@ -967,3 +969,60 @@ int drm_framebuffer_plane_height(int height, return fb_plane_height(height, fb->format, plane); } EXPORT_SYMBOL(drm_framebuffer_plane_height); + +void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent, + const struct drm_framebuffer *fb) +{ + struct drm_format_name_buf format_name; + unsigned int i; + + drm_printf_indent(p, indent, "refcount=%u\n", + drm_framebuffer_read_refcount(fb)); + drm_printf_indent(p, indent, "format=%s\n", + drm_get_format_name(fb->format->format, &format_name)); + drm_printf_indent(p, indent, "modifier=0x%llx\n", fb->modifier); + drm_printf_indent(p, indent, "size=%ux%u\n", fb->width, fb->height); + drm_printf_indent(p, indent, "layers:\n"); + + for (i = 0; i < fb->format->num_planes; i++) { + drm_printf_indent(p, indent + 1, "size[%u]=%dx%d\n", i, + drm_framebuffer_plane_width(fb->width, fb, i), + drm_framebuffer_plane_height(fb->height, fb, i)); + drm_printf_indent(p, indent + 1, "pitch[%u]=%u\n", i, fb->pitches[i]); + drm_printf_indent(p, indent + 1, "offset[%u]=%u\n", i, fb->offsets[i]); + drm_printf_indent(p, indent + 1, "obj[%u]:%s\n", i, + fb->obj[i] ? "" : "(null)"); + if (fb->obj[i]) + drm_gem_print_info(p, indent + 2, fb->obj[i]); + } +} + +#ifdef CONFIG_DEBUG_FS +static int drm_framebuffer_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_printer p = drm_seq_file_printer(m); + struct drm_framebuffer *fb; + + mutex_lock(&dev->mode_config.fb_lock); + drm_for_each_fb(fb, dev) { + drm_printf(&p, "framebuffer[%u]:\n", fb->base.id); + drm_framebuffer_print_info(&p, 1, fb); + } + mutex_unlock(&dev->mode_config.fb_lock); + + return 0; +} + +static const struct drm_info_list drm_framebuffer_debugfs_list[] = { + { "framebuffer", drm_framebuffer_info, 0 }, +}; + +int drm_framebuffer_debugfs_init(struct drm_minor *minor) +{ + return drm_debugfs_create_files(drm_framebuffer_debugfs_list, + ARRAY_SIZE(drm_framebuffer_debugfs_list), + minor->debugfs_root, minor); +} +#endif diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 4c84b23d37cc..01f8d9481211 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "drm_internal.h" /** @file drm_gem.c @@ -1040,3 +1041,19 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) return ret; } EXPORT_SYMBOL(drm_gem_mmap); + +void drm_gem_print_info(struct drm_printer *p, unsigned int indent, + const struct drm_gem_object *obj) +{ + drm_printf_indent(p, indent, "name=%d\n", obj->name); + drm_printf_indent(p, indent, "refcount=%u\n", + kref_read(&obj->refcount)); + drm_printf_indent(p, indent, "start=%08lx\n", + drm_vma_node_start(&obj->vma_node)); + drm_printf_indent(p, indent, "size=%zu\n", obj->size); + drm_printf_indent(p, indent, "imported=%s\n", + obj->import_attach ? "yes" : "no"); + + if (obj->dev->driver->gem_print_info) + obj->dev->driver->gem_print_info(p, indent, obj); +} diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index fbc3f308fa19..430ce3fe4f3b 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -106,6 +106,8 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); void drm_gem_open(struct drm_device *dev, struct drm_file *file_private); void drm_gem_release(struct drm_device *dev, struct drm_file *file_private); +void drm_gem_print_info(struct drm_printer *p, unsigned int indent, + const struct drm_gem_object *obj); /* drm_debugfs.c drm_debugfs_crc.c */ #if defined(CONFIG_DEBUG_FS) @@ -173,3 +175,8 @@ int drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private); int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private); + +/* drm_framebuffer.c */ +void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent, + const struct drm_framebuffer *fb); +int drm_framebuffer_debugfs_init(struct drm_minor *minor); diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 0e90ef24214b..1536e5bddeaf 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -39,6 +39,7 @@ struct drm_minor; struct dma_buf_attachment; struct drm_display_mode; struct drm_mode_create_dumb; +struct drm_printer; /* driver capabilities and requirements mask */ #define DRIVER_USE_AGP 0x1 @@ -428,6 +429,20 @@ struct drm_driver { */ void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); + /** + * @gem_print_info: + * + * If driver subclasses struct &drm_gem_object, it can implement this + * optional hook for printing additional driver specific info. + * + * drm_printf_indent() should be used in the callback passing it the + * indent argument. + * + * This callback is called from drm_gem_print_info(). + */ + void (*gem_print_info)(struct drm_printer *p, unsigned int indent, + const struct drm_gem_object *obj); + /** * @gem_create_object: constructor for gem objects * -- cgit v1.2.3