diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-07-04 16:54:13 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-07-05 04:01:14 -0400 |
commit | d6b2c790a4742a69624e6884b48e5d72f275abd0 (patch) | |
tree | 7011657a3754e1e698470c28edacf4158b3fbff4 /drivers/gpu/drm/i915/i915_gem.c | |
parent | d54a02c041ccfdcfe3efcd1e5b90c6e8d5e7a8d9 (diff) |
drm/i915: non-interruptible sleeps can't handle -EAGAIN
So don't return -EAGAIN, even in the case of a gpu hang. Remap it to
-EIO instead. Note that this isn't really an issue with
interruptability, but more that we have quite a few codepaths (mostly
around kms stuff) that simply can't handle any errors and hence not
even -EAGAIN. Instead of adding proper failure paths so that we could
restart these ioctls we've opted for the cheap way out of sleeping
non-interruptibly. Which works everywhere but when the gpu dies,
which this patch fixes.
So essentially interruptible == false means 'wait for the gpu or die
trying'.'
This patch is a bit ugly because intel_ring_begin is all non-interruptible
and hence only returns -EIO. But as the comment in there says,
auditing all the callsites would be a pain.
To avoid duplicating code, reuse i915_gem_check_wedge in __wait_seqno
and intel_wait_ring_buffer. Also use the opportunity to clarify the
different cases in i915_gem_check_wedge a bit with comments.
v2: Don't access dev_priv->mm.interruptible from check_wedge - we
might not hold dev->struct_mutex, making this racy. Instead pass
interruptible in as a parameter. I've noticed this because I've hit a
BUG_ON(!mutex_is_locked) at the top of check_wedge. This has been
added in
commit b4aca0106c466b5a0329318203f65bac2d91b682
Author: Ben Widawsky <ben@bwidawsk.net>
Date: Wed Apr 25 20:50:12 2012 -0700
drm/i915: extract some common olr+wedge code
although that commit is missing any justification for this. I guess
it's just copy&paste, because the same commit add the same BUG_ON
check to check_olr, where it indeed makes sense.
But in check_wedge everything we access is protected by other means,
so this is superflous. And because it now gets in the way (we add a
new caller in __wait_seqno, which can be called without
dev->struct_mutext) let's just remove it.
v3: Group all the i915_gem_check_wedge refactoring into this patch, so
that this patch here is all about not returning -EAGAIN to callsites
that can't handle syscall restarting.
v4: Add clarification what interuptible == fales means in our code,
requested by Ben Widawsky.
v5: Fix EAGAIN mispell noticed by Chris Wilson.
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Tested-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6a98c0659324..af6a510367af 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1863,11 +1863,10 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
1863 | mutex_unlock(&dev->struct_mutex); | 1863 | mutex_unlock(&dev->struct_mutex); |
1864 | } | 1864 | } |
1865 | 1865 | ||
1866 | static int | 1866 | int |
1867 | i915_gem_check_wedge(struct drm_i915_private *dev_priv) | 1867 | i915_gem_check_wedge(struct drm_i915_private *dev_priv, |
1868 | bool interruptible) | ||
1868 | { | 1869 | { |
1869 | BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); | ||
1870 | |||
1871 | if (atomic_read(&dev_priv->mm.wedged)) { | 1870 | if (atomic_read(&dev_priv->mm.wedged)) { |
1872 | struct completion *x = &dev_priv->error_completion; | 1871 | struct completion *x = &dev_priv->error_completion; |
1873 | bool recovery_complete; | 1872 | bool recovery_complete; |
@@ -1878,7 +1877,16 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv) | |||
1878 | recovery_complete = x->done > 0; | 1877 | recovery_complete = x->done > 0; |
1879 | spin_unlock_irqrestore(&x->wait.lock, flags); | 1878 | spin_unlock_irqrestore(&x->wait.lock, flags); |
1880 | 1879 | ||
1881 | return recovery_complete ? -EIO : -EAGAIN; | 1880 | /* Non-interruptible callers can't handle -EAGAIN, hence return |
1881 | * -EIO unconditionally for these. */ | ||
1882 | if (!interruptible) | ||
1883 | return -EIO; | ||
1884 | |||
1885 | /* Recovery complete, but still wedged means reset failure. */ | ||
1886 | if (recovery_complete) | ||
1887 | return -EIO; | ||
1888 | |||
1889 | return -EAGAIN; | ||
1882 | } | 1890 | } |
1883 | 1891 | ||
1884 | return 0; | 1892 | return 0; |
@@ -1932,6 +1940,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, | |||
1932 | unsigned long timeout_jiffies; | 1940 | unsigned long timeout_jiffies; |
1933 | long end; | 1941 | long end; |
1934 | bool wait_forever = true; | 1942 | bool wait_forever = true; |
1943 | int ret; | ||
1935 | 1944 | ||
1936 | if (i915_seqno_passed(ring->get_seqno(ring), seqno)) | 1945 | if (i915_seqno_passed(ring->get_seqno(ring), seqno)) |
1937 | return 0; | 1946 | return 0; |
@@ -1963,8 +1972,9 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, | |||
1963 | end = wait_event_timeout(ring->irq_queue, EXIT_COND, | 1972 | end = wait_event_timeout(ring->irq_queue, EXIT_COND, |
1964 | timeout_jiffies); | 1973 | timeout_jiffies); |
1965 | 1974 | ||
1966 | if (atomic_read(&dev_priv->mm.wedged)) | 1975 | ret = i915_gem_check_wedge(dev_priv, interruptible); |
1967 | end = -EAGAIN; | 1976 | if (ret) |
1977 | end = ret; | ||
1968 | } while (end == 0 && wait_forever); | 1978 | } while (end == 0 && wait_forever); |
1969 | 1979 | ||
1970 | getrawmonotonic(&now); | 1980 | getrawmonotonic(&now); |
@@ -2004,7 +2014,7 @@ i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno) | |||
2004 | 2014 | ||
2005 | BUG_ON(seqno == 0); | 2015 | BUG_ON(seqno == 0); |
2006 | 2016 | ||
2007 | ret = i915_gem_check_wedge(dev_priv); | 2017 | ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); |
2008 | if (ret) | 2018 | if (ret) |
2009 | return ret; | 2019 | return ret; |
2010 | 2020 | ||