[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20220906140117.409852-4-michal.winiarski@intel.com>
Date: Tue, 6 Sep 2022 16:01:16 +0200
From: Michał Winiarski <michal.winiarski@...el.com>
To: <dri-devel@...ts.freedesktop.org>, <linux-kernel@...r.kernel.org>
CC: David Airlie <airlied@...ux.ie>, Daniel Vetter <daniel@...ll.ch>,
"Maarten Lankhorst" <maarten.lankhorst@...ux.intel.com>,
Maxime Ripard <mripard@...nel.org>,
Thomas Zimmermann <tzimmermann@...e.de>,
Simon Ser <contact@...rsion.fr>,
Matthew Wilcox <willy@...radead.org>,
Michał Winiarski <michal.winiarski@...el.com>,
"Daniel Vetter" <daniel.vetter@...ll.ch>
Subject: [PATCH v3 3/4] drm: Use mutex for minors
Operating on drm minor is not done in IRQ context, which means that we
could safely downgrade to regular non-irq spinlock.
But we can also go further and drop the idr_preload tricks by just using
a mutex.
Signed-off-by: Michał Winiarski <michal.winiarski@...el.com>
Reviewed-by: Daniel Vetter <daniel.vetter@...ll.ch>
---
drivers/gpu/drm/drm_drv.c | 33 +++++++++++++--------------------
1 file changed, 13 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 0bdcca0db611..f66904527256 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -53,7 +53,7 @@ MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl");
MODULE_DESCRIPTION("DRM shared core routines");
MODULE_LICENSE("GPL and additional rights");
-static DEFINE_SPINLOCK(drm_minor_lock);
+static DEFINE_MUTEX(drm_minor_lock);
static struct idr drm_minors_idr;
static bool skip_legacy_minors;
@@ -103,21 +103,19 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
static void drm_minor_alloc_release(struct drm_device *dev, void *data)
{
struct drm_minor *minor = data;
- unsigned long flags;
WARN_ON(dev != minor->dev);
put_device(minor->kdev);
- spin_lock_irqsave(&drm_minor_lock, flags);
+ mutex_lock(&drm_minor_lock);
idr_remove(&drm_minors_idr, minor->index);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
+ mutex_unlock(&drm_minor_lock);
}
static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
{
struct drm_minor *minor;
- unsigned long flags;
int r = -ENOSPC;
minor = drmm_kzalloc(dev, sizeof(*minor), GFP_KERNEL);
@@ -133,18 +131,16 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
* and 128-191 are render nodes.
* After reaching the limit, we're allocating minors dynamically - first-come, first-serve.
*/
- idr_preload(GFP_KERNEL);
- spin_lock_irqsave(&drm_minor_lock, flags);
+ mutex_lock(&drm_minor_lock);
if (!skip_legacy_minors)
r = idr_alloc(&drm_minors_idr,
NULL,
64 * type,
64 * (type + 1),
- GFP_NOWAIT);
+ GFP_KERNEL);
if (r == -ENOSPC)
- r = idr_alloc(&drm_minors_idr, NULL, 192, 1 << MINORBITS, GFP_NOWAIT);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
- idr_preload_end();
+ r = idr_alloc(&drm_minors_idr, NULL, 192, 1 << MINORBITS, GFP_KERNEL);
+ mutex_unlock(&drm_minor_lock);
if (r < 0)
return r;
@@ -166,7 +162,6 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
static int drm_minor_register(struct drm_device *dev, unsigned int type)
{
struct drm_minor *minor;
- unsigned long flags;
int ret;
DRM_DEBUG("\n");
@@ -186,9 +181,9 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
goto err_debugfs;
/* replace NULL with @minor so lookups will succeed from now on */
- spin_lock_irqsave(&drm_minor_lock, flags);
+ mutex_lock(&drm_minor_lock);
idr_replace(&drm_minors_idr, minor, minor->index);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
+ mutex_unlock(&drm_minor_lock);
DRM_DEBUG("new minor registered %d\n", minor->index);
return 0;
@@ -201,16 +196,15 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
{
struct drm_minor *minor;
- unsigned long flags;
minor = *drm_minor_get_slot(dev, type);
if (!minor || !device_is_registered(minor->kdev))
return;
/* replace @minor with NULL so lookups will fail from now on */
- spin_lock_irqsave(&drm_minor_lock, flags);
+ mutex_lock(&drm_minor_lock);
idr_replace(&drm_minors_idr, NULL, minor->index);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
+ mutex_unlock(&drm_minor_lock);
device_del(minor->kdev);
dev_set_drvdata(minor->kdev, NULL); /* safety belt */
@@ -229,13 +223,12 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
struct drm_minor *drm_minor_acquire(unsigned int minor_id)
{
struct drm_minor *minor;
- unsigned long flags;
- spin_lock_irqsave(&drm_minor_lock, flags);
+ mutex_lock(&drm_minor_lock);
minor = idr_find(&drm_minors_idr, minor_id);
if (minor)
drm_dev_get(minor->dev);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
+ mutex_unlock(&drm_minor_lock);
if (!minor) {
return ERR_PTR(-ENODEV);
--
2.37.3
Powered by blists - more mailing lists