svn commit: r195912 - in stable/7/sys: . contrib/pf dev/drm

Robert Noland rnoland at FreeBSD.org
Mon Jul 27 16:05:52 UTC 2009


Author: rnoland
Date: Mon Jul 27 16:05:51 2009
New Revision: 195912
URL: http://svn.freebsd.org/changeset/base/195912

Log:
  MFC r194741,194745-194746,194748-194749,194759,194960,194963,194965-194966,194969,194986,194996
  
  This pulls in numerous vblank related fixes from HEAD.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/drm/drmP.h
  stable/7/sys/dev/drm/drm_drv.c
  stable/7/sys/dev/drm/drm_irq.c
  stable/7/sys/dev/drm/drm_sysctl.c
  stable/7/sys/dev/drm/i915_dma.c
  stable/7/sys/dev/drm/i915_drv.c
  stable/7/sys/dev/drm/i915_drv.h
  stable/7/sys/dev/drm/i915_irq.c
  stable/7/sys/dev/drm/radeon_cp.c
  stable/7/sys/dev/drm/radeon_irq.c

Modified: stable/7/sys/dev/drm/drmP.h
==============================================================================
--- stable/7/sys/dev/drm/drmP.h	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/drmP.h	Mon Jul 27 16:05:51 2009	(r195912)
@@ -502,19 +502,10 @@ typedef struct drm_local_map {
 	TAILQ_ENTRY(drm_local_map) link;
 } drm_local_map_t;
 
