All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Herrmann <dh.herrmann@gmail.com>
To: dri-devel@lists.freedesktop.org
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Subject: [PATCH 06/13] drm: add minor-lookup/release helpers
Date: Wed, 29 Jan 2014 15:01:53 +0100	[thread overview]
Message-ID: <1391004120-687-7-git-send-email-dh.herrmann@gmail.com> (raw)
In-Reply-To: <1391004120-687-1-git-send-email-dh.herrmann@gmail.com>

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: David Herrmann <dh.herrmann@gmail.com>
---
 drivers/gpu/drm/drm_fops.c | 50 +++++++++++++++++++++++++---------------------
 drivers/gpu/drm/drm_stub.c | 39 ++++++++++++++++++++++++++++++++++++
 include/drm/drmP.h         |  4 ++++
 3 files changed, 70 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 6466cb5..7947819 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -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 @@ err_undo:
 	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);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index c51333e..d3232b6 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -356,6 +356,45 @@ static void drm_unplug_minor(struct drm_minor *minor)
 }
 
 /**
+ * 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
  *
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 2c58e94..3c02cad 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1669,6 +1669,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 */
-- 
1.8.5.3

  parent reply	other threads:[~2014-01-29 14:02 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-29 14:01 [PATCH 00/13] DRM Reliable Minor-IDs David Herrmann
2014-01-29 14:01 ` [PATCH 01/13] drm: group dev-lifetime related members David Herrmann
2014-01-29 14:01 ` [PATCH 02/13] drm: skip redundant minor-lookup in open path David Herrmann
2014-01-29 14:01 ` [PATCH 03/13] drm: remove unused DRM_MINOR_UNASSIGNED David Herrmann
2014-01-29 14:01 ` [PATCH 04/13] drm: turn DRM_MINOR_* into enum David Herrmann
2014-01-29 14:01 ` [PATCH 05/13] drm: provide device-refcount David Herrmann
2014-02-12 13:25   ` Daniel Vetter
2014-02-12 14:44     ` David Herrmann
2014-02-12 16:26       ` Daniel Vetter
2014-02-12 16:26         ` Daniel Vetter
2014-02-12 16:40         ` Greg KH
2014-02-12 17:48           ` David Herrmann
2014-02-12 17:48             ` David Herrmann
2014-02-12 18:31             ` Daniel Vetter
2014-02-12 18:31               ` Daniel Vetter
2014-02-12 18:38             ` Greg KH
2014-02-21  7:01   ` Thierry Reding
2014-02-24 13:51     ` David Herrmann
2014-01-29 14:01 ` David Herrmann [this message]
2014-02-21  7:09   ` [PATCH 06/13] drm: add minor-lookup/release helpers Thierry Reding
2014-02-21  7:34     ` David Herrmann
2014-02-21  7:37       ` Thierry Reding
2014-01-29 14:01 ` [PATCH 07/13] drm: allocate minors early David Herrmann
2014-01-29 14:01 ` [PATCH 08/13] drm: move drm_put_minor() to drm_minor_free() David Herrmann
2014-01-29 14:01 ` [PATCH 09/13] drm: rename drm_unplug/get_minor() to drm_minor_register/unregister() David Herrmann
2014-02-21  7:21   ` Thierry Reding
2014-02-24 13:52     ` David Herrmann
2014-01-29 14:01 ` [PATCH 10/13] drm: remove unneeded #ifdef CONFIG_DEBUGFS David Herrmann
2014-01-29 14:01 ` [PATCH 11/13] drm: remove redundant minor->device field David Herrmann
2014-02-12 13:36   ` Daniel Vetter
2014-02-21  7:30     ` Thierry Reding
2014-02-21 20:07       ` David Herrmann
2014-01-29 14:01 ` [PATCH 12/13] drm: make minor-IDs reliable David Herrmann
2014-01-29 14:02 ` [PATCH 13/13] drm: remove redundant minor->index David Herrmann
2014-02-21  7:30 ` [PATCH 00/13] DRM Reliable Minor-IDs Thierry Reding

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1391004120-687-7-git-send-email-dh.herrmann@gmail.com \
    --to=dh.herrmann@gmail.com \
    --cc=daniel.vetter@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.