Module Name:    src
Committed By:   riastradh
Date:           Wed Aug 27 13:21:15 UTC 2014

Modified Files:
        src/sys/external/bsd/drm2/dist/drm/i915: i915_irq.c

Log Message:
Fix i915 locking around error handling.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/external/bsd/drm2/dist/drm/i915/i915_irq.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/dist/drm/i915/i915_irq.c
diff -u src/sys/external/bsd/drm2/dist/drm/i915/i915_irq.c:1.6 src/sys/external/bsd/drm2/dist/drm/i915/i915_irq.c:1.7
--- src/sys/external/bsd/drm2/dist/drm/i915/i915_irq.c:1.6	Wed Jul 16 20:56:25 2014
+++ src/sys/external/bsd/drm2/dist/drm/i915/i915_irq.c	Wed Aug 27 13:21:15 2014
@@ -1099,7 +1099,9 @@ static void notify_ring(struct drm_devic
     {
 	unsigned long flags;
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	/* XXX Set a flag under the lock...  */
+	/*
+	 * XXX Set a flag under the lock or push the lock out to callers.
+	 */
 	DRM_SPIN_WAKEUP_ALL(&ring->irq_queue, &dev_priv->irq_lock);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
     }
@@ -1315,8 +1317,10 @@ static void snb_gt_irq_handler(struct dr
 	if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
 		      GT_BSD_CS_ERROR_INTERRUPT |
 		      GT_RENDER_CS_MASTER_ERROR_INTERRUPT)) {
+		spin_lock(&dev_priv->irq_lock);
 		i915_handle_error(dev, false, "GT error interrupt 0x%08x",
 				  gt_iir);
+		spin_unlock(&dev_priv->irq_lock);
 	}
 
 	if (gt_iir & GT_PARITY_ERROR(dev))
@@ -1589,9 +1593,11 @@ static void gen6_rps_irq_handler(struct 
 			notify_ring(dev_priv->dev, &dev_priv->ring[VECS]);
 
 		if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) {
+			spin_lock(&dev_priv->irq_lock);
 			i915_handle_error(dev_priv->dev, false,
 					  "VEBOX CS error interrupt 0x%08x",
 					  pm_iir);
+			spin_unlock(&dev_priv->irq_lock);
 		}
 	}
 }
@@ -2357,6 +2363,8 @@ void i915_handle_error(struct drm_device
 	va_list args;
 	char error_msg[80];
 
+	assert_spin_locked(&dev_priv->irq_lock);
+
 	va_start(args, fmt);
 	vscnprintf(error_msg, sizeof(error_msg), fmt, args);
 	va_end(args);
@@ -2734,6 +2742,8 @@ static void i915_hangcheck_elapsed(unsig
 	if (!i915.enable_hangcheck)
 		return;
 
+	spin_lock(&dev_priv->irq_lock);
+
 	for_each_ring(ring, dev_priv, i) {
 		u64 acthd;
 		u32 seqno;
@@ -2747,9 +2757,7 @@ static void i915_hangcheck_elapsed(unsig
 		if (ring->hangcheck.seqno == seqno) {
 			if (ring_idle(ring, seqno)) {
 				ring->hangcheck.action = HANGCHECK_IDLE;
-
 #ifdef __NetBSD__
-				spin_lock(&dev_priv->irq_lock);
 				if (DRM_SPIN_WAITERS_P(&ring->irq_queue,
 					&dev_priv->irq_lock)) {
 					if (!test_and_set_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings)) {
@@ -2765,7 +2773,6 @@ static void i915_hangcheck_elapsed(unsig
 				} else {
 					busy = false;
 				}
-				spin_unlock(&dev_priv->irq_lock);
 #else
 				if (waitqueue_active(&ring->irq_queue)) {
 					/* Issue a wake-up to catch stuck h/w. */
@@ -2845,6 +2852,8 @@ static void i915_hangcheck_elapsed(unsig
 	if (rings_hung)
 		return i915_handle_error(dev, true, "Ring hung");
 
+	spin_unlock(&dev_priv->irq_lock);
+
 	if (busy_count)
 		/* Reset timer case chip hangs without another request
 		 * being added */

Reply via email to