-TAILQ_HEAD(drm_vbl_sig_list, drm_vbl_sig);
-typedef struct drm_vbl_sig {
-	TAILQ_ENTRY(drm_vbl_sig) link;
-	unsigned int	sequence;
-	int		signo;
-	int		pid;
-} drm_vbl_sig_t;
-
 struct drm_vblank_info {
 	wait_queue_head_t queue;	/* vblank wait queue */
 	atomic_t count;			/* number of VBLANK interrupts */
 					/* (driver must alloc the right number of counters) */
-	struct drm_vbl_sig_list sigs;	/* signal list to send on VBLANK */
 	atomic_t refcount;		/* number of users of vblank interrupts */
 	u32 last;			/* protected by dev->vbl_lock, used */
 					/* for wraparound handling */
@@ -684,7 +675,6 @@ struct drm_device {
 	int		  last_context;	/* Last current context		   */
 
 	int		  vblank_disable_allowed;
-	atomic_t 	  vbl_signal_pending;	/* number of signals pending on all crtcs */
 	struct callout	  vblank_disable_timer;
 	u32		  max_vblank_count;	/* size of vblank counter register */
 	struct drm_vblank_info *vblank;		/* per crtc vblank info */
@@ -802,7 +792,6 @@ void	drm_vblank_put(struct drm_device *d
 void	drm_vblank_cleanup(struct drm_device *dev);
 int	drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
 int	drm_vblank_init(struct drm_device *dev, int num_crtcs);
-void	drm_vbl_send_signals(struct drm_device *dev, int crtc);
 int 	drm_modeset_ctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 

Modified: stable/7/sys/dev/drm/drm_drv.c
==============================================================================
--- stable/7/sys/dev/drm/drm_drv.c	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/drm_drv.c	Mon Jul 27 16:05:51 2009	(r195912)
@@ -273,11 +273,14 @@ int drm_detach(device_t kdev)
 
 	drm_unload(dev);
 
-	bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr);
-
-	if (dev->msi_enabled) {
-		pci_release_msi(dev->device);
-		DRM_INFO("MSI released\n");
+	if (dev->irqr) {
+		bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid,
+		    dev->irqr);
+
+		if (dev->msi_enabled) {
+			pci_release_msi(dev->device);
+			DRM_INFO("MSI released\n");
+		}
 	}
 
 	return 0;

Modified: stable/7/sys/dev/drm/drm_irq.c
==============================================================================
--- stable/7/sys/dev/drm/drm_irq.c	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/drm_irq.c	Mon Jul 27 16:05:51 2009	(r195912)
@@ -70,6 +70,9 @@ static void vblank_disable_fn(void *arg)
 	struct drm_device *dev = (struct drm_device *)arg;
 	int i;
 
+	/* Make sure that we are called with the lock held */
+	mtx_assert(&dev->vbl_lock, MA_OWNED);
+
 	if (callout_pending(&dev->vblank_disable_timer)) {
 		/* callout was reset */
 		return;
@@ -86,7 +89,7 @@ static void vblank_disable_fn(void *arg)
 		return;
 
 	for (i = 0; i < dev->num_crtcs; i++) {
-		if (atomic_read(&dev->vblank[i].refcount) == 0 &&
+		if (dev->vblank[i].refcount == 0 &&
 		    dev->vblank[i].enabled && !dev->vblank[i].inmodeset) {
 			DRM_DEBUG("disabling vblank on crtc %d\n", i);
 			dev->vblank[i].last =
@@ -109,7 +112,9 @@ void drm_vblank_cleanup(struct drm_devic
 
 	callout_drain(&dev->vblank_disable_timer);
 
+	DRM_SPINLOCK(&dev->vbl_lock);
 	vblank_disable_fn((void *)dev);
+	DRM_SPINUNLOCK(&dev->vbl_lock);
 
 	free(dev->vblank, DRM_MEM_DRIVER);
 
@@ -121,7 +126,6 @@ int drm_vblank_init(struct drm_device *d
 	int i, ret = ENOMEM;
 
 	callout_init_mtx(&dev->vblank_disable_timer, &dev->vbl_lock, 0);
-	atomic_set(&dev->vbl_signal_pending, 0);
 	dev->num_crtcs = num_crtcs;
 
 	dev->vblank = malloc(sizeof(struct drm_vblank_info) * num_crtcs,
@@ -132,14 +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);
-		TAILQ_INIT(&dev->vblank[i].sigs);
-		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;
 
@@ -272,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)
@@ -298,45 +302,48 @@ 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);
+
+	if (dev->vblank[crtc].enabled)
+		dev->vblank[crtc].last =
+		    dev->driver->get_vblank_counter(dev, crtc);
 
 	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,
@@ -345,13 +352,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;
@@ -366,25 +371,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;
@@ -418,7 +423,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;
@@ -442,28 +449,11 @@ int drm_wait_vblank(struct drm_device *d
 	}
 
 	if (flags & _DRM_VBLANK_SIGNAL) {
-#if 0 /* disabled */
-		drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t),
-		    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
-		if (vbl_sig == NULL)
-			return ENOMEM;
-
-		vbl_sig->sequence = vblwait->request.sequence;
-		vbl_sig->signo = vblwait->request.signal;
-		vbl_sig->pid = DRM_CURRENTPID;
-
-		vblwait->reply.sequence = atomic_read(&dev->vbl_received);
-		
-		DRM_SPINLOCK(&dev->vbl_lock);
-		TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
-		DRM_SPINUNLOCK(&dev->vbl_lock);
-		ret = 0;
-#endif
+		/* There have never been any consumers */
 		ret = EINVAL;
 	} else {
 		DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
 		    vblwait->request.sequence, crtc);
-		dev->vblank[crtc].last = vblwait->request.sequence;
 		for ( ret = 0 ; !ret && !(((drm_vblank_count(dev, crtc) -
 		    vblwait->request.sequence) <= (1 << 23)) ||
 		    !dev->irq_enabled) ; ) {
@@ -473,7 +463,7 @@ int drm_wait_vblank(struct drm_device *d
 			    !dev->irq_enabled))
 				ret = mtx_sleep(&dev->vblank[crtc].queue,
 				    &dev->irq_lock, PCATCH, "vblwtq",
-				    3 * DRM_HZ);
+				    DRM_HZ);
 			mtx_unlock(&dev->irq_lock);
 		}
 
@@ -492,42 +482,16 @@ int drm_wait_vblank(struct drm_device *d
 	}
 
 done:
+	DRM_SPINLOCK(&dev->vbl_lock);
 	drm_vblank_put(dev, crtc);
-	return ret;
-}
-
-void drm_vbl_send_signals(struct drm_device *dev, int crtc)
-{
-}
-
-#if 0 /* disabled */
-void drm_vbl_send_signals(struct drm_device *dev, int crtc )
-{
-	drm_vbl_sig_t *vbl_sig;
-	unsigned int vbl_seq = atomic_read( &dev->vbl_received );
-	struct proc *p;
-
-	vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list);
-	while (vbl_sig != NULL) {
-		drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
-
-		if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
-			p = pfind(vbl_sig->pid);
-			if (p != NULL)
-				psignal(p, vbl_sig->signo);
+	DRM_SPINUNLOCK(&dev->vbl_lock);
 
-			TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link);
-			DRM_FREE(vbl_sig,sizeof(*vbl_sig));
-		}
-		vbl_sig = next;
-	}
+	return ret;
 }
