[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