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); |
