X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fdrm_gem.c;h=aa89d4b0b4c44e87e2726c8945895e96280dc7bb;hb=334656f33c43921cf383dfd0220dfd34376bcd98;hp=8bf3770f294e12feb562d046a5de4ed281b9ce45;hpb=f0f20a16983f7d3713ab695e19bd15eca4e7533f;p=karo-tx-linux.git diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 8bf3770f294e..aa89d4b0b4c4 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -192,9 +192,7 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle) idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); - mutex_lock(&dev->struct_mutex); - drm_gem_object_handle_unreference(obj); - mutex_unlock(&dev->struct_mutex); + drm_gem_object_handle_unreference_unlocked(obj); return 0; } @@ -325,9 +323,7 @@ again: } err: - mutex_lock(&dev->struct_mutex); - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); + drm_gem_object_unreference_unlocked(obj); return ret; } @@ -358,9 +354,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data, return -ENOENT; ret = drm_gem_handle_create(file_priv, obj, &handle); - mutex_lock(&dev->struct_mutex); - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); + drm_gem_object_unreference_unlocked(obj); if (ret) return ret; @@ -390,7 +384,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) { struct drm_gem_object *obj = ptr; - drm_gem_object_handle_unreference(obj); + drm_gem_object_handle_unreference_unlocked(obj); return 0; } @@ -403,16 +397,25 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) void drm_gem_release(struct drm_device *dev, struct drm_file *file_private) { - mutex_lock(&dev->struct_mutex); idr_for_each(&file_private->object_idr, &drm_gem_object_release_handle, NULL); idr_destroy(&file_private->object_idr); - mutex_unlock(&dev->struct_mutex); +} + +static void +drm_gem_object_free_common(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + fput(obj->filp); + atomic_dec(&dev->object_count); + atomic_sub(obj->size, &dev->object_memory); + kfree(obj); } /** * Called after the last reference to the object has been lost. + * Must be called holding struct_ mutex * * Frees the object */ @@ -427,13 +430,39 @@ drm_gem_object_free(struct kref *kref) if (dev->driver->gem_free_object != NULL) dev->driver->gem_free_object(obj); - fput(obj->filp); - atomic_dec(&dev->object_count); - atomic_sub(obj->size, &dev->object_memory); - kfree(obj); + drm_gem_object_free_common(obj); } EXPORT_SYMBOL(drm_gem_object_free); +/** + * Called after the last reference to the object has been lost. + * Must be called without holding struct_mutex + * + * Frees the object + */ +void +drm_gem_object_free_unlocked(struct kref *kref) +{ + struct drm_gem_object *obj = (struct drm_gem_object *) kref; + struct drm_device *dev = obj->dev; + + if (dev->driver->gem_free_object_unlocked != NULL) + dev->driver->gem_free_object_unlocked(obj); + else if (dev->driver->gem_free_object != NULL) { + mutex_lock(&dev->struct_mutex); + dev->driver->gem_free_object(obj); + mutex_unlock(&dev->struct_mutex); + } + + drm_gem_object_free_common(obj); +} +EXPORT_SYMBOL(drm_gem_object_free_unlocked); + +static void drm_gem_object_ref_bug(struct kref *list_kref) +{ + BUG(); +} + /** * Called after the last handle to the object has been closed * @@ -458,8 +487,10 @@ drm_gem_object_handle_free(struct kref *kref) /* * The object name held a reference to this object, drop * that now. + * + * This cannot be the last reference, since the handle holds one too. */ - drm_gem_object_unreference(obj); + kref_put(&obj->refcount, drm_gem_object_ref_bug); } else spin_unlock(&dev->object_name_lock); @@ -477,11 +508,8 @@ EXPORT_SYMBOL(drm_gem_vm_open); void drm_gem_vm_close(struct vm_area_struct *vma) { struct drm_gem_object *obj = vma->vm_private_data; - struct drm_device *dev = obj->dev; - mutex_lock(&dev->struct_mutex); - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); + drm_gem_object_unreference_unlocked(obj); } EXPORT_SYMBOL(drm_gem_vm_close);