[PATCH] drm/i915: Drop mutex whilst waiting for a request.

Chris Wilson chris at chris-wilson.co.uk
Wed Feb 4 05:43:57 PST 2009


i915_wait_request() has the habit of taking an arbitrary long time and
so it is not wise to hold onto the struct_mutex for the duration. For
example, when the chip hangs this stops the user from querying the device
state using the proc/debug interfaces.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_drv.h      |    9 +++++----
 drivers/gpu/drm/i915/i915_gem.c      |   34 ++++++++++++++++++----------------
 drivers/gpu/drm/i915/i915_gem_proc.c |    5 +++--
 drivers/gpu/drm/i915/i915_irq.c      |    3 ++-
 4 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a70bf77..3314059 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -344,9 +344,10 @@ typedef struct drm_i915_private {
 		uint32_t waiting_gem_seqno;
 
 		/**
-		 * Last seq seen at irq time
+		 * Last seq seen at irq time, accessed outside of mutex by
+		 * waiter.
 		 */
-		uint32_t irq_gem_seqno;
+		atomic_t irq_gem_seqno;
 
 		/**
 		 * Flag if the X Server, and thus DRM, is not currently in
@@ -363,9 +364,9 @@ typedef struct drm_i915_private {
 		 *
 		 * This is set when attempts to idle the device timeout.
 		 * It prevents command submission from occuring and makes
-		 * every pending request fail
+		 * every pending request fail.
 		 */
-		int wedged;
+		atomic_t wedged;
 
 		/** Bit 6 swizzling required for X tiling */
 		uint32_t bit_6_swizzle_x;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 6a9e3a8..30c69a4 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1027,8 +1027,10 @@ i915_gem_retire_requests(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t seqno;
+	int is_wedged;
 
 	seqno = i915_get_gem_seqno(dev);
+	is_wedged = atomic_read(&dev_priv->mm.wedged);
 
 	while (!list_empty(&dev_priv->mm.request_list)) {
 		struct drm_i915_gem_request *request;
@@ -1039,8 +1041,7 @@ i915_gem_retire_requests(struct drm_device *dev)
 					   list);
 		retiring_seqno = request->seqno;
 
-		if (i915_seqno_passed(seqno, retiring_seqno) ||
-		    dev_priv->mm.wedged) {
+		if (i915_seqno_passed(seqno, retiring_seqno) || is_wedged) {
 			i915_gem_retire_request(dev, request);
 
 			list_del(&request->list);
@@ -1083,14 +1084,16 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
 	if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
 		dev_priv->mm.waiting_gem_seqno = seqno;
 		i915_user_irq_get(dev);
+		mutex_unlock(&dev->struct_mutex);
 		ret = wait_event_interruptible(dev_priv->irq_queue,
-					       i915_seqno_passed(i915_get_gem_seqno(dev),
+					       i915_seqno_passed(atomic_read(&dev_priv->mm.irq_gem_seqno),
 								 seqno) ||
-					       dev_priv->mm.wedged);
+					       atomic_read(&dev_priv->mm.wedged));
+		mutex_lock(&dev->struct_mutex);
 		i915_user_irq_put(dev);
 		dev_priv->mm.waiting_gem_seqno = 0;
 	}
-	if (dev_priv->mm.wedged)
+	if (atomic_read(&dev_priv->mm.wedged))
 		ret = -EIO;
 
 	if (ret && ret != -ERESTARTSYS)
@@ -2449,6 +2452,11 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
 		return -EINVAL;
 	}
+	if (atomic_read(&dev_priv->mm.wedged)) {
+		DRM_ERROR("Execbuf while wedged\n");
+		return -EIO;
+	}
+
 	/* Copy in the exec list from userland */
 	exec_list = drm_calloc(sizeof(*exec_list), args->buffer_count,
 			       DRM_MEM_DRIVER);
@@ -2475,16 +2483,10 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 
 	i915_verify_inactive(dev, __FILE__, __LINE__);
 
-	if (dev_priv->mm.wedged) {
-		DRM_ERROR("Execbuf while wedged\n");
-		mutex_unlock(&dev->struct_mutex);
-		return -EIO;
-	}
-
 	if (dev_priv->mm.suspended) {
 		DRM_ERROR("Execbuf while VT-switched.\n");
 		mutex_unlock(&dev->struct_mutex);
-		return -EBUSY;
+		goto pre_mutex_err;
 	}
 
 	/* Look up object handles */
@@ -2995,7 +2997,7 @@ i915_gem_idle(struct drm_device *dev)
 		if (last_seqno == cur_seqno) {
 			if (stuck++ > 100) {
 				DRM_ERROR("hardware wedged\n");
-				dev_priv->mm.wedged = 1;
+				atomic_set(&dev_priv->mm.wedged, 1);
 				DRM_WAKEUP(&dev_priv->irq_queue);
 				break;
 			}
@@ -3007,7 +3009,7 @@ i915_gem_idle(struct drm_device *dev)
 
 	i915_gem_retire_requests(dev);
 
-	if (!dev_priv->mm.wedged) {
+	if (!atomic_read(&dev_priv->mm.wedged)) {
 		/* Active and flushing should now be empty as we've
 		 * waited for a sequence higher than any pending execbuffer
 		 */
@@ -3252,9 +3254,9 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return 0;
 
-	if (dev_priv->mm.wedged) {
+	if (atomic_read(&dev_priv->mm.wedged)) {
 		DRM_ERROR("Reenabling wedged hardware, good luck\n");
-		dev_priv->mm.wedged = 0;
+		atomic_set(&dev_priv->mm.wedged, 0);
 	}
 
 	mutex_lock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c
index 4d1b9de..ff0c4c8 100644
--- a/drivers/gpu/drm/i915/i915_gem_proc.c
+++ b/drivers/gpu/drm/i915/i915_gem_proc.c
@@ -199,7 +199,8 @@ static int i915_gem_seqno_info(char *buf, char **start, off_t offset,
 	}
 	DRM_PROC_PRINT("Waiter sequence:  %d\n",
 		       dev_priv->mm.waiting_gem_seqno);
-	DRM_PROC_PRINT("IRQ sequence:     %d\n", dev_priv->mm.irq_gem_seqno);
+	DRM_PROC_PRINT("IRQ sequence:     %d\n",
+		       atomic_read(&dev_priv->mm.irq_gem_seqno));
 	if (len > request + offset)
 		return request;
 	*eof = 1;
@@ -243,7 +244,7 @@ static int i915_interrupt_info(char *buf, char **start, off_t offset,
 	DRM_PROC_PRINT("Waiter sequence:     %d\n",
 		       dev_priv->mm.waiting_gem_seqno);
 	DRM_PROC_PRINT("IRQ sequence:        %d\n",
-		       dev_priv->mm.irq_gem_seqno);
+		       atomic_read(&dev_priv->mm.irq_gem_seqno));
 	if (len > request + offset)
 		return request;
 	*eof = 1;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 6290219..9d42480 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -242,7 +242,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 		}
 
 		if (iir & I915_USER_INTERRUPT) {
-			dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
+			atomic_set(&dev_priv->mm.irq_gem_seqno,
+				  i915_get_gem_seqno(dev));
 			DRM_WAKEUP(&dev_priv->irq_queue);
 		}
 
-- 
1.6.0.4


--=-/IUot6BTtCLH2SFz7nwd--



More information about the Intel-gfx mailing list