[PATCH 5/5] drm: Nerv drm_global_mutex BKL for good drivers
Daniel Vetter
daniel at ffwll.ch
Wed Jan 29 17:07:21 UTC 2020
On Wed, Jan 29, 2020 at 05:47:33PM +0100, Sam Ravnborg wrote:
> Hi Daniel.
>
> In the nit-pick department today - sorry.
>
> Subject: [PATCH 5/5] drm: Nerv drm_global_mutex BKL for good drivers
> I did not understand this subject... - what is "Nerv"?
It's a typo, supposed to be nerf:
https://www.urbandictionary.com/define.php?term=nerf
Cheers, Daniel
>
> Sam
>
> On Wed, Jan 29, 2020 at 09:24:10AM +0100, Daniel Vetter wrote:
> > This catches the majority of drivers (unfortunately not if we take
> > users into account, because all the big drivers have at least a
> > lastclose hook).
> >
> > With the prep patches out of the way all drm state is fully protected
> > and either prevents or can deal with the races from dropping the BKL
> > around open/close. The only thing left to audit are the various driver
> > hooks - by keeping the BKL around if any of them are set we have a
> > very simple cop-out!
> >
> > Note that one of the biggest prep pieces to get here was making
> > dev->open_count atomic, which was done in
> >
> > commit 7e13ad896484a0165a68197a2e64091ea28c9602
> > Author: Chris Wilson <chris at chris-wilson.co.uk>
> > Date: Fri Jan 24 13:01:07 2020 +0000
> >
> > drm: Avoid drm_global_mutex for simple inc/dec of dev->open_count
> >
> > Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
> > Cc: Chris Wilson <chris at chris-wilson.co.uk>
> > Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
> > ---
> > drivers/gpu/drm/drm_drv.c | 6 +++--
> > drivers/gpu/drm/drm_file.c | 46 ++++++++++++++++++++++++++++++----
> > drivers/gpu/drm/drm_internal.h | 1 +
> > 3 files changed, 46 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> > index 05bdf0b9d2b3..9fcd6ab3c154 100644
> > --- a/drivers/gpu/drm/drm_drv.c
> > +++ b/drivers/gpu/drm/drm_drv.c
> > @@ -946,7 +946,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
> > struct drm_driver *driver = dev->driver;
> > int ret;
> >
> > - mutex_lock(&drm_global_mutex);
> > + if (drm_dev_needs_global_mutex(dev))
> > + mutex_lock(&drm_global_mutex);
> >
> > if (dev->driver->load) {
> > if (!drm_core_check_feature(dev, DRIVER_LEGACY))
> > @@ -992,7 +993,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
> > drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
> > drm_minor_unregister(dev, DRM_MINOR_RENDER);
> > out_unlock:
> > - mutex_unlock(&drm_global_mutex);
> > + if (drm_dev_needs_global_mutex(dev))
> > + mutex_unlock(&drm_global_mutex);
> > return ret;
> > }
> > EXPORT_SYMBOL(drm_dev_register);
> > diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
> > index d36cb74ebe0c..efd6fe0b6b4f 100644
> > --- a/drivers/gpu/drm/drm_file.c
> > +++ b/drivers/gpu/drm/drm_file.c
> > @@ -51,6 +51,37 @@
> > /* from BKL pushdown */
> > DEFINE_MUTEX(drm_global_mutex);
> >
> > +bool drm_dev_needs_global_mutex(struct drm_device *dev)
> > +{
> > + /*
> > + * Legacy drivers rely on all kinds of BKL locking semantics, don't
> > + * bother. They also still need BKL locking for their ioctls, so better
> > + * safe than sorry.
> > + */
> > + if (drm_core_check_feature(dev, DRIVER_LEGACY))
> > + return true;
> > +
> > + /*
> > + * The deprecated ->load callback must be called after the driver is
> > + * already registered. This means such drivers rely on the BKL to make
> > + * sure an open can't proceed until the driver is actually fully set up.
> > + * Similar hilarity holds for the unload callback.
> > + */
> > + if (dev->driver->load || dev->driver->unload)
> > + return true;
> > +
> > + /*
> > + * Drivers with the lastclose callback assume that it's synchronized
> > + * against concurrent opens, which again needs the BKL. The proper fix
> > + * is to use the drm_client infrastructure with proper locking for each
> > + * client.
> > + */
> > + if (dev->driver->lastclose)
> > + return true;
> > +
> > + return false;
> > +}
> > +
> > /**
> > * DOC: file operations
> > *
> > @@ -378,9 +409,10 @@ int drm_open(struct inode *inode, struct file *filp)
> > if (IS_ERR(minor))
> > return PTR_ERR(minor);
> >
> > - mutex_unlock(&drm_global_mutex);
> > -
> > dev = minor->dev;
> > + if (drm_dev_needs_global_mutex(dev))
> > + mutex_unlock(&drm_global_mutex);
> > +
> > if (!atomic_fetch_inc(&dev->open_count))
> > need_setup = 1;
> >
> > @@ -398,13 +430,15 @@ int drm_open(struct inode *inode, struct file *filp)
> > }
> > }
> >
> > - mutex_unlock(&drm_global_mutex);
> > + if (drm_dev_needs_global_mutex(dev))
> > + mutex_unlock(&drm_global_mutex);
> >
> > return 0;
> >
> > err_undo:
> > atomic_dec(&dev->open_count);
> > - mutex_unlock(&drm_global_mutex);
> > + if (drm_dev_needs_global_mutex(dev))
> > + mutex_unlock(&drm_global_mutex);
> > drm_minor_release(minor);
> > return retcode;
> > }
> > @@ -444,6 +478,7 @@ int drm_release(struct inode *inode, struct file *filp)
> > struct drm_minor *minor = file_priv->minor;
> > struct drm_device *dev = minor->dev;
> >
> > + if (drm_dev_needs_global_mutex(dev))
> > mutex_lock(&drm_global_mutex);
> >
> > DRM_DEBUG("open_count = %d\n", atomic_read(&dev->open_count));
> > @@ -453,7 +488,8 @@ int drm_release(struct inode *inode, struct file *filp)
> > if (atomic_dec_and_test(&dev->open_count))
> > drm_lastclose(dev);
> >
> > - mutex_unlock(&drm_global_mutex);
> > + if (drm_dev_needs_global_mutex(dev))
> > + mutex_unlock(&drm_global_mutex);
> >
> > drm_minor_release(minor);
> >
> > diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
> > index 6937bf923f05..aeec2e68d772 100644
> > --- a/drivers/gpu/drm/drm_internal.h
> > +++ b/drivers/gpu/drm/drm_internal.h
> > @@ -41,6 +41,7 @@ struct drm_printer;
> >
> > /* drm_file.c */
> > extern struct mutex drm_global_mutex;
> > +bool drm_dev_needs_global_mutex(struct drm_device *dev);
> > struct drm_file *drm_file_alloc(struct drm_minor *minor);
> > void drm_file_free(struct drm_file *file);
> > void drm_lastclose(struct drm_device *dev);
> > --
> > 2.24.1
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list