diff options
Diffstat (limited to 'drivers/gpu/drm/drm_file.c')
-rw-r--r-- | drivers/gpu/drm/drm_file.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 92d16724f949..1075b3a8b5b1 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -220,7 +220,7 @@ void drm_file_free(struct drm_file *file) DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", task_pid_nr(current), (long)old_encode_dev(file->minor->kdev->devt), - dev->open_count); + atomic_read(&dev->open_count)); if (drm_core_check_feature(dev, DRIVER_LEGACY) && dev->driver->preclose) @@ -379,7 +379,7 @@ int drm_open(struct inode *inode, struct file *filp) return PTR_ERR(minor); dev = minor->dev; - if (!dev->open_count++) + if (!atomic_fetch_inc(&dev->open_count)) need_setup = 1; /* share address_space across all char-devs of a single device */ @@ -398,7 +398,7 @@ int drm_open(struct inode *inode, struct file *filp) return 0; err_undo: - dev->open_count--; + atomic_dec(&dev->open_count); drm_minor_release(minor); return retcode; } @@ -440,11 +440,11 @@ int drm_release(struct inode *inode, struct file *filp) mutex_lock(&drm_global_mutex); - DRM_DEBUG("open_count = %d\n", dev->open_count); + DRM_DEBUG("open_count = %d\n", atomic_read(&dev->open_count)); drm_close_helper(filp); - if (!--dev->open_count) + if (atomic_dec_and_test(&dev->open_count)) drm_lastclose(dev); mutex_unlock(&drm_global_mutex); @@ -456,6 +456,40 @@ int drm_release(struct inode *inode, struct file *filp) EXPORT_SYMBOL(drm_release); /** + * drm_release_noglobal - release method for DRM file + * @inode: device inode + * @filp: file pointer. + * + * This function may be used by drivers as their &file_operations.release + * method. It frees any resources associated with the open file prior to taking + * the drm_global_mutex, which then calls the &drm_driver.postclose driver + * callback. If this is the last open file for the DRM device also proceeds to + * call the &drm_driver.lastclose driver callback. + * + * RETURNS: + * + * Always succeeds and returns 0. + */ +int drm_release_noglobal(struct inode *inode, struct file *filp) +{ + struct drm_file *file_priv = filp->private_data; + struct drm_minor *minor = file_priv->minor; + struct drm_device *dev = minor->dev; + + drm_close_helper(filp); + + if (atomic_dec_and_mutex_lock(&dev->open_count, &drm_global_mutex)) { + drm_lastclose(dev); + mutex_unlock(&drm_global_mutex); + } + + drm_minor_release(minor); + + return 0; +} +EXPORT_SYMBOL(drm_release_noglobal); + +/** * drm_read - read method for DRM file * @filp: file pointer * @buffer: userspace destination pointer for the read |