staging: drm/omap: debugfs for object and fb tracking
authorRob Clark <rob@ti.com>
Mon, 5 Mar 2012 16:48:36 +0000 (10:48 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Mar 2012 21:38:07 +0000 (13:38 -0800)
Add some additional debugfs file to aid in tracking buffer usage.

Signed-off-by: Rob Clark <rob@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/omapdrm/omap_debugfs.c
drivers/staging/omapdrm/omap_drv.c
drivers/staging/omapdrm/omap_drv.h
drivers/staging/omapdrm/omap_fb.c
drivers/staging/omapdrm/omap_gem.c

index da920dfdc59c4aee0bf1cc033bcca6e743d5c71f..e23f907e5fc6b31c9209513119de34c969e71fcb 100644 (file)
 #include "omap_drv.h"
 #include "omap_dmm_tiler.h"
 
+#include "drm_fb_helper.h"
+
+
 #ifdef CONFIG_DEBUG_FS
 
+static int gem_show(struct seq_file *m, void *arg)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct omap_drm_private *priv = dev->dev_private;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       seq_printf(m, "All Objects:\n");
+       omap_gem_describe_objects(&priv->obj_list, m);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
+static int mm_show(struct seq_file *m, void *arg)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       return drm_mm_dump_table(m, dev->mm_private);
+}
+
+static int fb_show(struct seq_file *m, void *arg)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct omap_drm_private *priv = dev->dev_private;
+       struct drm_framebuffer *fb;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+       if (ret)
+               return ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret) {
+               mutex_unlock(&dev->mode_config.mutex);
+               return ret;
+       }
+
+       seq_printf(m, "fbcon ");
+       omap_framebuffer_describe(priv->fbdev->fb, m);
+
+       list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+               if (fb == priv->fbdev->fb)
+                       continue;
+
+               seq_printf(m, "user ");
+               omap_framebuffer_describe(fb, m);
+       }
+
+       mutex_unlock(&dev->struct_mutex);
+       mutex_unlock(&dev->mode_config.mutex);
+
+       return 0;
+}
+
+/* list of debufs files that are applicable to all devices */
 static struct drm_info_list omap_debugfs_list[] = {
+       {"gem", gem_show, 0},
+       {"mm", mm_show, 0},
+       {"fb", fb_show, 0},
+};
+
+/* list of debugfs files that are specific to devices with dmm/tiler */
+static struct drm_info_list omap_dmm_debugfs_list[] = {
        {"tiler_map", tiler_map_show, 0},
 };
 
 int omap_debugfs_init(struct drm_minor *minor)
 {
-       return drm_debugfs_create_files(omap_debugfs_list,
+       struct drm_device *dev = minor->dev;
+       int ret;
+
+       ret = drm_debugfs_create_files(omap_debugfs_list,
                        ARRAY_SIZE(omap_debugfs_list),
                        minor->debugfs_root, minor);
+
+       if (ret) {
+               dev_err(dev->dev, "could not install omap_debugfs_list\n");
+               return ret;
+       }
+
+       /* TODO: only do this if has_dmm.. but this fxn gets called before
+        * dev_load() so we don't know this yet..
+        */
+       ret = drm_debugfs_create_files(omap_dmm_debugfs_list,
+                       ARRAY_SIZE(omap_dmm_debugfs_list),
+                       minor->debugfs_root, minor);
+
+       if (ret) {
+               dev_err(dev->dev, "could not install omap_dmm_debugfs_list\n");
+               return ret;
+       }
+
+       return ret;
 }
 
 void omap_debugfs_cleanup(struct drm_minor *minor)
 {
        drm_debugfs_remove_files(omap_debugfs_list,
                        ARRAY_SIZE(omap_debugfs_list), minor);
+       drm_debugfs_remove_files(omap_dmm_debugfs_list,
+                       ARRAY_SIZE(omap_dmm_debugfs_list), minor);
 }
 
 #endif
index 7417e1f35aa9bc73f0a73a64af54a15f3d73b30f..e2100bb5609c5827cddf2ed01d969b88478d6292 100644 (file)
@@ -573,6 +573,8 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
        priv->wq = alloc_workqueue("omapdrm",
                        WQ_UNBOUND | WQ_NON_REENTRANT, 1);
 
+       INIT_LIST_HEAD(&priv->obj_list);
+
        omap_gem_init(dev);
 
        ret = omap_modeset_init(dev);
index fe4766e27b9eba8dd094f4955551d3b83e410ac3..21e48cf430f4e6dd18b4d30b0ae649eda7ccfe52 100644 (file)
 struct omap_drm_private {
        unsigned int num_crtcs;
        struct drm_crtc *crtcs[8];
+
        unsigned int num_planes;
        struct drm_plane *planes[8];
+
        unsigned int num_encoders;
        struct drm_encoder *encoders[8];
+
        unsigned int num_connectors;
        struct drm_connector *connectors[8];
 
@@ -53,12 +56,17 @@ struct omap_drm_private {
 
        struct workqueue_struct *wq;
 
+       struct list_head obj_list;
+
        bool has_dmm;
 };
 
 #ifdef CONFIG_DEBUG_FS
 int omap_debugfs_init(struct drm_minor *minor);
 void omap_debugfs_cleanup(struct drm_minor *minor);
+void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
+void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m);
+void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
 #endif
 
 struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev);
