From patchwork Tue Apr 5 03:35:57 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shuah Khan X-Patchwork-Id: 8746791 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 3A9BB9F336 for ; Tue, 5 Apr 2016 03:37:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3B851202EC for ; Tue, 5 Apr 2016 03:37:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D4EDC20328 for ; Tue, 5 Apr 2016 03:37:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753872AbcDEDgP (ORCPT ); Mon, 4 Apr 2016 23:36:15 -0400 Received: from mailout.easymail.ca ([64.68.201.169]:50264 "EHLO mailout.easymail.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752172AbcDEDgL (ORCPT ); Mon, 4 Apr 2016 23:36:11 -0400 Received: from localhost (localhost [127.0.0.1]) by mailout.easymail.ca (Postfix) with ESMTP id E1EE2EB63; Mon, 4 Apr 2016 23:36:09 -0400 (EDT) X-Quarantine-ID: X-Virus-Scanned: Debian amavisd-new at mailout.easymail.ca X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" X-Spam-Score: -3.694 X-Spam-Level: X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from mailout.easymail.ca ([127.0.0.1]) by localhost (easymail-mailout.easydns.vpn [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id J5-wbQkLWuOc; Mon, 4 Apr 2016 23:36:09 -0400 (EDT) Received: from mail.gonehiking.org (c-73-181-52-62.hsd1.co.comcast.net [73.181.52.62]) by mailout.easymail.ca (Postfix) with ESMTPA id 62507EA78; Mon, 4 Apr 2016 23:36:07 -0400 (EDT) Received: from lorien.sisa.samsung.com (lorien-wl.internal [192.168.1.40]) by mail.gonehiking.org (Postfix) with ESMTP id 065219F2F2; Mon, 4 Apr 2016 21:36:07 -0600 (MDT) From: Shuah Khan To: mchehab@osg.samsung.com, laurent.pinchart@ideasonboard.com, perex@perex.cz, tiwai@suse.com, hans.verkuil@cisco.com, chehabrafael@gmail.com, javier@osg.samsung.com, jh1009.sung@samsung.com, ricard.wanderlof@axis.com, julian@jusst.de, pierre-louis.bossart@linux.intel.com, clemens@ladisch.de, dominic.sacre@gmx.de, takamichiho@gmail.com, johan@oljud.se, geliangtang@163.com Cc: Shuah Khan , linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org Subject: [RFC PATCH v2 2/5] media: Add driver count to keep track of media device registrations Date: Mon, 4 Apr 2016 21:35:57 -0600 Message-Id: <07bb92168242dc8a30338cf2978b22ec31395dc3.1459825702.git.shuahkh@osg.samsung.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: References: In-Reply-To: References: Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add driver count to keep track of media device registrations to avoid releasing the media device, when one of the drivers does unregister when media device belongs to more than one driver. Also add a new interfaces to unregister a media device allocated using Media Device Allocator and a increment register count. Change media_open() to get media device reference and put the reference in media_release(). Signed-off-by: Shuah Khan --- drivers/media/media-device.c | 49 ++++++++++++++++++++++++++++++++++++++++++- drivers/media/media-devnode.c | 10 ++++++--- include/media/media-device.h | 31 +++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 6e43c95..f22cf0f 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -36,6 +36,7 @@ #include #include #include +#include #ifdef CONFIG_MEDIA_CONTROLLER @@ -743,12 +744,31 @@ int __must_check __media_device_register(struct media_device *mdev, return ret; } - dev_dbg(mdev->dev, "Media device registered\n"); + mdev->num_drivers++; + dev_dbg(mdev->dev, "Media device registered num_drivers %d\n", + mdev->num_drivers); return 0; } EXPORT_SYMBOL_GPL(__media_device_register); +void media_device_register_ref(struct media_device *mdev) +{ + if (!mdev) + return; + + mutex_lock(&mdev->graph_mutex); + + /* Check if mdev is registered - bump registered driver count */ + if (media_devnode_is_registered(&mdev->devnode)) + mdev->num_drivers++; + + dev_dbg(mdev->dev, "%s: mdev %p num_drivers %d\n", __func__, mdev, + mdev->num_drivers); + mutex_unlock(&mdev->graph_mutex); +} +EXPORT_SYMBOL_GPL(media_device_register_ref); + int __must_check media_device_register_entity_notify(struct media_device *mdev, struct media_entity_notify *nptr) { @@ -820,6 +840,33 @@ void media_device_unregister(struct media_device *mdev) } EXPORT_SYMBOL_GPL(media_device_unregister); +void media_device_unregister_put(struct media_device *mdev) +{ + if (mdev == NULL) + return; + + dev_dbg(mdev->dev, "%s: mdev %p num_drivers %d\n", __func__, mdev, + mdev->num_drivers); + + mutex_lock(&mdev->graph_mutex); + mdev->num_drivers--; + if (mdev->num_drivers == 0) { + mutex_unlock(&mdev->graph_mutex); + + /* unregister media device and cleanup */ + media_device_unregister(mdev); + media_device_cleanup(mdev); + + /* mark the media device for deletion */ + media_device_set_to_delete_state(mdev->dev); + } else + mutex_unlock(&mdev->graph_mutex); + + dev_dbg(mdev->dev, "%s: end mdev %p num_drivers %d\n", __func__, mdev, + mdev->num_drivers); +} +EXPORT_SYMBOL_GPL(media_device_unregister_put); + static void media_device_release_devres(struct device *dev, void *res) { } diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index 29409f4..ec18815 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -44,6 +44,7 @@ #include #include +#include #define MEDIA_NUM_DEVICES 256 #define MEDIA_NAME "media" @@ -173,7 +174,6 @@ static int media_open(struct inode *inode, struct file *filp) } /* and increase the device refcount */ get_device(&mdev->dev); - mutex_unlock(&media_devnode_lock); filp->private_data = mdev; @@ -182,11 +182,14 @@ static int media_open(struct inode *inode, struct file *filp) if (ret) { put_device(&mdev->dev); filp->private_data = NULL; - return ret; + goto done; } } - return 0; + media_device_get_ref(mdev->parent); +done: + mutex_unlock(&media_devnode_lock); + return ret; } /* Override for the release function */ @@ -201,6 +204,7 @@ static int media_release(struct inode *inode, struct file *filp) return value is ignored. */ put_device(&mdev->dev); filp->private_data = NULL; + media_device_put(mdev->parent); return 0; } diff --git a/include/media/media-device.h b/include/media/media-device.h index df74cfa..aaeac7a 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -284,6 +284,7 @@ struct media_entity_notify { * struct media_device - Media device * @dev: Parent device * @devnode: Media device node + * @num_drivers: Number of drivers that own the media device and register. * @driver_name: Optional device driver name. If not set, calls to * %MEDIA_IOC_DEVICE_INFO will return dev->driver->name. * This is needed for USB drivers for example, as otherwise @@ -349,6 +350,7 @@ struct media_device { /* dev->driver_data points to this struct. */ struct device *dev; struct media_devnode devnode; + int num_drivers; char model[32]; char driver_name[32]; @@ -494,6 +496,17 @@ int __must_check __media_device_register(struct media_device *mdev, #define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE) /** + * media_device_register_ref() - Increments media device register driver count + * + * @mdev: pointer to struct &media_device + * + * When more than one driver is associated with the media device, it is + * necessary to maintain the number of registrations to avoid unregister + * when it is still in use. + */ +void media_device_register_ref(struct media_device *mdev); + +/** * __media_device_unregister() - Unegisters a media device element * * @mdev: pointer to struct &media_device @@ -505,6 +518,18 @@ int __must_check __media_device_register(struct media_device *mdev, void media_device_unregister(struct media_device *mdev); /** + * media_device_unregister_put() - Unregisters a media device element + * + * @mdev: pointer to struct &media_device + * + * Should be called to unregister media device allocated with Media Device + * Allocator API media_device_get() interface. + * It is safe to call this function on an unregistered (but initialised) + * media device. + */ +void media_device_unregister_put(struct media_device *mdev); + +/** * media_device_register_entity() - registers a media entity inside a * previously registered media device. * @@ -661,9 +686,15 @@ static inline int media_device_register(struct media_device *mdev) { return 0; } +static inline void media_device_register_ref(struct media_device *mdev) +{ +} static inline void media_device_unregister(struct media_device *mdev) { } +static inline void media_device_unregister_put(struct media_device *mdev) +{ +} static inline int media_device_register_entity(struct media_device *mdev, struct media_entity *entity) {