-#endif
 
 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);
-	drm_vbl_send_signals(dev, crtc);
 }
 

Modified: stable/7/sys/dev/drm/drm_sysctl.c
==============================================================================
--- stable/7/sys/dev/drm/drm_sysctl.c	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/drm_sysctl.c	Mon Jul 27 16:05:51 2009	(r195912)
@@ -38,6 +38,7 @@ static int	   drm_name_info DRM_SYSCTL_H
 static int	   drm_vm_info DRM_SYSCTL_HANDLER_ARGS;
 static int	   drm_clients_info DRM_SYSCTL_HANDLER_ARGS;
 static int	   drm_bufs_info DRM_SYSCTL_HANDLER_ARGS;
+static int	   drm_vblank_info DRM_SYSCTL_HANDLER_ARGS;
 
 struct drm_sysctl_list {
 	const char *name;
@@ -47,6 +48,7 @@ struct drm_sysctl_list {
 	{"vm",	    drm_vm_info},
 	{"clients", drm_clients_info},
 	{"bufs",    drm_bufs_info},
+	{"vblank",    drm_vblank_info},
 };
 #define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0]))
 
@@ -313,3 +315,25 @@ done:
 	free(tempprivs, DRM_MEM_DRIVER);
 	return retcode;
 }
+
+static int drm_vblank_info DRM_SYSCTL_HANDLER_ARGS
+{
+	struct drm_device *dev = arg1;
+	char buf[128];
+	int retcode;
+	int i;
+
+	DRM_SYSCTL_PRINT("\ncrtc ref count    last     enabled inmodeset\n");
+	for(i = 0 ; i < dev->num_crtcs ; i++) {
+		DRM_SYSCTL_PRINT("  %02d  %02d %08d %08d %02d      %02d\n",
+		    i, atomic_load_acq_32(&dev->vblank[i].refcount),
+		    atomic_load_acq_32(&dev->vblank[i].count),
+		    atomic_load_acq_32(&dev->vblank[i].last),
+		    atomic_load_acq_int(&dev->vblank[i].enabled),
+		    atomic_load_acq_int(&dev->vblank[i].inmodeset));
+	}
+
+	SYSCTL_OUT(req, "", -1);
+done:
+	return retcode;
+}

Modified: stable/7/sys/dev/drm/i915_dma.c
==============================================================================
--- stable/7/sys/dev/drm/i915_dma.c	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/i915_dma.c	Mon Jul 27 16:05:51 2009	(r195912)
@@ -644,18 +644,17 @@ static int i915_batchbuffer(struct drm_d
 			return -EFAULT;
 		}
 	}
-	DRM_LOCK();
 
 	ret = i915_dispatch_batchbuffer(dev, batch);
 
-	if (sarea_priv)
-		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-
-	DRM_UNLOCK();
 	if (batch->num_cliprects)
 		vsunlock(batch->cliprects, cliplen);
+
 	DRM_LOCK();
 
+	if (sarea_priv)
+		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+
 	return ret;
 }
 
@@ -697,10 +696,9 @@ static int i915_cmdbuffer(struct drm_dev
 			return -EFAULT;
 		}
 	}
-	DRM_LOCK();
 
 	ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
