aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-09-22 19:43:56 -0400
committerEric Anholt <eric@anholt.net>2009-09-22 21:25:32 -0400
commitc715089f49844260f1eeae8e3b55af9468ba1325 (patch)
tree0d0b72a77c75c84ad2cf4e473fda0b31e976a47a /drivers/gpu
parentab18282d58ce67ee5cd720d99a91c1a2bbf3e693 (diff)
drm/i915: Handle ERESTARTSYS during page fault
During a page fault and rebinding the buffer there exists a window for a signal to arrive during the i915_wait_request() and trigger a ERESTARTSYS. This used to be handled by returning SIGBUS and thereby killing the application. Try 'cairo-perf-trace & cairo-test-suite' and watch X go boom! The solution as suggested by H. Peter Anvin is to simply return NOPAGE and leave the higher layers to spot we did not fill the page and resubmit the page fault. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: stable@kernel.org [anholt: Mostly squash it with another commit]
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 4755ba41bfef..6129b7b4f1a5 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1200,26 +1200,21 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1200 mutex_lock(&dev->struct_mutex); 1200 mutex_lock(&dev->struct_mutex);
1201 if (!obj_priv->gtt_space) { 1201 if (!obj_priv->gtt_space) {
1202 ret = i915_gem_object_bind_to_gtt(obj, 0); 1202 ret = i915_gem_object_bind_to_gtt(obj, 0);
1203 if (ret) { 1203 if (ret)
1204 mutex_unlock(&dev->struct_mutex); 1204 goto unlock;
1205 return VM_FAULT_SIGBUS; 1205
1206 }
1207 list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); 1206 list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
1208 1207
1209 ret = i915_gem_object_set_to_gtt_domain(obj, write); 1208 ret = i915_gem_object_set_to_gtt_domain(obj, write);
1210 if (ret) { 1209 if (ret)
1211 mutex_unlock(&dev->struct_mutex); 1210 goto unlock;
1212 return VM_FAULT_SIGBUS;
1213 }
1214 } 1211 }
1215 1212
1216 /* Need a new fence register? */ 1213 /* Need a new fence register? */
1217 if (obj_priv->tiling_mode != I915_TILING_NONE) { 1214 if (obj_priv->tiling_mode != I915_TILING_NONE) {
1218 ret = i915_gem_object_get_fence_reg(obj); 1215 ret = i915_gem_object_get_fence_reg(obj);
1219 if (ret) { 1216 if (ret)
1220 mutex_unlock(&dev->struct_mutex); 1217 goto unlock;
1221 return VM_FAULT_SIGBUS;
1222 }
1223 } 1218 }
1224 1219
1225 pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + 1220 pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
@@ -1227,18 +1222,18 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1227 1222
1228 /* Finally, remap it using the new GTT offset */ 1223 /* Finally, remap it using the new GTT offset */
1229 ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); 1224 ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
1230 1225unlock:
1231 mutex_unlock(&dev->struct_mutex); 1226 mutex_unlock(&dev->struct_mutex);
1232 1227
1233 switch (ret) { 1228 switch (ret) {
1229 case 0:
1230 case -ERESTARTSYS:
1231 return VM_FAULT_NOPAGE;
1234 case -ENOMEM: 1232 case -ENOMEM:
1235 case -EAGAIN: 1233 case -EAGAIN:
1236 return VM_FAULT_OOM; 1234 return VM_FAULT_OOM;
1237 case -EFAULT:
1238 case -EINVAL:
1239 return VM_FAULT_SIGBUS;
1240 default: 1235 default:
1241 return VM_FAULT_NOPAGE; 1236 return VM_FAULT_SIGBUS;
1242 } 1237 }
1243} 1238}
1244 1239