aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-10-17 04:45:41 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-19 04:20:23 -0400
commit1d7cfea152cae6159aa30ceae38c3eaf13ea083c (patch)
treef9d8b2536555c3a5af75d461f16d7374af988cf8 /drivers/gpu/drm/i915/i915_gem.c
parent139d363bcf2d995a72694ddd2b8665af6cb7fb54 (diff)
drm/i915: Do interrupible mutex lock first to avoid locking for unreference
One of the primarily consumers of the i915 driver is X, a large signal driven application. Frequently when writing into the buffers, there is a pending signal which causes us not to take the interruptible lock but then we need to take that same lock around the object unreference. By rearranging the code to do the interruptible lock as the first check, we can avoid the frequent additional locking around the unreference. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c206
1 files changed, 93 insertions, 113 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index efc6a4e3b1d2..34a07fc20513 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -547,16 +547,16 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
547 struct drm_i915_gem_object *obj_priv; 547 struct drm_i915_gem_object *obj_priv;
548 int ret = 0; 548 int ret = 0;
549 549
550 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
551 if (obj == NULL)
552 return -ENOENT;
553 obj_priv = to_intel_bo(obj);
554
555 ret = i915_mutex_lock_interruptible(dev); 550 ret = i915_mutex_lock_interruptible(dev);
556 if (ret) { 551 if (ret)
557 drm_gem_object_unreference_unlocked(obj);
558 return ret; 552 return ret;
553
554 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
555 if (obj == NULL) {
556 ret = -ENOENT;
557 goto unlock;
559 } 558 }
559 obj_priv = to_intel_bo(obj);
560 560
561 /* Bounds check source. */ 561 /* Bounds check source. */
562 if (args->offset > obj->size || args->size > obj->size - args->offset) { 562 if (args->offset > obj->size || args->size > obj->size - args->offset) {
@@ -601,6 +601,7 @@ out_put:
601 i915_gem_object_put_pages(obj); 601 i915_gem_object_put_pages(obj);
602out: 602out:
603 drm_gem_object_unreference(obj); 603 drm_gem_object_unreference(obj);
604unlock:
604 mutex_unlock(&dev->struct_mutex); 605 mutex_unlock(&dev->struct_mutex);
605 return ret; 606 return ret;
606} 607}
@@ -982,16 +983,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
982 struct drm_i915_gem_object *obj_priv; 983 struct drm_i915_gem_object *obj_priv;
983 int ret = 0; 984 int ret = 0;
984 985
985 obj = drm_gem_object_lookup(dev, file, args->handle);
986 if (obj == NULL)
987 return -ENOENT;
988 obj_priv = to_intel_bo(obj);
989
990 ret = i915_mutex_lock_interruptible(dev); 986 ret = i915_mutex_lock_interruptible(dev);
991 if (ret) { 987 if (ret)
992 drm_gem_object_unreference_unlocked(obj);
993 return ret; 988 return ret;
989
990 obj = drm_gem_object_lookup(dev, file, args->handle);
991 if (obj == NULL) {
992 ret = -ENOENT;
993 goto unlock;
994 } 994 }
995 obj_priv = to_intel_bo(obj);
996
995 997
996 /* Bounds check destination. */ 998 /* Bounds check destination. */
997 if (args->offset > obj->size || args->size > obj->size - args->offset) { 999 if (args->offset > obj->size || args->size > obj->size - args->offset) {
@@ -1062,6 +1064,7 @@ out_put:
1062 1064
1063out: 1065out:
1064 drm_gem_object_unreference(obj); 1066 drm_gem_object_unreference(obj);
1067unlock:
1065 mutex_unlock(&dev->struct_mutex); 1068 mutex_unlock(&dev->struct_mutex);
1066 return ret; 1069 return ret;
1067} 1070}
@@ -1098,16 +1101,16 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
1098 if (write_domain != 0 && read_domains != write_domain) 1101 if (write_domain != 0 && read_domains != write_domain)
1099 return -EINVAL; 1102 return -EINVAL;
1100 1103
1101 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
1102 if (obj == NULL)
1103 return -ENOENT;
1104 obj_priv = to_intel_bo(obj);
1105
1106 ret = i915_mutex_lock_interruptible(dev); 1104 ret = i915_mutex_lock_interruptible(dev);
1107 if (ret) { 1105 if (ret)
1108 drm_gem_object_unreference_unlocked(obj);
1109 return ret; 1106 return ret;
1107
1108 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
1109 if (obj == NULL) {
1110 ret = -ENOENT;
1111 goto unlock;
1110 } 1112 }
1113 obj_priv = to_intel_bo(obj);
1111 1114
1112 intel_mark_busy(dev, obj); 1115 intel_mark_busy(dev, obj);
1113 1116
@@ -1139,6 +1142,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
1139 list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); 1142 list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
1140 1143
1141 drm_gem_object_unreference(obj); 1144 drm_gem_object_unreference(obj);
1145unlock:
1142 mutex_unlock(&dev->struct_mutex); 1146 mutex_unlock(&dev->struct_mutex);
1143 return ret; 1147 return ret;
1144} 1148}
@@ -1157,14 +1161,14 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
1157 if (!(dev->driver->driver_features & DRIVER_GEM)) 1161 if (!(dev->driver->driver_features & DRIVER_GEM))
1158 return -ENODEV; 1162 return -ENODEV;
1159 1163
1160 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
1161 if (obj == NULL)
1162 return -ENOENT;
1163
1164 ret = i915_mutex_lock_interruptible(dev); 1164 ret = i915_mutex_lock_interruptible(dev);
1165 if (ret) { 1165 if (ret)
1166 drm_gem_object_unreference_unlocked(obj);
1167 return ret; 1166 return ret;
1167
1168 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
1169 if (obj == NULL) {
1170 ret = -ENOENT;
1171 goto unlock;
1168 } 1172 }
1169 1173
1170 /* Pinned buffers may be scanout, so flush the cache */ 1174 /* Pinned buffers may be scanout, so flush the cache */
@@ -1172,6 +1176,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
1172 i915_gem_object_flush_cpu_write_domain(obj); 1176 i915_gem_object_flush_cpu_write_domain(obj);
1173 1177
1174 drm_gem_object_unreference(obj); 1178 drm_gem_object_unreference(obj);
1179unlock:
1175 mutex_unlock(&dev->struct_mutex); 1180 mutex_unlock(&dev->struct_mutex);
1176 return ret; 1181 return ret;
1177} 1182}
@@ -1469,33 +1474,27 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
1469 if (!(dev->driver->driver_features & DRIVER_GEM)) 1474 if (!(dev->driver->driver_features & DRIVER_GEM))
1470 return -ENODEV; 1475 return -ENODEV;
1471 1476
1472 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
1473 if (obj == NULL)
1474 return -ENOENT;
1475
1476 ret = i915_mutex_lock_interruptible(dev); 1477 ret = i915_mutex_lock_interruptible(dev);
1477 if (ret) { 1478 if (ret)
1478 drm_gem_object_unreference_unlocked(obj);
1479 return ret; 1479 return ret;
1480 }
1481 1480
1481 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
1482 if (obj == NULL) {
1483 ret = -ENOENT;
1484 goto unlock;
1485 }
1482 obj_priv = to_intel_bo(obj); 1486 obj_priv = to_intel_bo(obj);
1483 1487
1484 if (obj_priv->madv != I915_MADV_WILLNEED) { 1488 if (obj_priv->madv != I915_MADV_WILLNEED) {
1485 DRM_ERROR("Attempting to mmap a purgeable buffer\n"); 1489 DRM_ERROR("Attempting to mmap a purgeable buffer\n");
1486 drm_gem_object_unreference(obj); 1490 ret = -EINVAL;
1487 mutex_unlock(&dev->struct_mutex); 1491 goto out;
1488 return -EINVAL;
1489 } 1492 }
1490 1493
1491
1492 if (!obj_priv->mmap_offset) { 1494 if (!obj_priv->mmap_offset) {
1493 ret = i915_gem_create_mmap_offset(obj); 1495 ret = i915_gem_create_mmap_offset(obj);
1494 if (ret) { 1496 if (ret)
1495 drm_gem_object_unreference(obj); 1497 goto out;
1496 mutex_unlock(&dev->struct_mutex);
1497 return ret;
1498 }
1499 } 1498 }
1500 1499
1501 args->offset = obj_priv->mmap_offset; 1500 args->offset = obj_priv->mmap_offset;
@@ -1506,17 +1505,15 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
1506 */ 1505 */
1507 if (!obj_priv->agp_mem) { 1506 if (!obj_priv->agp_mem) {
1508 ret = i915_gem_object_bind_to_gtt(obj, 0); 1507 ret = i915_gem_object_bind_to_gtt(obj, 0);
1509 if (ret) { 1508 if (ret)
1510 drm_gem_object_unreference(obj); 1509 goto out;
1511 mutex_unlock(&dev->struct_mutex);
1512 return ret;
1513 }
1514 } 1510 }
1515 1511
1512out:
1516 drm_gem_object_unreference(obj); 1513 drm_gem_object_unreference(obj);
1514unlock:
1517 mutex_unlock(&dev->struct_mutex); 1515 mutex_unlock(&dev->struct_mutex);
1518 1516 return ret;
1519 return 0;
1520} 1517}
1521 1518
1522static void 1519static void
@@ -4100,44 +4097,36 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
4100 struct drm_i915_gem_object *obj_priv; 4097 struct drm_i915_gem_object *obj_priv;
4101 int ret; 4098 int ret;
4102 4099
4100 ret = i915_mutex_lock_interruptible(dev);
4101 if (ret)
4102 return ret;
4103
4103 obj = drm_gem_object_lookup(dev, file_priv, args->handle); 4104 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
4104 if (obj == NULL) { 4105 if (obj == NULL) {
4105 DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", 4106 ret = -ENOENT;
4106 args->handle); 4107 goto unlock;
4107 return -ENOENT;
4108 } 4108 }
4109 obj_priv = to_intel_bo(obj); 4109 obj_priv = to_intel_bo(obj);
4110 4110
4111 ret = i915_mutex_lock_interruptible(dev);
4112 if (ret) {
4113 drm_gem_object_unreference_unlocked(obj);
4114 return ret;
4115 }
4116
4117 if (obj_priv->madv != I915_MADV_WILLNEED) { 4111 if (obj_priv->madv != I915_MADV_WILLNEED) {
4118 DRM_ERROR("Attempting to pin a purgeable buffer\n"); 4112 DRM_ERROR("Attempting to pin a purgeable buffer\n");
4119 drm_gem_object_unreference(obj); 4113 ret = -EINVAL;
4120 mutex_unlock(&dev->struct_mutex); 4114 goto out;
4121 return -EINVAL;
4122 } 4115 }
4123 4116
4124 if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { 4117 if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
4125 DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", 4118 DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
4126 args->handle); 4119 args->handle);
4127 drm_gem_object_unreference(obj); 4120 ret = -EINVAL;
4128 mutex_unlock(&dev->struct_mutex); 4121 goto out;
4129 return -EINVAL;
4130 } 4122 }
4131 4123
4132 obj_priv->user_pin_count++; 4124 obj_priv->user_pin_count++;
4133 obj_priv->pin_filp = file_priv; 4125 obj_priv->pin_filp = file_priv;
4134 if (obj_priv->user_pin_count == 1) { 4126 if (obj_priv->user_pin_count == 1) {
4135 ret = i915_gem_object_pin(obj, args->alignment); 4127 ret = i915_gem_object_pin(obj, args->alignment);
4136 if (ret != 0) { 4128 if (ret)
4137 drm_gem_object_unreference(obj); 4129 goto out;
4138 mutex_unlock(&dev->struct_mutex);
4139 return ret;
4140 }
4141 } 4130 }
4142 4131
4143 /* XXX - flush the CPU caches for pinned objects 4132 /* XXX - flush the CPU caches for pinned objects
@@ -4145,10 +4134,11 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
4145 */ 4134 */
4146 i915_gem_object_flush_cpu_write_domain(obj); 4135 i915_gem_object_flush_cpu_write_domain(obj);
4147 args->offset = obj_priv->gtt_offset; 4136 args->offset = obj_priv->gtt_offset;
4137out:
4148 drm_gem_object_unreference(obj); 4138 drm_gem_object_unreference(obj);
4139unlock:
4149 mutex_unlock(&dev->struct_mutex); 4140 mutex_unlock(&dev->struct_mutex);
4150 4141 return ret;
4151 return 0;
4152} 4142}
4153 4143
4154int 4144int
@@ -4160,27 +4150,22 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
4160 struct drm_i915_gem_object *obj_priv; 4150 struct drm_i915_gem_object *obj_priv;
4161 int ret; 4151 int ret;
4162 4152
4153 ret = i915_mutex_lock_interruptible(dev);
4154 if (ret)
4155 return ret;
4156
4163 obj = drm_gem_object_lookup(dev, file_priv, args->handle); 4157 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
4164 if (obj == NULL) { 4158 if (obj == NULL) {
4165 DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", 4159 ret = -ENOENT;
4166 args->handle); 4160 goto unlock;
4167 return -ENOENT;
4168 } 4161 }
4169
4170 obj_priv = to_intel_bo(obj); 4162 obj_priv = to_intel_bo(obj);
4171 4163
4172 ret = i915_mutex_lock_interruptible(dev);
4173 if (ret) {
4174 drm_gem_object_unreference_unlocked(obj);
4175 return ret;
4176 }
4177
4178 if (obj_priv->pin_filp != file_priv) { 4164 if (obj_priv->pin_filp != file_priv) {
4179 DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", 4165 DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
4180 args->handle); 4166 args->handle);
4181 drm_gem_object_unreference(obj); 4167 ret = -EINVAL;
4182 mutex_unlock(&dev->struct_mutex); 4168 goto out;
4183 return -EINVAL;
4184 } 4169 }
4185 obj_priv->user_pin_count--; 4170 obj_priv->user_pin_count--;
4186 if (obj_priv->user_pin_count == 0) { 4171 if (obj_priv->user_pin_count == 0) {
@@ -4188,9 +4173,11 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
4188 i915_gem_object_unpin(obj); 4173 i915_gem_object_unpin(obj);
4189 } 4174 }
4190 4175
4176out:
4191 drm_gem_object_unreference(obj); 4177 drm_gem_object_unreference(obj);
4178unlock:
4192 mutex_unlock(&dev->struct_mutex); 4179 mutex_unlock(&dev->struct_mutex);
4193 return 0; 4180 return ret;
4194} 4181}
4195 4182
4196int 4183int
@@ -4202,25 +4189,22 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
4202 struct drm_i915_gem_object *obj_priv; 4189 struct drm_i915_gem_object *obj_priv;
4203 int ret; 4190 int ret;
4204 4191
4205 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
4206 if (obj == NULL) {
4207 DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n",
4208 args->handle);
4209 return -ENOENT;
4210 }
4211
4212 ret = i915_mutex_lock_interruptible(dev); 4192 ret = i915_mutex_lock_interruptible(dev);
4213 if (ret) { 4193 if (ret)
4214 drm_gem_object_unreference_unlocked(obj);
4215 return ret; 4194 return ret;
4195
4196 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
4197 if (obj == NULL) {
4198 ret = -ENOENT;
4199 goto unlock;
4216 } 4200 }
4201 obj_priv = to_intel_bo(obj);
4217 4202
4218 /* Count all active objects as busy, even if they are currently not used 4203 /* Count all active objects as busy, even if they are currently not used
4219 * by the gpu. Users of this interface expect objects to eventually 4204 * by the gpu. Users of this interface expect objects to eventually
4220 * become non-busy without any further actions, therefore emit any 4205 * become non-busy without any further actions, therefore emit any
4221 * necessary flushes here. 4206 * necessary flushes here.
4222 */ 4207 */
4223 obj_priv = to_intel_bo(obj);
4224 args->busy = obj_priv->active; 4208 args->busy = obj_priv->active;
4225 if (args->busy) { 4209 if (args->busy) {
4226 /* Unconditionally flush objects, even when the gpu still uses this 4210 /* Unconditionally flush objects, even when the gpu still uses this
@@ -4244,8 +4228,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
4244 } 4228 }
4245 4229
4246 drm_gem_object_unreference(obj); 4230 drm_gem_object_unreference(obj);
4231unlock:
4247 mutex_unlock(&dev->struct_mutex); 4232 mutex_unlock(&dev->struct_mutex);
4248 return 0; 4233 return ret;
4249} 4234}
4250 4235
4251int 4236int
@@ -4272,26 +4257,20 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
4272 return -EINVAL; 4257 return -EINVAL;
4273 } 4258 }
4274 4259
4260 ret = i915_mutex_lock_interruptible(dev);
4261 if (ret)
4262 return ret;
4263
4275 obj = drm_gem_object_lookup(dev, file_priv, args->handle); 4264 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
4276 if (obj == NULL) { 4265 if (obj == NULL) {
4277 DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n", 4266 ret = -ENOENT;
4278 args->handle); 4267 goto unlock;
4279 return -ENOENT;
4280 } 4268 }
4281 obj_priv = to_intel_bo(obj); 4269 obj_priv = to_intel_bo(obj);
4282 4270
4283 ret = i915_mutex_lock_interruptible(dev);
4284 if (ret) {
4285 drm_gem_object_unreference_unlocked(obj);
4286 return ret;
4287 }
4288
4289 if (obj_priv->pin_count) { 4271 if (obj_priv->pin_count) {
4290 drm_gem_object_unreference(obj); 4272 ret = -EINVAL;
4291 mutex_unlock(&dev->struct_mutex); 4273 goto out;
4292
4293 DRM_ERROR("Attempted i915_gem_madvise_ioctl() on a pinned object\n");
4294 return -EINVAL;
4295 } 4274 }
4296 4275
4297 if (obj_priv->madv != __I915_MADV_PURGED) 4276 if (obj_priv->madv != __I915_MADV_PURGED)
@@ -4304,10 +4283,11 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
4304 4283
4305 args->retained = obj_priv->madv != __I915_MADV_PURGED; 4284 args->retained = obj_priv->madv != __I915_MADV_PURGED;
4306 4285
4286out:
4307 drm_gem_object_unreference(obj); 4287 drm_gem_object_unreference(obj);
4288unlock:
4308 mutex_unlock(&dev->struct_mutex); 4289 mutex_unlock(&dev->struct_mutex);
4309 4290 return ret;
4310 return 0;
4311} 4291}
4312 4292
4313struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, 4293struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev,