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.winiar...@intel.com>
---
 drivers/gpu/drm/drm_drv.c | 31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 0dab1ef8a98d..b31497e28e6a 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;
 
 /*
@@ -98,21 +98,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, start, end;
 
        minor = drmm_kzalloc(dev, sizeof(*minor), GFP_KERNEL);
@@ -126,11 +124,9 @@ static int drm_minor_alloc(struct drm_device *dev, 
unsigned int type)
        end = 128 * (type + 1);
 
        do {
-               idr_preload(GFP_KERNEL);
-               spin_lock_irqsave(&drm_minor_lock, flags);
-               r = idr_alloc(&drm_minors_idr, NULL, start, end, GFP_NOWAIT);
-               spin_unlock_irqrestore(&drm_minor_lock, flags);
-               idr_preload_end();
+               mutex_lock(&drm_minor_lock);
+               r = idr_alloc(&drm_minors_idr, NULL, start, end, GFP_KERNEL);
+               mutex_unlock(&drm_minor_lock);
 
                start += 256;
                end += 256;
@@ -156,7 +152,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");
@@ -176,9 +171,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;
@@ -191,16 +186,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 */
@@ -219,13 +213,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.2

Reply via email to