From: Jerome Glisse jglisse@redhat.com
This is to allow debugging of userspace program not freeing buffer after, which is basicly a memory leak. This print the list of all gem object along with their size and placement (VRAM,GTT,CPU) and with the pid of the task that created them.
Signed-off-by: Jerome Glisse jglisse@redhat.com --- drivers/gpu/drm/radeon/radeon.h | 5 +++- drivers/gpu/drm/radeon/radeon_device.c | 5 ++++ drivers/gpu/drm/radeon/radeon_gem.c | 50 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 18904fb..bd28ee6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -358,7 +358,8 @@ struct radeon_bo { struct radeon_device *rdev; struct drm_gem_object gem_base;
- struct ttm_bo_kmap_obj dma_buf_vmap; + struct ttm_bo_kmap_obj dma_buf_vmap; + pid_t pid; }; #define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base)
@@ -372,6 +373,8 @@ struct radeon_bo_list { u32 tiling_flags; };
+int radeon_gem_debugfs_init(struct radeon_device *rdev); + /* sub-allocation manager, it has to be protected by another lock. * By conception this is an helper for other part of the driver * like the indirect buffer or semaphore, which both have their diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 62d0ba3..76166ae 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1142,6 +1142,11 @@ int radeon_device_init(struct radeon_device *rdev, if (r) DRM_ERROR("ib ring test failed (%d).\n", r);
+ r = radeon_gem_debugfs_init(rdev); + if (r) { + DRM_ERROR("registering gem debugfs failed (%d).\n", r); + } + if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { /* Acceleration not working on AGP card try again * with fallback to PCI or PCIE GART diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index fe5c1f6..87f8c52 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -84,6 +84,7 @@ retry: return r; } *obj = &robj->gem_base; + robj->pid = task_pid_nr(current);
mutex_lock(&rdev->gem.mutex); list_add_tail(&robj->list, &rdev->gem.objects); @@ -575,3 +576,52 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv, { return drm_gem_handle_delete(file_priv, handle); } + +#if defined(CONFIG_DEBUG_FS) +static int radeon_debugfs_gem_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_device *dev = node->minor->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_bo *rbo; + unsigned i = 0; + + mutex_lock(&rdev->gem.mutex); + list_for_each_entry(rbo, &rdev->gem.objects, list) { + unsigned domain; + const char *placement; + + domain = radeon_mem_type_to_domain(rbo->tbo.mem.mem_type); + switch (domain) { + case RADEON_GEM_DOMAIN_VRAM: + placement = "VRAM"; + break; + case RADEON_GEM_DOMAIN_GTT: + placement = " GTT"; + break; + case RADEON_GEM_DOMAIN_CPU: + default: + placement = " CPU"; + break; + } + seq_printf(m, "bo[0x%08x] %8dkB %8dMB %s pid %8ld\n", + i, radeon_bo_size(rbo) >> 10, radeon_bo_size(rbo) >> 20, + placement, (unsigned long)rbo->pid); + i++; + } + mutex_unlock(&rdev->gem.mutex); + return 0; +} + +static struct drm_info_list radeon_debugfs_gem_list[] = { + {"radeon_gem_info", &radeon_debugfs_gem_info, 0, NULL}, +}; +#endif + +int radeon_gem_debugfs_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS) + return radeon_debugfs_add_files(rdev, radeon_debugfs_gem_list, 1); +#endif + return 0; +}
On Thu, Apr 25, 2013 at 10:29 PM, j.glisse@gmail.com wrote:
From: Jerome Glisse jglisse@redhat.com
This is to allow debugging of userspace program not freeing buffer after, which is basicly a memory leak. This print the list of all gem object along with their size and placement (VRAM,GTT,CPU) and with the pid of the task that created them.
Signed-off-by: Jerome Glisse jglisse@redhat.com
Looks good to me. Unless there are any objections, I'll pull it in for 3.10
Alex
drivers/gpu/drm/radeon/radeon.h | 5 +++- drivers/gpu/drm/radeon/radeon_device.c | 5 ++++ drivers/gpu/drm/radeon/radeon_gem.c | 50 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 18904fb..bd28ee6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -358,7 +358,8 @@ struct radeon_bo { struct radeon_device *rdev; struct drm_gem_object gem_base;
struct ttm_bo_kmap_obj dma_buf_vmap;
struct ttm_bo_kmap_obj dma_buf_vmap;
pid_t pid;
}; #define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base)
@@ -372,6 +373,8 @@ struct radeon_bo_list { u32 tiling_flags; };
+int radeon_gem_debugfs_init(struct radeon_device *rdev);
/* sub-allocation manager, it has to be protected by another lock.
- By conception this is an helper for other part of the driver
- like the indirect buffer or semaphore, which both have their
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 62d0ba3..76166ae 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1142,6 +1142,11 @@ int radeon_device_init(struct radeon_device *rdev, if (r) DRM_ERROR("ib ring test failed (%d).\n", r);
r = radeon_gem_debugfs_init(rdev);
if (r) {
DRM_ERROR("registering gem debugfs failed (%d).\n", r);
}
if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { /* Acceleration not working on AGP card try again * with fallback to PCI or PCIE GART
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index fe5c1f6..87f8c52 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -84,6 +84,7 @@ retry: return r; } *obj = &robj->gem_base;
robj->pid = task_pid_nr(current); mutex_lock(&rdev->gem.mutex); list_add_tail(&robj->list, &rdev->gem.objects);
@@ -575,3 +576,52 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv, { return drm_gem_handle_delete(file_priv, handle); }
+#if defined(CONFIG_DEBUG_FS) +static int radeon_debugfs_gem_info(struct seq_file *m, void *data) +{
struct drm_info_node *node = (struct drm_info_node *)m->private;
struct drm_device *dev = node->minor->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_bo *rbo;
unsigned i = 0;
mutex_lock(&rdev->gem.mutex);
list_for_each_entry(rbo, &rdev->gem.objects, list) {
unsigned domain;
const char *placement;
domain = radeon_mem_type_to_domain(rbo->tbo.mem.mem_type);
switch (domain) {
case RADEON_GEM_DOMAIN_VRAM:
placement = "VRAM";
break;
case RADEON_GEM_DOMAIN_GTT:
placement = " GTT";
break;
case RADEON_GEM_DOMAIN_CPU:
default:
placement = " CPU";
break;
}
seq_printf(m, "bo[0x%08x] %8dkB %8dMB %s pid %8ld\n",
i, radeon_bo_size(rbo) >> 10, radeon_bo_size(rbo) >> 20,
placement, (unsigned long)rbo->pid);
i++;
}
mutex_unlock(&rdev->gem.mutex);
return 0;
+}
+static struct drm_info_list radeon_debugfs_gem_list[] = {
{"radeon_gem_info", &radeon_debugfs_gem_info, 0, NULL},
+}; +#endif
+int radeon_gem_debugfs_init(struct radeon_device *rdev) +{ +#if defined(CONFIG_DEBUG_FS)
return radeon_debugfs_add_files(rdev, radeon_debugfs_gem_list, 1);
+#endif
return 0;
+}
1.8.2.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel@lists.freedesktop.org