summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2008-08-21 18:23:18 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2008-08-21 18:23:18 +0000
commitf44e4b203deb68368dd4bec45d50123844a89f26 (patch)
treeb260a37ecb1efd8be2d4657c9693ec8b5a1c7267 /sys/dev/pci/drm
parentd50db245ff77c46102ad1821b47c3a78aa72d1f6 (diff)
Instead of having a number of malloced arrays for vblank handling, just
put them in a structure and malloc free an array of those, it is nicer that way and They're all needed at the same time, anyway. Idea taken from a suggestion on the dri-devel mailing list.
Diffstat (limited to 'sys/dev/pci/drm')
-rw-r--r--sys/dev/pci/drm/drmP.h35
-rw-r--r--sys/dev/pci/drm/drm_irq.c91
2 files changed, 47 insertions, 79 deletions
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h
index 65e9320f8cd..cbdbb6760a5 100644
--- a/sys/dev/pci/drm/drmP.h
+++ b/sys/dev/pci/drm/drmP.h
@@ -481,6 +481,18 @@ typedef struct drm_local_map {
drm_map_type_t type; /* Type of memory mapped */
} drm_local_map_t;
+struct drm_vblank {
+#if 0 /* unneeded for now, signal support */
+ TAILQ_HEAD(vbl_sigs);
+#endif
+ u_int32_t last_vblank; /* Last vblank we recieved */
+ atomic_t vbl_count; /* Number of interrupts */
+ int vbl_queue; /* sleep on this when waiting */
+ atomic_t vbl_refcount; /* Number of users */
+ int vbl_enabled; /* Enabled? */
+ int vbl_inmodeset; /* is the DDX currently modesetting */
+};
+
TAILQ_HEAD(drm_vbl_sig_list, drm_vbl_sig);
typedef struct drm_vbl_sig {
TAILQ_ENTRY(drm_vbl_sig) link;
@@ -638,22 +650,13 @@ struct drm_device {
int pci_func;
/* VBLANK support */
- int vblank_disable_allowed;
- int *vbl_queue; /* vbl wait channel */
- atomic_t *_vblank_count; /* no vblank interrupts */
- DRM_SPINTYPE vbl_lock; /* locking for vblank operations */
-#if 0 /* unneeded for now */
- TAILQ_HEAD(vbl_sigs);
-#endif
- atomic_t vbl_signal_pending; /* sigs pending on all crtcs */
- atomic_t *vblank_refcount; /* no. users for vlank interrupts */
- u_int32_t *last_vblank; /* locked, used for overflow handling*/
- int *vblank_enabled; /* make sure we only disable once */
- int *vblank_inmodeset; /* X DDX is currently setting mode */
- struct timeout vblank_disable_timer;
- int num_crtcs; /* number of crtcs on device */
-
- u_int32_t max_vblank_count; /* size of counter reg */
+ int num_crtcs; /* number of crtcs */
+ u_int32_t max_vblank_count; /* size of counter reg*/
+ DRM_SPINTYPE vbl_lock; /* VBLANK data lock */
+ atomic_t vbl_signal_pending; /* No. pending sigs */
+ int vblank_disable_allowed;
+ struct timeout vblank_disable_timer; /* timer for disable */
+ struct drm_vblank *vblank; /* One per ctrc */
pid_t buf_pgid;
diff --git a/sys/dev/pci/drm/drm_irq.c b/sys/dev/pci/drm/drm_irq.c
index dfd0bfdc98c..32d1abc9206 100644
--- a/sys/dev/pci/drm/drm_irq.c
+++ b/sys/dev/pci/drm/drm_irq.c
@@ -186,12 +186,12 @@ vblank_disable(void *arg)
for (i=0; i < dev->num_crtcs; i++){
DRM_SPINLOCK(&dev->vbl_lock);
- if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
- dev->vblank_enabled[i]) {
- dev->last_vblank[i] =
+ if (atomic_read(&dev->vblank[i].vbl_refcount) == 0 &&
+ dev->vblank[i].vbl_enabled) {
+ dev->vblank[i].last_vblank =
dev->driver.get_vblank_counter(dev, i);
dev->driver.disable_vblank(dev, i);
- dev->vblank_enabled[i] = 0;
+ dev->vblank[i].vbl_enabled = 0;
}
DRM_SPINUNLOCK(&dev->vbl_lock);
}
@@ -207,22 +207,10 @@ drm_vblank_cleanup(struct drm_device *dev)
vblank_disable(dev);
- drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) *
- dev->num_crtcs, M_DRM);
-#if 0 /* disabled for now */
- drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs, M_DRM);
-#endif
- drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
- dev->num_crtcs, M_DRM);
- drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
- dev->num_crtcs, M_DRM);
- drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
- dev->num_crtcs, M_DRM);
- drm_free(dev->last_vblank, sizeof(*dev->last_vblank) *
- dev->num_crtcs, M_DRM);
- drm_free(dev->vblank_inmodeset, sizeof(*dev->vblank_inmodeset) *
+ drm_free(dev->vblank, sizeof(*dev->vblank) *
dev->num_crtcs, M_DRM);
+ dev->vblank = NULL;
dev->num_crtcs = 0;
DRM_SPINUNINIT(&dev->vbl_lock);
}
@@ -230,40 +218,15 @@ drm_vblank_cleanup(struct drm_device *dev)
int
drm_vblank_init(struct drm_device *dev, int num_crtcs)
{
- int i;
-
timeout_set(&dev->vblank_disable_timer, vblank_disable, dev);
mtx_init(&dev->vbl_lock, IPL_BIO);
atomic_set(&dev->vbl_signal_pending, 0);
dev->num_crtcs = num_crtcs;
- if ((dev->vbl_queue = drm_calloc(num_crtcs, sizeof(*dev->vbl_queue),
- M_DRM)) == NULL)
- goto err;
-
- if ((dev->_vblank_count = drm_calloc(num_crtcs,
- sizeof(*dev->_vblank_count), M_DRM)) == NULL)
+ dev->vblank = drm_calloc(num_crtcs, sizeof(*dev->vblank), M_DRM);
+ if (dev->vblank == NULL)
goto err;
- if ((dev->vblank_refcount = drm_calloc(num_crtcs,
- sizeof(*dev->vblank_refcount), M_DRM)) == NULL)
- goto err;
- if ((dev->vblank_enabled = drm_calloc(num_crtcs,
- sizeof(*dev->vblank_enabled), M_DRM)) == NULL)
- goto err;
- if ((dev->last_vblank = drm_calloc(num_crtcs,
- sizeof(*dev->last_vblank), M_DRM)) == NULL)
- goto err;
- if ((dev->vblank_inmodeset = drm_calloc(num_crtcs,
- sizeof(*dev->vblank_inmodeset), M_DRM)) == NULL)
- goto err;
-
- /* Zero everything */
- for (i = 0; i < num_crtcs; i++) {
- atomic_set(&dev->_vblank_count[i], 0);
- atomic_set(&dev->vblank_refcount[i], 0);
- }
-
dev->vblank_disable_allowed = 0;
return (0);
@@ -276,7 +239,7 @@ err:
u_int32_t
drm_vblank_count(struct drm_device *dev, int crtc)
{
- return atomic_read(&dev->_vblank_count[crtc]);
+ return atomic_read(&dev->vblank[crtc].vbl_count);
}
void
@@ -290,11 +253,11 @@ drm_update_vblank_count(struct drm_device *dev, int crtc)
* the register is small or the interrupts were off for a long time.
*/
cur_vblank = dev->driver.get_vblank_counter(dev, crtc);
- diff = cur_vblank - dev->last_vblank[crtc];
- if (cur_vblank < dev->last_vblank[crtc])
+ diff = cur_vblank - dev->vblank[crtc].last_vblank;
+ if (cur_vblank < dev->vblank[crtc].last_vblank)
diff += dev->max_vblank_count;
- atomic_add(diff, &dev->_vblank_count[crtc]);
+ atomic_add(diff, &dev->vblank[crtc].vbl_count);
}
int
@@ -304,14 +267,14 @@ drm_vblank_get(struct drm_device *dev, int crtc)
DRM_SPINLOCK(&dev->vbl_lock);
- atomic_add(1, &dev->vblank_refcount[crtc]);
- if (dev->vblank_refcount[crtc] == 1 &&
- dev->vblank_enabled[crtc] == 0) {
+ atomic_add(1, &dev->vblank[crtc].vbl_refcount);
+ if (dev->vblank[crtc].vbl_refcount == 1 &&
+ dev->vblank[crtc].vbl_enabled == 0) {
ret = dev->driver.enable_vblank(dev, crtc);
if (ret) {
- atomic_dec(&dev->vblank_refcount[crtc]);
+ atomic_dec(&dev->vblank[crtc].vbl_refcount);
} else {
- dev->vblank_enabled[crtc] = 1;
+ dev->vblank[crtc].vbl_enabled = 1;
drm_update_vblank_count(dev, crtc);
}
}
@@ -325,8 +288,8 @@ drm_vblank_put(struct drm_device *dev, int crtc)
{
DRM_SPINLOCK(&dev->vbl_lock);
/* Last user schedules interrupt disable */
- atomic_dec(&dev->vblank_refcount[crtc]);
- if (dev->vblank_refcount[crtc] == 0)
+ atomic_dec(&dev->vblank[crtc].vbl_refcount);
+ if (dev->vblank[crtc].vbl_refcount == 0)
timeout_add_sec(&dev->vblank_disable_timer, 5);
DRM_SPINUNLOCK(&dev->vbl_lock);
}
@@ -354,16 +317,18 @@ drm_modeset_ctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
*/
switch (modeset->cmd) {
case _DRM_PRE_MODESET:
- if (dev->vblank_inmodeset[crtc] == 0) {
- dev->vblank_inmodeset[crtc] = 1;
+ if (dev->vblank[crtc].vbl_inmodeset == 0) {
+ DRM_SPINLOCK(&dev->vbl_lock);
+ dev->vblank[crtc].vbl_inmodeset = 1;
+ DRM_SPINUNLOCK(&dev->vbl_lock);
drm_vblank_get(dev, crtc);
}
break;
case _DRM_POST_MODESET:
- if (dev->vblank_inmodeset[crtc]) {
+ if (dev->vblank[crtc].vbl_inmodeset) {
DRM_SPINLOCK(&dev->vbl_lock);
dev->vblank_disable_allowed = 1;
- dev->vblank_inmodeset[crtc] = 0;
+ dev->vblank[crtc].vbl_inmodeset = 0;
DRM_SPINUNLOCK(&dev->vbl_lock);
drm_vblank_put(dev, crtc);
}
@@ -436,7 +401,7 @@ drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
DRM_SPINUNLOCK(&dev->vbl_lock);
break;
}
- ret = msleep(&dev->vbl_queue[crtc],
+ ret = msleep(&dev->vblank[crtc].vbl_queue,
&dev->vbl_lock, PZERO | PCATCH,
"drmvblq", 3 * DRM_HZ);
DRM_SPINUNLOCK(&dev->vbl_lock);
@@ -489,8 +454,8 @@ drm_vbl_send_signals(struct drm_device *dev, int crtc)
void
drm_handle_vblank(struct drm_device *dev, int crtc)
{
- atomic_inc(&dev->_vblank_count[crtc]);
- DRM_WAKEUP(&dev->vbl_queue[crtc]);
+ atomic_inc(&dev->vblank[crtc].vbl_count);
+ DRM_WAKEUP(&dev->vblank[crtc].vbl_queue);
drm_vbl_send_signals(dev, crtc);
}