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

Commit 1616c525 authored by David Herrmann's avatar David Herrmann
Browse files

drm: add minor-lookup/release helpers



Instead of accessing drm_minors_idr directly, this adds a small helper to
hide the internals. This will help us later to remove the drm_global_mutex
requirement for minor-lookup.

Furthermore, this also makes sure that minor->dev is always valid and
takes a reference-count to the device as long as the minor is used in an
open-file. This way, "struct file*"->private_data->dev is guaranteed to be
valid (which it has to, as we cannot reset it).

Signed-off-by: default avatarDavid Herrmann <dh.herrmann@gmail.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 099d1c29
Loading
Loading
Loading
Loading
+27 −23
Original line number Diff line number Diff line
@@ -79,23 +79,22 @@ static int drm_setup(struct drm_device * dev)
 */
int drm_open(struct inode *inode, struct file *filp)
{
	struct drm_device *dev = NULL;
	int minor_id = iminor(inode);
	struct drm_device *dev;
	struct drm_minor *minor;
	int retcode = 0;
	int retcode;
	int need_setup = 0;
	struct address_space *old_mapping;
	struct address_space *old_imapping;

	minor = idr_find(&drm_minors_idr, minor_id);
	if (!minor)
		return -ENODEV;

	if (!(dev = minor->dev))
		return -ENODEV;
	minor = drm_minor_acquire(iminor(inode));
	if (IS_ERR(minor))
		return PTR_ERR(minor);

	if (drm_device_is_unplugged(dev))
		return -ENODEV;
	dev = minor->dev;
	if (drm_device_is_unplugged(dev)) {
		retcode = -ENODEV;
		goto err_release;
	}

	if (!dev->open_count++)
		need_setup = 1;
@@ -128,6 +127,8 @@ int drm_open(struct inode *inode, struct file *filp)
	dev->dev_mapping = old_mapping;
	mutex_unlock(&dev->struct_mutex);
	dev->open_count--;
err_release:
	drm_minor_release(minor);
	return retcode;
}
EXPORT_SYMBOL(drm_open);
@@ -143,33 +144,33 @@ EXPORT_SYMBOL(drm_open);
 */
int drm_stub_open(struct inode *inode, struct file *filp)
{
	struct drm_device *dev = NULL;
	struct drm_device *dev;
	struct drm_minor *minor;
	int minor_id = iminor(inode);
	int err = -ENODEV;
	const struct file_operations *new_fops;

	DRM_DEBUG("\n");

	mutex_lock(&drm_global_mutex);
	minor = idr_find(&drm_minors_idr, minor_id);
	if (!minor)
		goto out;

	if (!(dev = minor->dev))
		goto out;
	minor = drm_minor_acquire(iminor(inode));
	if (IS_ERR(minor))
		goto out_unlock;

	dev = minor->dev;
	if (drm_device_is_unplugged(dev))
		goto out;
		goto out_release;

	new_fops = fops_get(dev->driver->fops);
	if (!new_fops)
		goto out;
		goto out_release;

	replace_fops(filp, new_fops);
	if (filp->f_op->open)
		err = filp->f_op->open(inode, filp);
out:

out_release:
	drm_minor_release(minor);
out_unlock:
	mutex_unlock(&drm_global_mutex);
	return err;
}
@@ -453,7 +454,8 @@ int drm_lastclose(struct drm_device * dev)
int drm_release(struct inode *inode, struct file *filp)
{
	struct drm_file *file_priv = filp->private_data;
	struct drm_device *dev = file_priv->minor->dev;
	struct drm_minor *minor = file_priv->minor;
	struct drm_device *dev = minor->dev;
	int retcode = 0;

	mutex_lock(&drm_global_mutex);
@@ -575,6 +577,8 @@ int drm_release(struct inode *inode, struct file *filp)
	}
	mutex_unlock(&drm_global_mutex);

	drm_minor_release(minor);

	return retcode;
}
EXPORT_SYMBOL(drm_release);
+39 −0
Original line number Diff line number Diff line
@@ -355,6 +355,45 @@ static void drm_unplug_minor(struct drm_minor *minor)
	idr_remove(&drm_minors_idr, minor->index);
}

/**
 * drm_minor_acquire - Acquire a DRM minor
 * @minor_id: Minor ID of the DRM-minor
 *
 * Looks up the given minor-ID and returns the respective DRM-minor object. The
 * refence-count of the underlying device is increased so you must release this
 * object with drm_minor_release().
 *
 * As long as you hold this minor, it is guaranteed that the object and the
 * minor->dev pointer will stay valid! However, the device may get unplugged and
 * unregistered while you hold the minor.
 *
 * Returns:
 * Pointer to minor-object with increased device-refcount, or PTR_ERR on
 * failure.
 */
struct drm_minor *drm_minor_acquire(unsigned int minor_id)
{
	struct drm_minor *minor;

	minor = idr_find(&drm_minors_idr, minor_id);
	if (!minor)
		return ERR_PTR(-ENODEV);

	drm_dev_ref(minor->dev);
	return minor;
}

/**
 * drm_minor_release - Release DRM minor
 * @minor: Pointer to DRM minor object
 *
 * Release a minor that was previously acquired via drm_minor_acquire().
 */
void drm_minor_release(struct drm_minor *minor)
{
	drm_dev_unref(minor->dev);
}

/**
 * drm_put_minor - Destroy DRM minor
 * @minor: Minor to destroy
+4 −0
Original line number Diff line number Diff line
@@ -1672,6 +1672,10 @@ void drm_dev_ref(struct drm_device *dev);
void drm_dev_unref(struct drm_device *dev);
int drm_dev_register(struct drm_device *dev, unsigned long flags);
void drm_dev_unregister(struct drm_device *dev);

struct drm_minor *drm_minor_acquire(unsigned int minor_id);
void drm_minor_release(struct drm_minor *minor);

/*@}*/

/* PCI section */