summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_file.c')
-rw-r--r--drivers/gpu/drm/drm_file.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index 92d16724f949..e25306c49cc6 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);
+ READ_ONCE(dev->open_count));
if (drm_core_check_feature(dev, DRIVER_LEGACY) &&
dev->driver->preclose)
@@ -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);
+
+ mutex_lock(&drm_global_mutex);
+ if (!--dev->open_count)
+ 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