diff options
author | rnoland <rnoland@FreeBSD.org> | 2009-06-25 15:30:25 +0000 |
---|---|---|
committer | rnoland <rnoland@FreeBSD.org> | 2009-06-25 15:30:25 +0000 |
commit | 87697759f9f2be25d52a7ab9ab5969a10bbf7bbb (patch) | |
tree | d933643a726a0f4ab2bd41c7d4ada42bf4a6ea75 /sys/dev/drm/drm_irq.c | |
parent | 51baf9c1b678c7b5092811c73262b321e6a9ac89 (diff) | |
download | FreeBSD-src-87697759f9f2be25d52a7ab9ab5969a10bbf7bbb.zip FreeBSD-src-87697759f9f2be25d52a7ab9ab5969a10bbf7bbb.tar.gz |
Additional vblank cleanups.
Use the vbl_lock when maniputlating the refcount. Eventually I want to
convert this to use our internal refcount code. Continue to use atomic
ops for manipulating vblank count since we access it often just for
reading.
MFC after: 3 days
Diffstat (limited to 'sys/dev/drm/drm_irq.c')
-rw-r--r-- | sys/dev/drm/drm_irq.c | 55 |
1 files changed, 29 insertions, 26 deletions
diff --git a/sys/dev/drm/drm_irq.c b/sys/dev/drm/drm_irq.c index b98f2ce..7b5580e 100644 --- a/sys/dev/drm/drm_irq.c +++ b/sys/dev/drm/drm_irq.c @@ -136,13 +136,14 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) DRM_DEBUG("\n"); /* Zero per-crtc vblank stuff */ + DRM_SPINLOCK(&dev->vbl_lock); for (i = 0; i < num_crtcs; i++) { DRM_INIT_WAITQUEUE(&dev->vblank[i].queue); - atomic_set(&dev->vblank[i].count, 0); - atomic_set(&dev->vblank[i].refcount, 0); + dev->vblank[i].refcount = 0; + atomic_set_rel_32(&dev->vblank[i].count, 0); } - dev->vblank_disable_allowed = 0; + DRM_SPINUNLOCK(&dev->vbl_lock); return 0; @@ -275,7 +276,7 @@ int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv) u32 drm_vblank_count(struct drm_device *dev, int crtc) { - return atomic_read(&dev->vblank[crtc].count); + return atomic_load_acq_32(&dev->vblank[crtc].count); } static void drm_update_vblank_count(struct drm_device *dev, int crtc) @@ -301,45 +302,44 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", crtc, diff); - atomic_add(diff, &dev->vblank[crtc].count); + atomic_add_rel_32(&dev->vblank[crtc].count, diff); } int drm_vblank_get(struct drm_device *dev, int crtc) { int ret = 0; - DRM_SPINLOCK(&dev->vbl_lock); + /* Make sure that we are called with the lock held */ + mtx_assert(&dev->vbl_lock, MA_OWNED); + /* Going from 0->1 means we have to enable interrupts again */ - atomic_add_acq_int(&dev->vblank[crtc].refcount, 1); - if (dev->vblank[crtc].refcount == 1 && + if (++dev->vblank[crtc].refcount == 1 && !dev->vblank[crtc].enabled) { ret = dev->driver->enable_vblank(dev, crtc); DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); if (ret) - atomic_dec(&dev->vblank[crtc].refcount); + --dev->vblank[crtc].refcount; else { dev->vblank[crtc].enabled = 1; drm_update_vblank_count(dev, crtc); } } - DRM_SPINUNLOCK(&dev->vbl_lock); return ret; } void drm_vblank_put(struct drm_device *dev, int crtc) { - KASSERT(atomic_read(&dev->vblank[crtc].refcount) > 0, + /* Make sure that we are called with the lock held */ + mtx_assert(&dev->vbl_lock, MA_OWNED); + + KASSERT(dev->vblank[crtc].refcount > 0, ("invalid refcount")); /* Last user schedules interrupt disable */ - atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1); - - DRM_SPINLOCK(&dev->vbl_lock); - if (dev->vblank[crtc].refcount == 0) + if (--dev->vblank[crtc].refcount == 0) callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, (timeout_t *)vblank_disable_fn, (void *)dev); - DRM_SPINUNLOCK(&dev->vbl_lock); } int drm_modeset_ctl(struct drm_device *dev, void *data, @@ -348,13 +348,11 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, struct drm_modeset_ctl *modeset = data; int crtc, ret = 0; - DRM_DEBUG("num_crtcs=%d\n", dev->num_crtcs); /* If drm_vblank_init() hasn't been called yet, just no-op */ if (!dev->num_crtcs) goto out; crtc = modeset->crtc; - DRM_DEBUG("crtc=%d\n", crtc); if (crtc >= dev->num_crtcs) { ret = EINVAL; goto out; @@ -369,25 +367,25 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, */ switch (modeset->cmd) { case _DRM_PRE_MODESET: - DRM_DEBUG("pre-modeset\n"); + DRM_DEBUG("pre-modeset, crtc %d\n", crtc); + DRM_SPINLOCK(&dev->vbl_lock); if (!dev->vblank[crtc].inmodeset) { dev->vblank[crtc].inmodeset = 0x1; if (drm_vblank_get(dev, crtc) == 0) dev->vblank[crtc].inmodeset |= 0x2; } + DRM_SPINUNLOCK(&dev->vbl_lock); break; case _DRM_POST_MODESET: - DRM_DEBUG("post-modeset\n"); + DRM_DEBUG("post-modeset, crtc %d\n", crtc); + DRM_SPINLOCK(&dev->vbl_lock); if (dev->vblank[crtc].inmodeset) { - DRM_SPINLOCK(&dev->vbl_lock); - dev->vblank_disable_allowed = 1; - DRM_SPINUNLOCK(&dev->vbl_lock); - if (dev->vblank[crtc].inmodeset & 0x2) drm_vblank_put(dev, crtc); - dev->vblank[crtc].inmodeset = 0; } + dev->vblank_disable_allowed = 1; + DRM_SPINUNLOCK(&dev->vbl_lock); break; default: ret = EINVAL; @@ -421,7 +419,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr if (crtc >= dev->num_crtcs) return EINVAL; + DRM_SPINLOCK(&dev->vbl_lock); ret = drm_vblank_get(dev, crtc); + DRM_SPINUNLOCK(&dev->vbl_lock); if (ret) { DRM_ERROR("failed to acquire vblank counter, %d\n", ret); return ret; @@ -478,13 +478,16 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr } done: + DRM_SPINLOCK(&dev->vbl_lock); drm_vblank_put(dev, crtc); + DRM_SPINUNLOCK(&dev->vbl_lock); + return ret; } void drm_handle_vblank(struct drm_device *dev, int crtc) { - atomic_inc(&dev->vblank[crtc].count); + atomic_add_rel_32(&dev->vblank[crtc].count, 1); DRM_WAKEUP(&dev->vblank[crtc].queue); } |