-	DRM_UNLOCK();
+
 	if (cmdbuf->num_cliprects) {
 		vsunlock(cmdbuf->buf, cmdbuf->sz);
 		vsunlock(cmdbuf->cliprects, cliplen);

Modified: stable/7/sys/dev/drm/i915_drv.c
==============================================================================
--- stable/7/sys/dev/drm/i915_drv.c	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/i915_drv.c	Mon Jul 27 16:05:51 2009	(r195912)
@@ -52,7 +52,10 @@ static int i915_suspend(device_t kdev)
 		return -ENODEV;
 	}
 
+	DRM_LOCK();
+	DRM_DEBUG("starting suspend\n");
 	i915_save_state(dev);
+	DRM_UNLOCK();
 
 	return (bus_generic_suspend(kdev));
 }
@@ -61,7 +64,10 @@ static int i915_resume(device_t kdev)
 {
 	struct drm_device *dev = device_get_softc(kdev);
 
+	DRM_LOCK();
 	i915_restore_state(dev);
+	DRM_DEBUG("finished resume\n");
+	DRM_UNLOCK();
 
 	return (bus_generic_resume(kdev));
 }

Modified: stable/7/sys/dev/drm/i915_drv.h
==============================================================================
--- stable/7/sys/dev/drm/i915_drv.h	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/i915_drv.h	Mon Jul 27 16:05:51 2009	(r195912)
@@ -129,7 +129,6 @@ typedef struct drm_i915_private {
 	int page_flipping;
 
 	wait_queue_head_t irq_queue;
-	atomic_t irq_received;
 	/** Protects user_irq_refcount and irq_mask_reg */
 	DRM_SPINTYPE user_irq_lock;
 	/** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */

Modified: stable/7/sys/dev/drm/i915_irq.c
==============================================================================
--- stable/7/sys/dev/drm/i915_irq.c	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/i915_irq.c	Mon Jul 27 16:05:51 2009	(r195912)
@@ -53,12 +53,6 @@ __FBSDID("$FreeBSD$");
 #define I915_INTERRUPT_ENABLE_MASK	(I915_INTERRUPT_ENABLE_FIX | \
 				    	 I915_INTERRUPT_ENABLE_VAR)
 
-#define I915_PIPE_VBLANK_STATUS		(PIPE_START_VBLANK_INTERRUPT_STATUS |\
-					 PIPE_VBLANK_INTERRUPT_STATUS)
- 
-#define I915_PIPE_VBLANK_ENABLE		(PIPE_START_VBLANK_INTERRUPT_ENABLE |\
-					 PIPE_VBLANK_INTERRUPT_ENABLE)
-  
 #define DRM_I915_VBLANK_PIPE_ALL	(DRM_I915_VBLANK_PIPE_A | \
 					 DRM_I915_VBLANK_PIPE_B)
 