index fcb248f4cb0c480c8d6efa3a7cf6b37b570df1bb..04b235b6724abc12cb79d06d14d51bfe0ae2b526 100644 (file)
@@ -277,6 +277,24 @@ void omap_framebuffer_flush(struct drm_framebuffer *fb,
        }
 }
 
+#ifdef CONFIG_DEBUG_FS
+void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
+{
+       struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+       int i, n = drm_format_num_planes(fb->pixel_format);
+
+       seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
+                       (char *)&fb->pixel_format);
+
+       for (i = 0; i < n; i++) {
+               struct plane *plane = &omap_fb->planes[i];
+               seq_printf(m, "   %d: offset=%d pitch=%d, obj: ",
+                               i, plane->offset, plane->pitch);
+               omap_gem_describe(plane->bo, m);
+       }
+}
+#endif
+
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
                struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)
 {
index bd35520d50ffc4cde3646ddc9369c6a0689c27da..1d734bc95a32b5ab1cee0b6428d342c02e0cf3f3 100644 (file)
@@ -45,6 +45,8 @@ int _drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
 struct omap_gem_object {
        struct drm_gem_object base;
 
+       struct list_head mm_list;
+
        uint32_t flags;
 
        /** width/height for tiled formats (rounded up to slot boundaries) */
@@ -254,13 +256,17 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj)
 /** get mmap offset */
 static uint64_t mmap_offset(struct drm_gem_object *obj)
 {
+       struct drm_device *dev = obj->dev;
+
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
        if (!obj->map_list.map) {
                /* Make it mmapable */
                size_t size = omap_gem_mmap_size(obj);
                int ret = _drm_gem_create_mmap_offset_size(obj, size);
 
                if (ret) {
-                       dev_err(obj->dev->dev, "could not allocate mmap offset");
+                       dev_err(dev->dev, "could not allocate mmap offset\n");
                        return 0;
                }
        }
@@ -764,6 +770,56 @@ void *omap_gem_vaddr(struct drm_gem_object *obj)
        return omap_obj->vaddr;
 }
 
+#ifdef CONFIG_DEBUG_FS
+void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
+{
+       struct drm_device *dev = obj->dev;
+       struct omap_gem_object *omap_obj = to_omap_bo(obj);
+       uint64_t off = 0;
+
+       WARN_ON(! mutex_is_locked(&dev->struct_mutex));
+
+       if (obj->map_list.map)
+               off = (uint64_t)obj->map_list.hash.key;
+
+       seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d",
+                       omap_obj->flags, obj->name, obj->refcount.refcount.counter,
+                       off, omap_obj->paddr, omap_obj->paddr_cnt,
+                       omap_obj->vaddr, omap_obj->roll);
+
+       if (omap_obj->flags & OMAP_BO_TILED) {
+               seq_printf(m, " %dx%d", omap_obj->width, omap_obj->height);
+               if (omap_obj->block) {
+                       struct tcm_area *area = &omap_obj->block->area;
+                       seq_printf(m, " (%dx%d, %dx%d)",
+                                       area->p0.x, area->p0.y,
+                                       area->p1.x, area->p1.y);
+               }
+       } else {
+               seq_printf(m, " %d", obj->size);
+       }
+
+       seq_printf(m, "\n");
+}
+
+void omap_gem_describe_objects(struct list_head *list, struct seq_file *m)
+{
+       struct omap_gem_object *omap_obj;
+       int count = 0;
+       size_t size = 0;
+
+       list_for_each_entry(omap_obj, list, mm_list) {
+               struct drm_gem_object *obj = &omap_obj->base;
+               seq_printf(m, "   ");
+               omap_gem_describe(obj, m);
+               count++;
+               size += obj->size;
+       }
+
+       seq_printf(m, "Total %d objects, %zu bytes\n", count, size);
+}
+#endif
+
 /* Buffer Synchronization:
  */
 
@@ -1030,6 +1086,10 @@ void omap_gem_free_object(struct drm_gem_object *obj)
 
        evict(obj);
 
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+       list_del(&omap_obj->mm_list);
+
        if (obj->map_list.map) {
                drm_gem_free_mmap_offset(obj);
        }
@@ -1130,6 +1190,8 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
                goto fail;
        }
 
+       list_add(&omap_obj->mm_list, &priv->obj_list);
+
        obj = &omap_obj->base;
 
        if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) {