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
This commit is contained in:
parent
64aeca7b42
commit
1f3c8cf88f
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user