diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-06-14 20:51:01 +0200 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-06-16 10:17:58 +0200 |
commit | 14d71ebdb5bd97529ff360b240f294559754824f (patch) | |
tree | 35d1fa56fd6c0ecc88ec768c1ca0f63fd4601d76 | |
parent | 2cbae7e63747c917b08a505e44b31ec8b4ee5583 (diff) |
drm: Extract drm_master_relase
Like with drm_master_open protect it with a check for primary_client
to make it clear that this can't happen on render/control nodes.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1465930269-7883-7-git-send-email-daniel.vetter@ffwll.ch
-rw-r--r-- | drivers/gpu/drm/drm_auth.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fops.c | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_internal.h | 1 |
3 files changed, 40 insertions, 33 deletions
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index 9c1e2081cd58..e015a7edb154 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -243,6 +243,43 @@ int drm_master_open(struct drm_file *file_priv) return ret; } +void drm_master_release(struct drm_file *file_priv) +{ + struct drm_device *dev = file_priv->minor->dev; + + mutex_lock(&dev->master_mutex); + if (file_priv->is_master) { + struct drm_master *master = file_priv->master; + + /* + * Since the master is disappearing, so is the + * possibility to lock. + */ + mutex_lock(&dev->struct_mutex); + if (master->lock.hw_lock) { + if (dev->sigdata.lock == master->lock.hw_lock) + dev->sigdata.lock = NULL; + master->lock.hw_lock = NULL; + master->lock.file_priv = NULL; + wake_up_interruptible_all(&master->lock.lock_queue); + } + mutex_unlock(&dev->struct_mutex); + + if (file_priv->minor->master == file_priv->master) { + /* drop the reference held my the minor */ + if (dev->driver->master_drop) + dev->driver->master_drop(dev, file_priv, true); + drm_master_put(&file_priv->minor->master); + } + } + + /* drop the master reference held by the file priv */ + if (file_priv->master) + drm_master_put(&file_priv->master); + file_priv->is_master = 0; + mutex_unlock(&dev->master_mutex); +} + struct drm_master *drm_master_get(struct drm_master *master) { kref_get(&master->refcount); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index e2522672719a..f3b2677de882 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -411,43 +411,12 @@ int drm_release(struct inode *inode, struct file *filp) drm_legacy_ctxbitmap_flush(dev, file_priv); - mutex_lock(&dev->master_mutex); - - if (file_priv->is_master) { - struct drm_master *master = file_priv->master; - - /* - * Since the master is disappearing, so is the - * possibility to lock. - */ - mutex_lock(&dev->struct_mutex); - if (master->lock.hw_lock) { - if (dev->sigdata.lock == master->lock.hw_lock) - dev->sigdata.lock = NULL; - master->lock.hw_lock = NULL; - master->lock.file_priv = NULL; - wake_up_interruptible_all(&master->lock.lock_queue); - } - mutex_unlock(&dev->struct_mutex); - - if (file_priv->minor->master == file_priv->master) { - /* drop the reference held my the minor */ - if (dev->driver->master_drop) - dev->driver->master_drop(dev, file_priv, true); - drm_master_put(&file_priv->minor->master); - } - } - - /* drop the master reference held by the file priv */ - if (file_priv->master) - drm_master_put(&file_priv->master); - file_priv->is_master = 0; - mutex_unlock(&dev->master_mutex); + if (drm_is_primary_client(file_priv)) + drm_master_release(file_priv); if (dev->driver->postclose) dev->driver->postclose(dev, file_priv); - if (drm_core_check_feature(dev, DRIVER_PRIME)) drm_prime_destroy_file_private(&file_priv->prime); diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 2b9a94f679ed..38401d406532 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -67,6 +67,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, int drm_dropmaster_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int drm_master_open(struct drm_file *file_priv); +void drm_master_release(struct drm_file *file_priv); /* drm_sysfs.c */ extern struct class *drm_class; |