diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-25 06:22:51 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-25 07:23:12 -0400 |
commit | 76c1dec1979d9b552aab9600eb898ccec394fbbc (patch) | |
tree | 8e86c83b9b2bb10b556d153238cb4d6e4ca201d9 | |
parent | 30dbf0c07ff4e3e21b827e2a9d6ff7eb34458819 (diff) |
drm/i915: Make the mutex_lock interruptible on ioctl paths
... and combine it with the wedged completion handler.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 126 |
1 files changed, 84 insertions, 42 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a7283092c233..ac5bff85a4c7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -91,6 +91,26 @@ i915_gem_check_is_wedged(struct drm_device *dev) | |||
91 | return -EIO; | 91 | return -EIO; |
92 | } | 92 | } |
93 | 93 | ||
94 | static int i915_mutex_lock_interruptible(struct drm_device *dev) | ||
95 | { | ||
96 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
97 | int ret; | ||
98 | |||
99 | ret = i915_gem_check_is_wedged(dev); | ||
100 | if (ret) | ||
101 | return ret; | ||
102 | |||
103 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
104 | if (ret) | ||
105 | return ret; | ||
106 | |||
107 | if (atomic_read(&dev_priv->mm.wedged)) { | ||
108 | mutex_unlock(&dev->struct_mutex); | ||
109 | return -EAGAIN; | ||
110 | } | ||
111 | |||
112 | return 0; | ||
113 | } | ||
94 | 114 | ||
95 | static inline bool | 115 | static inline bool |
96 | i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) | 116 | i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) |
@@ -299,7 +319,9 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
299 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 319 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
300 | remain = args->size; | 320 | remain = args->size; |
301 | 321 | ||
302 | mutex_lock(&dev->struct_mutex); | 322 | ret = i915_mutex_lock_interruptible(dev); |
323 | if (ret) | ||
324 | return ret; | ||
303 | 325 | ||
304 | ret = i915_gem_object_get_pages(obj, 0); | 326 | ret = i915_gem_object_get_pages(obj, 0); |
305 | if (ret != 0) | 327 | if (ret != 0) |
@@ -418,7 +440,9 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
418 | 440 | ||
419 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); | 441 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); |
420 | 442 | ||
421 | mutex_lock(&dev->struct_mutex); | 443 | ret = i915_mutex_lock_interruptible(dev); |
444 | if (ret) | ||
445 | goto fail_put_user_pages; | ||
422 | 446 | ||
423 | ret = i915_gem_object_get_pages_or_evict(obj); | 447 | ret = i915_gem_object_get_pages_or_evict(obj); |
424 | if (ret) | 448 | if (ret) |
@@ -617,8 +641,10 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
617 | if (!access_ok(VERIFY_READ, user_data, remain)) | 641 | if (!access_ok(VERIFY_READ, user_data, remain)) |
618 | return -EFAULT; | 642 | return -EFAULT; |
619 | 643 | ||
644 | ret = i915_mutex_lock_interruptible(dev); | ||
645 | if (ret) | ||
646 | return ret; | ||
620 | 647 | ||
621 | mutex_lock(&dev->struct_mutex); | ||
622 | ret = i915_gem_object_pin(obj, 0); | 648 | ret = i915_gem_object_pin(obj, 0); |
623 | if (ret) { | 649 | if (ret) { |
624 | mutex_unlock(&dev->struct_mutex); | 650 | mutex_unlock(&dev->struct_mutex); |
@@ -713,7 +739,10 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
713 | goto out_unpin_pages; | 739 | goto out_unpin_pages; |
714 | } | 740 | } |
715 | 741 | ||
716 | mutex_lock(&dev->struct_mutex); | 742 | ret = i915_mutex_lock_interruptible(dev); |
743 | if (ret) | ||
744 | goto out_unpin_pages; | ||
745 | |||
717 | ret = i915_gem_object_pin(obj, 0); | 746 | ret = i915_gem_object_pin(obj, 0); |
718 | if (ret) | 747 | if (ret) |
719 | goto out_unlock; | 748 | goto out_unlock; |
@@ -787,7 +816,9 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
787 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 816 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
788 | remain = args->size; | 817 | remain = args->size; |
789 | 818 | ||
790 | mutex_lock(&dev->struct_mutex); | 819 | ret = i915_mutex_lock_interruptible(dev); |
820 | if (ret) | ||
821 | return ret; | ||
791 | 822 | ||
792 | ret = i915_gem_object_get_pages(obj, 0); | 823 | ret = i915_gem_object_get_pages(obj, 0); |
793 | if (ret != 0) | 824 | if (ret != 0) |
@@ -883,7 +914,9 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
883 | 914 | ||
884 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); | 915 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); |
885 | 916 | ||
886 | mutex_lock(&dev->struct_mutex); | 917 | ret = i915_mutex_lock_interruptible(dev); |
918 | if (ret) | ||
919 | goto fail_put_user_pages; | ||
887 | 920 | ||
888 | ret = i915_gem_object_get_pages_or_evict(obj); | 921 | ret = i915_gem_object_get_pages_or_evict(obj); |
889 | if (ret) | 922 | if (ret) |
@@ -1051,7 +1084,11 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
1051 | return -ENOENT; | 1084 | return -ENOENT; |
1052 | obj_priv = to_intel_bo(obj); | 1085 | obj_priv = to_intel_bo(obj); |
1053 | 1086 | ||
1054 | mutex_lock(&dev->struct_mutex); | 1087 | ret = i915_mutex_lock_interruptible(dev); |
1088 | if (ret) { | ||
1089 | drm_gem_object_unreference_unlocked(obj); | ||
1090 | return ret; | ||
1091 | } | ||
1055 | 1092 | ||
1056 | intel_mark_busy(dev, obj); | 1093 | intel_mark_busy(dev, obj); |
1057 | 1094 | ||
@@ -1106,11 +1143,14 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, | |||
1106 | if (!(dev->driver->driver_features & DRIVER_GEM)) | 1143 | if (!(dev->driver->driver_features & DRIVER_GEM)) |
1107 | return -ENODEV; | 1144 | return -ENODEV; |
1108 | 1145 | ||
1109 | mutex_lock(&dev->struct_mutex); | ||
1110 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1146 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1111 | if (obj == NULL) { | 1147 | if (obj == NULL) |
1112 | mutex_unlock(&dev->struct_mutex); | ||
1113 | return -ENOENT; | 1148 | return -ENOENT; |
1149 | |||
1150 | ret = i915_mutex_lock_interruptible(dev); | ||
1151 | if (ret) { | ||
1152 | drm_gem_object_unreference_unlocked(obj); | ||
1153 | return ret; | ||
1114 | } | 1154 | } |
1115 | 1155 | ||
1116 | #if WATCH_BUF | 1156 | #if WATCH_BUF |
@@ -1425,7 +1465,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1425 | if (obj == NULL) | 1465 | if (obj == NULL) |
1426 | return -ENOENT; | 1466 | return -ENOENT; |
1427 | 1467 | ||
1428 | mutex_lock(&dev->struct_mutex); | 1468 | ret = i915_mutex_lock_interruptible(dev); |
1469 | if (ret) { | ||
1470 | drm_gem_object_unreference_unlocked(obj); | ||
1471 | return ret; | ||
1472 | } | ||
1429 | 1473 | ||
1430 | obj_priv = to_intel_bo(obj); | 1474 | obj_priv = to_intel_bo(obj); |
1431 | 1475 | ||
@@ -3668,16 +3712,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3668 | if (ret != 0) | 3712 | if (ret != 0) |
3669 | goto pre_mutex_err; | 3713 | goto pre_mutex_err; |
3670 | 3714 | ||
3671 | mutex_lock(&dev->struct_mutex); | 3715 | ret = i915_mutex_lock_interruptible(dev); |
3716 | if (ret) | ||
3717 | goto pre_mutex_err; | ||
3672 | 3718 | ||
3673 | i915_verify_inactive(dev, __FILE__, __LINE__); | 3719 | i915_verify_inactive(dev, __FILE__, __LINE__); |
3674 | 3720 | ||
3675 | if (atomic_read(&dev_priv->mm.wedged)) { | ||
3676 | mutex_unlock(&dev->struct_mutex); | ||
3677 | ret = -EAGAIN; | ||
3678 | goto pre_mutex_err; | ||
3679 | } | ||
3680 | |||
3681 | if (dev_priv->mm.suspended) { | 3721 | if (dev_priv->mm.suspended) { |
3682 | mutex_unlock(&dev->struct_mutex); | 3722 | mutex_unlock(&dev->struct_mutex); |
3683 | ret = -EBUSY; | 3723 | ret = -EBUSY; |
@@ -4161,21 +4201,20 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
4161 | struct drm_i915_gem_object *obj_priv; | 4201 | struct drm_i915_gem_object *obj_priv; |
4162 | int ret; | 4202 | int ret; |
4163 | 4203 | ||
4164 | ret = i915_gem_check_is_wedged(dev); | ||
4165 | if (ret) | ||
4166 | return ret; | ||
4167 | |||
4168 | mutex_lock(&dev->struct_mutex); | ||
4169 | |||
4170 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4204 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4171 | if (obj == NULL) { | 4205 | if (obj == NULL) { |
4172 | DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", | 4206 | DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", |
4173 | args->handle); | 4207 | args->handle); |
4174 | mutex_unlock(&dev->struct_mutex); | ||
4175 | return -ENOENT; | 4208 | return -ENOENT; |
4176 | } | 4209 | } |
4177 | obj_priv = to_intel_bo(obj); | 4210 | obj_priv = to_intel_bo(obj); |
4178 | 4211 | ||
4212 | ret = i915_mutex_lock_interruptible(dev); | ||
4213 | if (ret) { | ||
4214 | drm_gem_object_unreference_unlocked(obj); | ||
4215 | return ret; | ||
4216 | } | ||
4217 | |||
4179 | if (obj_priv->madv != I915_MADV_WILLNEED) { | 4218 | if (obj_priv->madv != I915_MADV_WILLNEED) { |
4180 | DRM_ERROR("Attempting to pin a purgeable buffer\n"); | 4219 | DRM_ERROR("Attempting to pin a purgeable buffer\n"); |
4181 | drm_gem_object_unreference(obj); | 4220 | drm_gem_object_unreference(obj); |
@@ -4220,18 +4259,23 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, | |||
4220 | struct drm_i915_gem_pin *args = data; | 4259 | struct drm_i915_gem_pin *args = data; |
4221 | struct drm_gem_object *obj; | 4260 | struct drm_gem_object *obj; |
4222 | struct drm_i915_gem_object *obj_priv; | 4261 | struct drm_i915_gem_object *obj_priv; |
4223 | 4262 | int ret; | |
4224 | mutex_lock(&dev->struct_mutex); | ||
4225 | 4263 | ||
4226 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4264 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4227 | if (obj == NULL) { | 4265 | if (obj == NULL) { |
4228 | DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", | 4266 | DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", |
4229 | args->handle); | 4267 | args->handle); |
4230 | mutex_unlock(&dev->struct_mutex); | ||
4231 | return -ENOENT; | 4268 | return -ENOENT; |
4232 | } | 4269 | } |
4233 | 4270 | ||
4234 | obj_priv = to_intel_bo(obj); | 4271 | obj_priv = to_intel_bo(obj); |
4272 | |||
4273 | ret = i915_mutex_lock_interruptible(dev); | ||
4274 | if (ret) { | ||
4275 | drm_gem_object_unreference_unlocked(obj); | ||
4276 | return ret; | ||
4277 | } | ||
4278 | |||
4235 | if (obj_priv->pin_filp != file_priv) { | 4279 | if (obj_priv->pin_filp != file_priv) { |
4236 | DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", | 4280 | DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", |
4237 | args->handle); | 4281 | args->handle); |
@@ -4254,16 +4298,11 @@ int | |||
4254 | i915_gem_busy_ioctl(struct drm_device *dev, void *data, | 4298 | i915_gem_busy_ioctl(struct drm_device *dev, void *data, |
4255 | struct drm_file *file_priv) | 4299 | struct drm_file *file_priv) |
4256 | { | 4300 | { |
4257 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
4258 | struct drm_i915_gem_busy *args = data; | 4301 | struct drm_i915_gem_busy *args = data; |
4259 | struct drm_gem_object *obj; | 4302 | struct drm_gem_object *obj; |
4260 | struct drm_i915_gem_object *obj_priv; | 4303 | struct drm_i915_gem_object *obj_priv; |
4261 | int ret; | 4304 | int ret; |
4262 | 4305 | ||
4263 | ret = i915_gem_check_is_wedged(dev); | ||
4264 | if (ret) | ||
4265 | return ret; | ||
4266 | |||
4267 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4306 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4268 | if (obj == NULL) { | 4307 | if (obj == NULL) { |
4269 | DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n", | 4308 | DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n", |
@@ -4271,11 +4310,10 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4271 | return -ENOENT; | 4310 | return -ENOENT; |
4272 | } | 4311 | } |
4273 | 4312 | ||
4274 | mutex_lock(&dev->struct_mutex); | 4313 | ret = i915_mutex_lock_interruptible(dev); |
4275 | 4314 | if (ret) { | |
4276 | if (atomic_read(&dev_priv->mm.wedged)) { | 4315 | drm_gem_object_unreference_unlocked(obj); |
4277 | ret = -EAGAIN; | 4316 | return ret; |
4278 | goto unlock; | ||
4279 | } | 4317 | } |
4280 | 4318 | ||
4281 | /* Count all active objects as busy, even if they are currently not used | 4319 | /* Count all active objects as busy, even if they are currently not used |
@@ -4306,10 +4344,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4306 | args->busy = obj_priv->active; | 4344 | args->busy = obj_priv->active; |
4307 | } | 4345 | } |
4308 | 4346 | ||
4309 | unlock: | ||
4310 | drm_gem_object_unreference(obj); | 4347 | drm_gem_object_unreference(obj); |
4311 | mutex_unlock(&dev->struct_mutex); | 4348 | mutex_unlock(&dev->struct_mutex); |
4312 | return ret; | 4349 | return 0; |
4313 | } | 4350 | } |
4314 | 4351 | ||
4315 | int | 4352 | int |
@@ -4326,6 +4363,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4326 | struct drm_i915_gem_madvise *args = data; | 4363 | struct drm_i915_gem_madvise *args = data; |
4327 | struct drm_gem_object *obj; | 4364 | struct drm_gem_object *obj; |
4328 | struct drm_i915_gem_object *obj_priv; | 4365 | struct drm_i915_gem_object *obj_priv; |
4366 | int ret; | ||
4329 | 4367 | ||
4330 | switch (args->madv) { | 4368 | switch (args->madv) { |
4331 | case I915_MADV_DONTNEED: | 4369 | case I915_MADV_DONTNEED: |
@@ -4341,10 +4379,14 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4341 | args->handle); | 4379 | args->handle); |
4342 | return -ENOENT; | 4380 | return -ENOENT; |
4343 | } | 4381 | } |
4344 | |||
4345 | mutex_lock(&dev->struct_mutex); | ||
4346 | obj_priv = to_intel_bo(obj); | 4382 | obj_priv = to_intel_bo(obj); |
4347 | 4383 | ||
4384 | ret = i915_mutex_lock_interruptible(dev); | ||
4385 | if (ret) { | ||
4386 | drm_gem_object_unreference_unlocked(obj); | ||
4387 | return ret; | ||
4388 | } | ||
4389 | |||
4348 | if (obj_priv->pin_count) { | 4390 | if (obj_priv->pin_count) { |
4349 | drm_gem_object_unreference(obj); | 4391 | drm_gem_object_unreference(obj); |
4350 | mutex_unlock(&dev->struct_mutex); | 4392 | mutex_unlock(&dev->struct_mutex); |