diff options
author | Eric Anholt <eric@anholt.net> | 2008-12-20 02:23:38 +0100 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-12-29 08:47:27 +0100 |
commit | fede5c91c4a8a7701d205b2b84b9835ddc7d6f02 (patch) | |
tree | a80b546790a405b5a0b60e843c06b5697c0b2226 | |
parent | drm: Avoid use-before-null-test on dev in drm_cleanup(). (diff) | |
download | linux-fede5c91c4a8a7701d205b2b84b9835ddc7d6f02.tar.xz linux-fede5c91c4a8a7701d205b2b84b9835ddc7d6f02.zip |
drm: Add a debug node for vblank state.
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@linux.ie>
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_proc.c | 63 | ||||
-rw-r--r-- | include/drm/drmP.h | 1 |
3 files changed, 73 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 1608f8dbfda0..724e505873cf 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -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))); diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index 7dbaa1a19ea4..8df849f66830 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c @@ -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. diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 7802c80f2b23..afb7858c068d 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -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 */ |