Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Jun 2009 15:30:25 +0000 (UTC)
From:      Robert Noland <rnoland@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r194963 - head/sys/dev/drm
Message-ID:  <200906251530.n5PFUP0v055291@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rnoland
Date: Thu Jun 25 15:30:25 2009
New Revision: 194963
URL: http://svn.freebsd.org/changeset/base/194963

Log:
  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

Modified:
  head/sys/dev/drm/drm_irq.c

Modified: head/sys/dev/drm/drm_irq.c
==============================================================================
--- head/sys/dev/drm/drm_irq.c	Thu Jun 25 14:44:00 2009	(r194962)
+++ head/sys/dev/drm/drm_irq.c	Thu Jun 25 15:30:25 2009	(r194963)
@@ -136,13 +136,14 @@ int drm_vblank_init(struct drm_device *d
 	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, 
 
 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(stru
 	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 *d
 	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 *d
 	 */
 	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 *d
 	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 *d
 	}
 
 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);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906251530.n5PFUP0v055291>