@@ -154,7 +148,7 @@ u32 i915_get_vblank_counter(struct drm_d
 	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
 
 	if (!i915_pipe_enabled(dev, pipe)) {
-		DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+		DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
 		return 0;
 	}
 
@@ -183,7 +177,7 @@ u32 g45_get_vblank_counter(struct drm_de
 	int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
 
 	if (!i915_pipe_enabled(dev, pipe)) {
-		DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+		DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
 		return 0;
 	}
 
@@ -200,12 +194,10 @@ irqreturn_t i915_driver_irq_handler(DRM_
 	u32 vblank_enable;
 	int irq_received;
 
-	atomic_inc(&dev_priv->irq_received);
-
 	iir = I915_READ(IIR);
 
 	if (IS_I965G(dev)) {
-		vblank_status = I915_START_VBLANK_INTERRUPT_STATUS;
+		vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
 		vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE;
 	} else {
 		vblank_status = I915_VBLANK_INTERRUPT_STATUS;
@@ -305,9 +297,12 @@ void i915_user_irq_get(struct drm_device
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
+	if (dev->irq_enabled == 0)
+		return;
+
 	DRM_DEBUG("\n");
 	DRM_SPINLOCK(&dev_priv->user_irq_lock);
-	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
+	if (++dev_priv->user_irq_refcount == 1)
 		i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
 	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
 }
@@ -316,12 +311,13 @@ void i915_user_irq_put(struct drm_device
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
+	if (dev->irq_enabled == 0)
+		return;
+
 	DRM_SPINLOCK(&dev_priv->user_irq_lock);
-	if (dev->irq_enabled) {
-		KASSERT(dev_priv->user_irq_refcount > 0, ("invalid refcount"));
-		if (--dev_priv->user_irq_refcount == 0)
-			i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
-	}
+	KASSERT(dev_priv->user_irq_refcount > 0, ("invalid refcount"));
+	if (--dev_priv->user_irq_refcount == 0)
+		i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
 	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
 }
 
@@ -408,11 +404,8 @@ int i915_irq_wait(struct drm_device *dev
 int i915_enable_vblank(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-	u32 pipeconf;
 
-	pipeconf = I915_READ(pipeconf_reg);
-	if (!(pipeconf & PIPEACONF_ENABLE))
+	if (!i915_pipe_enabled(dev, pipe))
 		return -EINVAL;
 
 	DRM_SPINLOCK(&dev_priv->user_irq_lock);
@@ -500,8 +493,6 @@ void i915_driver_irq_preinstall(struct d
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	atomic_set_int(&dev_priv->irq_received, 0);
-
 	I915_WRITE(HWSTAM, 0xeffe);
 	I915_WRITE(PIPEASTAT, 0);
 	I915_WRITE(PIPEBSTAT, 0);
@@ -519,9 +510,6 @@ int i915_driver_irq_postinstall(struct d
 	/* Unmask the interrupts that we always want on. */
 	dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
 
-	dev_priv->pipestat[0] = 0;
-	dev_priv->pipestat[1] = 0;
-
 	/* Disable pipe interrupt enables, clear pending pipe status */
 	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
 	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
@@ -531,6 +519,10 @@ int i915_driver_irq_postinstall(struct d
 
 	I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
 	I915_WRITE(IMR, dev_priv->irq_mask_reg);
+	I915_WRITE(PIPEASTAT, dev_priv->pipestat[0] |
+	    (dev_priv->pipestat[0] >> 16));
+	I915_WRITE(PIPEBSTAT, dev_priv->pipestat[1] |
+	    (dev_priv->pipestat[1] >> 16));
 	(void) I915_READ(IER);
 
 	return 0;

Modified: stable/7/sys/dev/drm/radeon_cp.c
==============================================================================
--- stable/7/sys/dev/drm/radeon_cp.c	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/radeon_cp.c	Mon Jul 27 16:05:51 2009	(r195912)
@@ -2064,16 +2064,22 @@ int radeon_driver_load(struct drm_device
 			 drm_get_resource_len(dev, 2), _DRM_REGISTERS,
 			 _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio);
 	if (ret != 0)
-		return ret;
+		goto error;
 
 	ret = drm_vblank_init(dev, 2);
-	if (ret) {
-		radeon_driver_unload(dev);
-		return ret;
-	}
+	if (ret != 0)
+		goto error;
+
+	dev->max_vblank_count = 0x001fffff;
 
 	DRM_DEBUG("%s card detected\n",
-		  ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
+		  ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" :
+		    (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
+
+	return ret;
+
+error:
+	radeon_driver_unload(dev);
 	return ret;
 }
 

Modified: stable/7/sys/dev/drm/radeon_irq.c
==============================================================================
--- stable/7/sys/dev/drm/radeon_irq.c	Mon Jul 27 16:03:04 2009	(r195911)
+++ stable/7/sys/dev/drm/radeon_irq.c	Mon Jul 27 16:05:51 2009	(r195912)
@@ -380,8 +380,6 @@ int radeon_driver_irq_postinstall(struct
 	atomic_set(&dev_priv->swi_emitted, 0);
 	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
 
-	dev->max_vblank_count = 0x001fffff;
-
 	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
 
 	return 0;


More information about the svn-src-stable-7 mailing list