Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cbae7e6 authored by Daniel Vetter's avatar Daniel Vetter
Browse files

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1465930269-7883-6-git-send-email-daniel.vetter@ffwll.ch
parent 6548f4e7
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -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 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
	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);
+2 −11
Original line number Diff line number Diff line
@@ -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:
+1 −1
Original line number Diff line number Diff line
@@ -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;