drm/i915: Defer reporting EIO until we try to use the GPU
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 26 Jan 2011 15:55:56 +0000 (15:55 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 27 Jan 2011 11:06:07 +0000 (11:06 +0000)
Instead of reporting EIO upfront in the entrance of an ioctl that may or
may not attempt to use the GPU, defer the actual detection of an invalid
ioctl to when we issue a GPU instruction. This allows us to continue to
use bo in video memory (via pread/pwrite and mmap) after the GPU has hung.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/intel_ringbuffer.c

index a39f8d254502db348830dad896b75666484c0761..ff498b98c9bd3e212957406af53a3e627ece7e10 100644 (file)
@@ -1052,7 +1052,6 @@ extern void i915_mem_takedown(struct mem_block **heap);
 extern void i915_mem_release(struct drm_device * dev,
                             struct drm_file *file_priv, struct mem_block *heap);
 /* i915_gem.c */
-int i915_gem_check_is_wedged(struct drm_device *dev);
 int i915_gem_init_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
 int i915_gem_create_ioctl(struct drm_device *dev, void *data,
index b9d4de368de3d1cc47cf723ca2de48c85f2aa48c..52dd77b1bb7ceddaf34bd1a145aa51d6520de953 100644 (file)
@@ -75,8 +75,8 @@ static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv,
        dev_priv->mm.object_memory -= size;
 }
 
-int
-i915_gem_check_is_wedged(struct drm_device *dev)
+static int
+i915_gem_wait_for_error(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct completion *x = &dev_priv->error_completion;
@@ -90,27 +90,24 @@ i915_gem_check_is_wedged(struct drm_device *dev)
        if (ret)
                return ret;
 
-       /* Success, we reset the GPU! */
-       if (!atomic_read(&dev_priv->mm.wedged))
-               return 0;
-
-       /* GPU is hung, bump the completion count to account for
-        * the token we just consumed so that we never hit zero and
-        * end up waiting upon a subsequent completion event that
-        * will never happen.
-        */
-       spin_lock_irqsave(&x->wait.lock, flags);
-       x->done++;
-       spin_unlock_irqrestore(&x->wait.lock, flags);
-       return -EIO;
+       if (atomic_read(&dev_priv->mm.wedged)) {
+               /* GPU is hung, bump the completion count to account for
+                * the token we just consumed so that we never hit zero and
+                * end up waiting upon a subsequent completion event that
+                * will never happen.
+                */
+               spin_lock_irqsave(&x->wait.lock, flags);
+               x->done++;
+               spin_unlock_irqrestore(&x->wait.lock, flags);
+       }
+       return 0;
 }
 
 int i915_mutex_lock_interruptible(struct drm_device *dev)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
-       ret = i915_gem_check_is_wedged(dev);
+       ret = i915_gem_wait_for_error(dev);
        if (ret)
                return ret;
 
@@ -118,11 +115,6 @@ int i915_mutex_lock_interruptible(struct drm_device *dev)
        if (ret)
                return ret;
 
-       if (atomic_read(&dev_priv->mm.wedged)) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EAGAIN;
-       }
-
        WARN_ON(i915_verify_lists(dev));
        return 0;
 }
index 22a32b9932c59c45761521415fb3d092d562e855..a093d67b94e28a94363712a339803942f50bd4a4 100644 (file)
@@ -284,11 +284,6 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
        struct drm_i915_gem_set_tiling *args = data;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
-       int ret;
-
-       ret = i915_gem_check_is_wedged(dev);
-       if (ret)
-               return ret;
 
        obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
        if (obj == NULL)
index 5f7bbaa6a60812ed5aee7b0f114384462c48b82a..235d9c4b40ae9bcf4f4c263ee33418bc10fa664b 100644 (file)
@@ -980,9 +980,13 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
 int intel_ring_begin(struct intel_ring_buffer *ring,
                     int num_dwords)
 {
+       struct drm_i915_private *dev_priv = ring->dev->dev_private;
        int n = 4*num_dwords;
        int ret;
 
+       if (unlikely(atomic_read(&dev_priv->mm.wedged)))
+               return -EIO;
+
        if (unlikely(ring->tail + n > ring->effective_size)) {
                ret = intel_wrap_ring_buffer(ring);
                if (unlikely(ret))