drm: Extract drm_master_open
And pull out the primary_client check to make it really obvious that this can't happen on control/render nodes. Bonus that we can avoid the master lock in this case. v2: Don't leak locks on error path (and simplify control flow while at it), reported by Julia. Cc: Julia Lawall <julia.lawall@lip6.fr> 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-6-git-send-email-daniel.vetter@ffwll.ch
This commit is contained in:
parent
6548f4e7a3
commit
2cbae7e637
@ -120,7 +120,7 @@ static struct drm_master *drm_master_create(struct drm_device *dev)
|
||||
* This function must be called with dev::struct_mutex held.
|
||||
* Returns negative error code on failure. Zero on success.
|
||||
*/
|
||||
int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
|
||||
static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
|
||||
{
|
||||
struct drm_master *old_master;
|
||||
int ret;
|
||||
@ -226,6 +226,23 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int drm_master_open(struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_device *dev = file_priv->minor->dev;
|
||||
int ret = 0;
|
||||
|
||||
/* if there is no current master make this fd it, but do not create
|
||||
* any master object for render clients */
|
||||
mutex_lock(&dev->master_mutex);
|
||||
if (!file_priv->minor->master)
|
||||
ret = drm_new_set_master(dev, file_priv);
|
||||
else
|
||||
file_priv->master = drm_master_get(file_priv->minor->master);
|
||||
mutex_unlock(&dev->master_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct drm_master *drm_master_get(struct drm_master *master)
|
||||
{
|
||||
kref_get(&master->refcount);
|
||||
|
@ -229,19 +229,11 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
||||
goto out_prime_destroy;
|
||||
}
|
||||
|
||||
/* if there is no current master make this fd it, but do not create
|
||||
* any master object for render clients */
|
||||
mutex_lock(&dev->master_mutex);
|
||||
if (drm_is_primary_client(priv) && !priv->minor->master) {
|
||||
/* create a new master */
|
||||
ret = drm_new_set_master(dev, priv);
|
||||
if (drm_is_primary_client(priv)) {
|
||||
ret = drm_master_open(priv);
|
||||
if (ret)
|
||||
goto out_close;
|
||||
} else if (drm_is_primary_client(priv)) {
|
||||
/* get a reference to the master */
|
||||
priv->master = drm_master_get(priv->minor->master);
|
||||
}
|
||||
mutex_unlock(&dev->master_mutex);
|
||||
|
||||
mutex_lock(&dev->filelist_mutex);
|
||||
list_add(&priv->lhead, &dev->filelist);
|
||||
@ -270,7 +262,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
||||
return 0;
|
||||
|
||||
out_close:
|
||||
mutex_unlock(&dev->master_mutex);
|
||||
if (dev->driver->postclose)
|
||||
dev->driver->postclose(dev, priv);
|
||||
out_prime_destroy:
|
||||
|
@ -66,7 +66,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv);
|
||||
int drm_master_open(struct drm_file *file_priv);
|
||||
|
||||
/* drm_sysfs.c */
|
||||
extern struct class *drm_class;
|
||||
|
Loading…
x
Reference in New Issue
Block a user