Commit 7e13ad89 authored by Chris Wilson's avatar Chris Wilson

drm: Avoid drm_global_mutex for simple inc/dec of dev->open_count

Since drm_global_mutex is a true global mutex across devices, we don't
want to acquire it unless absolutely necessary. For maintaining the
device local open_count, we can use atomic operations on the counter
itself, except when making the transition to/from 0. Here, we tackle the
easy portion of delaying acquiring the drm_global_mutex for the final
release by using atomic_dec_and_mutex_lock(), leaving the global
serialisation across the device opens.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Thomas Hellström (VMware) <thomas_os@shipmail.org>
Reviewed-by: default avatarThomas Hellström <thellstrom@vmware.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200124130107.125404-1-chris@chris-wilson.co.uk
parent 7a2c65dd
...@@ -1137,7 +1137,7 @@ static bool amdgpu_switcheroo_can_switch(struct pci_dev *pdev) ...@@ -1137,7 +1137,7 @@ static bool amdgpu_switcheroo_can_switch(struct pci_dev *pdev)
* locking inversion with the driver load path. And the access here is * locking inversion with the driver load path. And the access here is
* completely racy anyway. So don't bother with locking for now. * completely racy anyway. So don't bother with locking for now.
*/ */
return dev->open_count == 0; return atomic_read(&dev->open_count) == 0;
} }
static const struct vga_switcheroo_client_ops amdgpu_switcheroo_ops = { static const struct vga_switcheroo_client_ops amdgpu_switcheroo_ops = {
......
...@@ -220,7 +220,7 @@ void drm_file_free(struct drm_file *file) ...@@ -220,7 +220,7 @@ void drm_file_free(struct drm_file *file)
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
task_pid_nr(current), task_pid_nr(current),
(long)old_encode_dev(file->minor->kdev->devt), (long)old_encode_dev(file->minor->kdev->devt),
READ_ONCE(dev->open_count)); atomic_read(&dev->open_count));
if (drm_core_check_feature(dev, DRIVER_LEGACY) && if (drm_core_check_feature(dev, DRIVER_LEGACY) &&
dev->driver->preclose) dev->driver->preclose)
...@@ -379,7 +379,7 @@ int drm_open(struct inode *inode, struct file *filp) ...@@ -379,7 +379,7 @@ int drm_open(struct inode *inode, struct file *filp)
return PTR_ERR(minor); return PTR_ERR(minor);
dev = minor->dev; dev = minor->dev;
if (!dev->open_count++) if (!atomic_fetch_inc(&dev->open_count))
need_setup = 1; need_setup = 1;
/* share address_space across all char-devs of a single device */ /* share address_space across all char-devs of a single device */
...@@ -398,7 +398,7 @@ int drm_open(struct inode *inode, struct file *filp) ...@@ -398,7 +398,7 @@ int drm_open(struct inode *inode, struct file *filp)
return 0; return 0;
err_undo: err_undo:
dev->open_count--; atomic_dec(&dev->open_count);
drm_minor_release(minor); drm_minor_release(minor);
return retcode; return retcode;
} }
...@@ -440,11 +440,11 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -440,11 +440,11 @@ int drm_release(struct inode *inode, struct file *filp)
mutex_lock(&drm_global_mutex); 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); drm_close_helper(filp);
if (!--dev->open_count) if (atomic_dec_and_test(&dev->open_count))
drm_lastclose(dev); drm_lastclose(dev);
mutex_unlock(&drm_global_mutex); mutex_unlock(&drm_global_mutex);
...@@ -478,10 +478,10 @@ int drm_release_noglobal(struct inode *inode, struct file *filp) ...@@ -478,10 +478,10 @@ int drm_release_noglobal(struct inode *inode, struct file *filp)
drm_close_helper(filp); drm_close_helper(filp);
mutex_lock(&drm_global_mutex); if (atomic_dec_and_mutex_lock(&dev->open_count, &drm_global_mutex)) {
if (!--dev->open_count)
drm_lastclose(dev); drm_lastclose(dev);
mutex_unlock(&drm_global_mutex); mutex_unlock(&drm_global_mutex);
}
drm_minor_release(minor); drm_minor_release(minor);
......
...@@ -43,7 +43,7 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev) ...@@ -43,7 +43,7 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
* locking inversion with the driver load path. And the access here is * locking inversion with the driver load path. And the access here is
* completely racy anyway. So don't bother with locking for now. * completely racy anyway. So don't bother with locking for now.
*/ */
return i915 && i915->drm.open_count == 0; return i915 && atomic_read(&i915->drm.open_count) == 0;
} }
static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
......
...@@ -72,7 +72,7 @@ nouveau_switcheroo_can_switch(struct pci_dev *pdev) ...@@ -72,7 +72,7 @@ nouveau_switcheroo_can_switch(struct pci_dev *pdev)
* locking inversion with the driver load path. And the access here is * locking inversion with the driver load path. And the access here is
* completely racy anyway. So don't bother with locking for now. * completely racy anyway. So don't bother with locking for now.
*/ */
return dev->open_count == 0; return atomic_read(&dev->open_count) == 0;
} }
static const struct vga_switcheroo_client_ops static const struct vga_switcheroo_client_ops
......
...@@ -1263,7 +1263,7 @@ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) ...@@ -1263,7 +1263,7 @@ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
* locking inversion with the driver load path. And the access here is * locking inversion with the driver load path. And the access here is
* completely racy anyway. So don't bother with locking for now. * completely racy anyway. So don't bother with locking for now.
*/ */
return dev->open_count == 0; return atomic_read(&dev->open_count) == 0;
} }
static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = { static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
......
...@@ -144,7 +144,7 @@ struct drm_device { ...@@ -144,7 +144,7 @@ struct drm_device {
* Usage counter for outstanding files open, * Usage counter for outstanding files open,
* protected by drm_global_mutex * protected by drm_global_mutex
*/ */
int open_count; atomic_t open_count;
/** @filelist_mutex: Protects @filelist. */ /** @filelist_mutex: Protects @filelist. */
struct mutex filelist_mutex; struct mutex filelist_mutex;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment