drm: Add a debug node for vblank state.
authorEric Anholt <eric@anholt.net>
Sat, 20 Dec 2008 01:23:38 +0000 (17:23 -0800)
committerDave Airlie <airlied@linux.ie>
Mon, 29 Dec 2008 07:47:27 +0000 (17:47 +1000)
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@linux.ie>
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_proc.c
include/drm/drmP.h

index 1608f8d..724e505 100644 (file)
@@ -116,6 +116,9 @@ void drm_vblank_cleanup(struct drm_device *dev)
                 dev->num_crtcs, DRM_MEM_DRIVER);
        drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
                 DRM_MEM_DRIVER);
+       drm_free(dev->last_vblank_wait,
+                sizeof(*dev->last_vblank_wait) * dev->num_crtcs,
+                DRM_MEM_DRIVER);
        drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) *
                 dev->num_crtcs, DRM_MEM_DRIVER);
 
@@ -161,6 +164,11 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
        if (!dev->last_vblank)
                goto err;
 
+       dev->last_vblank_wait = drm_calloc(num_crtcs, sizeof(u32),
+                                          DRM_MEM_DRIVER);
+       if (!dev->last_vblank_wait)
+               goto err;
+
        dev->vblank_inmodeset = drm_calloc(num_crtcs, sizeof(int),
                                         DRM_MEM_DRIVER);
        if (!dev->vblank_inmodeset)
@@ -642,6 +650,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
        } else {
                DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
                          vblwait->request.sequence, crtc);
+               dev->last_vblank_wait[crtc] = vblwait->request.sequence;
                DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
                            ((drm_vblank_count(dev, crtc)
                              - vblwait->request.sequence) <= (1 << 23)));
index 7dbaa1a..8df849f 100644 (file)
@@ -49,6 +49,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset,
                           int request, int *eof, void *data);
 static int drm_bufs_info(char *buf, char **start, off_t offset,
                         int request, int *eof, void *data);
+static int drm_vblank_info(char *buf, char **start, off_t offset,
+                          int request, int *eof, void *data);
 static int drm_gem_name_info(char *buf, char **start, off_t offset,
                             int request, int *eof, void *data);
 static int drm_gem_object_info(char *buf, char **start, off_t offset,
@@ -72,6 +74,7 @@ static struct drm_proc_list {
        {"clients", drm_clients_info, 0},
        {"queues", drm_queues_info, 0},
        {"bufs", drm_bufs_info, 0},
+       {"vblank", drm_vblank_info, 0},
        {"gem_names", drm_gem_name_info, DRIVER_GEM},
        {"gem_objects", drm_gem_object_info, DRIVER_GEM},
 #if DRM_DEBUG_CODE
@@ -458,6 +461,66 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
 }
 
 /**
+ * Called when "/proc/dri/.../vblank" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
+static int drm__vblank_info(char *buf, char **start, off_t offset, int request,
+                         int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int len = 0;
+       int crtc;
+
+       if (offset > DRM_PROC_LIMIT) {
+               *eof = 1;
+               return 0;
+       }
+
+       *start = &buf[offset];
+       *eof = 0;
+
+       for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
+               DRM_PROC_PRINT("CRTC %d enable:     %d\n",
+                              crtc, atomic_read(&dev->vblank_refcount[crtc]));
+               DRM_PROC_PRINT("CRTC %d counter:    %d\n",
+                              crtc, drm_vblank_count(dev, crtc));
+               DRM_PROC_PRINT("CRTC %d last wait:  %d\n",
+                              crtc, dev->last_vblank_wait[crtc]);
+               DRM_PROC_PRINT("CRTC %d in modeset: %d\n",
+                              crtc, dev->vblank_inmodeset[crtc]);
+       }
+
+       if (len > request + offset)
+               return request;
+       *eof = 1;
+       return len - offset;
+}
+
+/**
+ * Simply calls _vblank_info() while holding the drm_device::struct_mutex lock.
+ */
+static int drm_vblank_info(char *buf, char **start, off_t offset, int request,
+                        int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm__vblank_info(buf, start, offset, request, eof, data);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+/**
  * Called when "/proc/dri/.../clients" is read.
  *
  * \param buf output buffer.
index 7802c80..afb7858 100644 (file)
@@ -911,6 +911,7 @@ struct drm_device {
        int *vblank_enabled;            /* so we don't call enable more than
                                           once per disable */
        int *vblank_inmodeset;          /* Display driver is setting mode */
+       u32 *last_vblank_wait;          /* Last vblank seqno waited per CRTC */
        struct timer_list vblank_disable_timer;
 
        u32 max_vblank_count;           /**< size of vblank counter register */