Commit d9bc7e9f authored by Chris Wilson's avatar Chris Wilson

drm/i915: Fix infinite loop regression from 21dd3734

By returning EAGAIN upon a wedged GPU before attempting to wait, we
would hit an infinite loop of repeating operation without ever
progressing. Instead this needs to be EIO so that userspace knows that
the GPU is truly wedged and not in the process of error recovery.

Similarly, we need to handle the error recovery during i915_gem_fault.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent dcbe6f2b
...@@ -1171,9 +1171,11 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -1171,9 +1171,11 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
PAGE_SHIFT; PAGE_SHIFT;
/* Now bind it into the GTT if needed */ ret = i915_mutex_lock_interruptible(dev);
mutex_lock(&dev->struct_mutex); if (ret)
goto out;
/* Now bind it into the GTT if needed */
if (!obj->map_and_fenceable) { if (!obj->map_and_fenceable) {
ret = i915_gem_object_unbind(obj); ret = i915_gem_object_unbind(obj);
if (ret) if (ret)
...@@ -1208,9 +1210,17 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -1208,9 +1210,17 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
unlock: unlock:
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
out:
switch (ret) { switch (ret) {
case -EIO:
case -EAGAIN: case -EAGAIN:
/* Give the error handler a chance to run and move the
* objects off the GPU active list. Next time we service the
* fault, we should be able to transition the page into the
* GTT without touching the GPU (and so avoid further
* EIO/EGAIN). If the GPU is wedged, then there is no issue
* with coherency, just lost writes.
*/
set_need_resched(); set_need_resched();
case 0: case 0:
case -ERESTARTSYS: case -ERESTARTSYS:
...@@ -1981,8 +1991,18 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, ...@@ -1981,8 +1991,18 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
BUG_ON(seqno == 0); BUG_ON(seqno == 0);
if (atomic_read(&dev_priv->mm.wedged)) if (atomic_read(&dev_priv->mm.wedged)) {
return -EAGAIN; struct completion *x = &dev_priv->error_completion;
bool recovery_complete;
unsigned long flags;
/* Give the error handler a chance to run. */
spin_lock_irqsave(&x->wait.lock, flags);
recovery_complete = x->done > 0;
spin_unlock_irqrestore(&x->wait.lock, flags);
return recovery_complete ? -EIO : -EAGAIN;
}
if (seqno == ring->outstanding_lazy_request) { if (seqno == ring->outstanding_lazy_request) {
struct drm_i915_gem_request *request; struct drm_i915_gem_request *request;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment