diff options
Diffstat (limited to 'drivers/gpu/drm/drm_gem.c')
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 109 |
1 files changed, 57 insertions, 52 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 2e10bba4468b..2e8c77e71e1f 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -220,6 +220,9 @@ static void drm_gem_object_exported_dma_buf_free(struct drm_gem_object *obj) | |||
220 | static void | 220 | static void |
221 | drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) | 221 | drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) |
222 | { | 222 | { |
223 | struct drm_device *dev = obj->dev; | ||
224 | bool final = false; | ||
225 | |||
223 | if (WARN_ON(obj->handle_count == 0)) | 226 | if (WARN_ON(obj->handle_count == 0)) |
224 | return; | 227 | return; |
225 | 228 | ||
@@ -229,14 +232,39 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) | |||
229 | * checked for a name | 232 | * checked for a name |
230 | */ | 233 | */ |
231 | 234 | ||
232 | mutex_lock(&obj->dev->object_name_lock); | 235 | mutex_lock(&dev->object_name_lock); |
233 | if (--obj->handle_count == 0) { | 236 | if (--obj->handle_count == 0) { |
234 | drm_gem_object_handle_free(obj); | 237 | drm_gem_object_handle_free(obj); |
235 | drm_gem_object_exported_dma_buf_free(obj); | 238 | drm_gem_object_exported_dma_buf_free(obj); |
239 | final = true; | ||
236 | } | 240 | } |
237 | mutex_unlock(&obj->dev->object_name_lock); | 241 | mutex_unlock(&dev->object_name_lock); |
238 | 242 | ||
239 | drm_gem_object_unreference_unlocked(obj); | 243 | if (final) |
244 | drm_gem_object_unreference_unlocked(obj); | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Called at device or object close to release the file's | ||
249 | * handle references on objects. | ||
250 | */ | ||
251 | static int | ||
252 | drm_gem_object_release_handle(int id, void *ptr, void *data) | ||
253 | { | ||
254 | struct drm_file *file_priv = data; | ||
255 | struct drm_gem_object *obj = ptr; | ||
256 | struct drm_device *dev = obj->dev; | ||
257 | |||
258 | if (drm_core_check_feature(dev, DRIVER_PRIME)) | ||
259 | drm_gem_remove_prime_handles(obj, file_priv); | ||
260 | drm_vma_node_revoke(&obj->vma_node, file_priv->filp); | ||
261 | |||
262 | if (dev->driver->gem_close_object) | ||
263 | dev->driver->gem_close_object(obj, file_priv); | ||
264 | |||
265 | drm_gem_object_handle_unreference_unlocked(obj); | ||
266 | |||
267 | return 0; | ||
240 | } | 268 | } |
241 | 269 | ||
242 | /** | 270 | /** |
@@ -277,14 +305,7 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle) | |||
277 | idr_remove(&filp->object_idr, handle); | 305 | idr_remove(&filp->object_idr, handle); |
278 | spin_unlock(&filp->table_lock); | 306 | spin_unlock(&filp->table_lock); |
279 | 307 | ||
280 | if (drm_core_check_feature(dev, DRIVER_PRIME)) | 308 | drm_gem_object_release_handle(handle, obj, filp); |
281 | drm_gem_remove_prime_handles(obj, filp); | ||
282 | drm_vma_node_revoke(&obj->vma_node, filp->filp); | ||
283 | |||
284 | if (dev->driver->gem_close_object) | ||
285 | dev->driver->gem_close_object(obj, filp); | ||
286 | drm_gem_object_handle_unreference_unlocked(obj); | ||
287 | |||
288 | return 0; | 309 | return 0; |
289 | } | 310 | } |
290 | EXPORT_SYMBOL(drm_gem_handle_delete); | 311 | EXPORT_SYMBOL(drm_gem_handle_delete); |
@@ -326,9 +347,12 @@ drm_gem_handle_create_tail(struct drm_file *file_priv, | |||
326 | u32 *handlep) | 347 | u32 *handlep) |
327 | { | 348 | { |
328 | struct drm_device *dev = obj->dev; | 349 | struct drm_device *dev = obj->dev; |
350 | u32 handle; | ||
329 | int ret; | 351 | int ret; |
330 | 352 | ||
331 | WARN_ON(!mutex_is_locked(&dev->object_name_lock)); | 353 | WARN_ON(!mutex_is_locked(&dev->object_name_lock)); |
354 | if (obj->handle_count++ == 0) | ||
355 | drm_gem_object_reference(obj); | ||
332 | 356 | ||
333 | /* | 357 | /* |
334 | * Get the user-visible handle using idr. Preload and perform | 358 | * Get the user-visible handle using idr. Preload and perform |
@@ -338,32 +362,38 @@ drm_gem_handle_create_tail(struct drm_file *file_priv, | |||
338 | spin_lock(&file_priv->table_lock); | 362 | spin_lock(&file_priv->table_lock); |
339 | 363 | ||
340 | ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT); | 364 | ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT); |
341 | drm_gem_object_reference(obj); | 365 | |
342 | obj->handle_count++; | ||
343 | spin_unlock(&file_priv->table_lock); | 366 | spin_unlock(&file_priv->table_lock); |
344 | idr_preload_end(); | 367 | idr_preload_end(); |
368 | |||
345 | mutex_unlock(&dev->object_name_lock); | 369 | mutex_unlock(&dev->object_name_lock); |
346 | if (ret < 0) { | 370 | if (ret < 0) |
347 | drm_gem_object_handle_unreference_unlocked(obj); | 371 | goto err_unref; |
348 | return ret; | 372 | |
349 | } | 373 | handle = ret; |
350 | *handlep = ret; | ||
351 | 374 | ||
352 | ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp); | 375 | ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp); |
353 | if (ret) { | 376 | if (ret) |
354 | drm_gem_handle_delete(file_priv, *handlep); | 377 | goto err_remove; |
355 | return ret; | ||
356 | } | ||
357 | 378 | ||
358 | if (dev->driver->gem_open_object) { | 379 | if (dev->driver->gem_open_object) { |
359 | ret = dev->driver->gem_open_object(obj, file_priv); | 380 | ret = dev->driver->gem_open_object(obj, file_priv); |
360 | if (ret) { | 381 | if (ret) |
361 | drm_gem_handle_delete(file_priv, *handlep); | 382 | goto err_revoke; |
362 | return ret; | ||
363 | } | ||
364 | } | 383 | } |
365 | 384 | ||
385 | *handlep = handle; | ||
366 | return 0; | 386 | return 0; |
387 | |||
388 | err_revoke: | ||
389 | drm_vma_node_revoke(&obj->vma_node, file_priv->filp); | ||
390 | err_remove: | ||
391 | spin_lock(&file_priv->table_lock); | ||
392 | idr_remove(&file_priv->object_idr, handle); | ||
393 | spin_unlock(&file_priv->table_lock); | ||
394 | err_unref: | ||
395 | drm_gem_object_handle_unreference_unlocked(obj); | ||
396 | return ret; | ||
367 | } | 397 | } |
368 | 398 | ||
369 | /** | 399 | /** |
@@ -630,7 +660,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, | |||
630 | return -ENOENT; | 660 | return -ENOENT; |
631 | 661 | ||
632 | mutex_lock(&dev->object_name_lock); | 662 | mutex_lock(&dev->object_name_lock); |
633 | idr_preload(GFP_KERNEL); | ||
634 | /* prevent races with concurrent gem_close. */ | 663 | /* prevent races with concurrent gem_close. */ |
635 | if (obj->handle_count == 0) { | 664 | if (obj->handle_count == 0) { |
636 | ret = -ENOENT; | 665 | ret = -ENOENT; |
@@ -638,7 +667,7 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, | |||
638 | } | 667 | } |
639 | 668 | ||
640 | if (!obj->name) { | 669 | if (!obj->name) { |
641 | ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT); | 670 | ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_KERNEL); |
642 | if (ret < 0) | 671 | if (ret < 0) |
643 | goto err; | 672 | goto err; |
644 | 673 | ||
@@ -649,7 +678,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, | |||
649 | ret = 0; | 678 | ret = 0; |
650 | 679 | ||
651 | err: | 680 | err: |
652 | idr_preload_end(); | ||
653 | mutex_unlock(&dev->object_name_lock); | 681 | mutex_unlock(&dev->object_name_lock); |
654 | drm_gem_object_unreference_unlocked(obj); | 682 | drm_gem_object_unreference_unlocked(obj); |
655 | return ret; | 683 | return ret; |
@@ -714,29 +742,6 @@ drm_gem_open(struct drm_device *dev, struct drm_file *file_private) | |||
714 | spin_lock_init(&file_private->table_lock); | 742 | spin_lock_init(&file_private->table_lock); |
715 | } | 743 | } |
716 | 744 | ||
717 | /* | ||
718 | * Called at device close to release the file's | ||
719 | * handle references on objects. | ||
720 | */ | ||
721 | static int | ||
722 | drm_gem_object_release_handle(int id, void *ptr, void *data) | ||
723 | { | ||
724 | struct drm_file *file_priv = data; | ||
725 | struct drm_gem_object *obj = ptr; | ||
726 | struct drm_device *dev = obj->dev; | ||
727 | |||
728 | if (drm_core_check_feature(dev, DRIVER_PRIME)) | ||
729 | drm_gem_remove_prime_handles(obj, file_priv); | ||
730 | drm_vma_node_revoke(&obj->vma_node, file_priv->filp); | ||
731 | |||
732 | if (dev->driver->gem_close_object) | ||
733 | dev->driver->gem_close_object(obj, file_priv); | ||
734 | |||
735 | drm_gem_object_handle_unreference_unlocked(obj); | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | /** | 745 | /** |
741 | * drm_gem_release - release file-private GEM resources | 746 | * drm_gem_release - release file-private GEM resources |
742 | * @dev: drm_device which is being closed by userspace | 747 | * @dev: drm_device which is being closed by userspace |