lkml.org 
[lkml]   [2022]   [Sep]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 3/4] drm: Use mutex for minors
    Date
    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@intel.com>
    Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.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
    \
     
     \ /
      Last update: 2022-09-06 16:50    [W:2.797 / U:1.512 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site