From patchwork Tue Oct 21 10:50:14 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dheeraj Jamwal X-Patchwork-Id: 5117161 Return-Path: X-Original-To: patchwork-ltsi-dev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id D8A52C11AC for ; Tue, 21 Oct 2014 11:31:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DC97220107 for ; Tue, 21 Oct 2014 11:31:53 +0000 (UTC) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D412C200CC for ; Tue, 21 Oct 2014 11:31:52 +0000 (UTC) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id DF317B77; Tue, 21 Oct 2014 11:05:22 +0000 (UTC) X-Original-To: ltsi-dev@lists.linuxfoundation.org Delivered-To: ltsi-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 99122B12 for ; Tue, 21 Oct 2014 11:05:21 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by smtp1.linuxfoundation.org (Postfix) with ESMTP id 8B3D220114 for ; Tue, 21 Oct 2014 11:05:20 +0000 (UTC) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 21 Oct 2014 04:05:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.04,761,1406617200"; d="scan'208";a="617795901" Received: from ubuntu-desktop.png.intel.com ([10.221.122.25]) by fmsmga002.fm.intel.com with ESMTP; 21 Oct 2014 04:05:18 -0700 From: Dheeraj Jamwal To: ltsi-dev@lists.linuxfoundation.org Date: Tue, 21 Oct 2014 18:50:14 +0800 Message-Id: <1413889294-31328-415-git-send-email-dheerajx.s.jamwal@intel.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1413889294-31328-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1413889294-31328-1-git-send-email-dheerajx.s.jamwal@intel.com> X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org Subject: [LTSI-dev] [PATCH 0414/1094] drm: add minor-lookup/release helpers X-BeenThere: ltsi-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: "A list to discuss patches, development, and other things related to the LTSI project" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ltsi-dev-bounces@lists.linuxfoundation.org Errors-To: ltsi-dev-bounces@lists.linuxfoundation.org X-Virus-Scanned: ClamAV using ClamSMTP From: David Herrmann 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 Reviewed-by: Daniel Vetter (cherry picked from commit 1616c525b98deb34b8f4b02eccf0ae3a1310fa27) Signed-off-by: Dheeraj Jamwal --- 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 1fd43ee..92396f0 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; } @@ -454,7 +455,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); @@ -576,6 +578,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 8b2133e..fccf252 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -358,6 +358,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 c4554bb..2406217 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1643,6 +1643,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 */