summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrnoland <rnoland@FreeBSD.org>2009-06-25 15:30:25 +0000
committerrnoland <rnoland@FreeBSD.org>2009-06-25 15:30:25 +0000
commit87697759f9f2be25d52a7ab9ab5969a10bbf7bbb (patch)
treed933643a726a0f4ab2bd41c7d4ada42bf4a6ea75
parent51baf9c1b678c7b5092811c73262b321e6a9ac89 (diff)
downloadFreeBSD-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
-rw-r--r--sys/dev/drm/drm_irq.c55
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);
}
OpenPOWER on IntegriCloud