From patchwork Wed Mar 16 12:04:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 8599441 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 615F2C0553 for ; Wed, 16 Mar 2016 12:05:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C5949202F0 for ; Wed, 16 Mar 2016 12:05:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F3364202A1 for ; Wed, 16 Mar 2016 12:05:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966306AbcCPMFD (ORCPT ); Wed, 16 Mar 2016 08:05:03 -0400 Received: from [198.137.202.9] ([198.137.202.9]:39058 "EHLO bombadil.infradead.org" rhost-flags-FAIL-FAIL-OK-OK) by vger.kernel.org with ESMTP id S965207AbcCPMFB (ORCPT ); Wed, 16 Mar 2016 08:05:01 -0400 Received: from [191.33.151.62] (helo=smtp.w2.samsung.com) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1agABR-0005i6-2v; Wed, 16 Mar 2016 12:04:13 +0000 Received: from mchehab by smtp.w2.samsung.com with local (Exim 4.86_2) (envelope-from ) id 1agABN-00008B-W0; Wed, 16 Mar 2016 09:04:09 -0300 From: Mauro Carvalho Chehab To: Linux Media Mailing List Cc: Mauro Carvalho Chehab , Mauro Carvalho Chehab , Shuah Khan Subject: [PATCH 4/5] [media] media-device: use kref for media_device instance Date: Wed, 16 Mar 2016 09:04:05 -0300 Message-Id: <82ef082c4de7c0a1c546da1d9e462bc86ab423bf.1458129823.git.mchehab@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-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 X-Virus-Scanned: ClamAV using ClamSMTP Now that the media_device can be used by multiple drivers, via devres, we need to be sure that it will be dropped only when all drivers stop using it. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Javier Martinez Canillas Reviewed-by: Shuah Khan Acked-by: Sakari Ailus Reviewed-by: Shuah Khan Tested-by: Shuah Khan --- drivers/media/media-device.c | 48 +++++++++++++++++++++++++++++++------------- include/media/media-device.h | 3 +++ 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index c32fa15cc76e..38e6c319fe6e 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -721,6 +721,15 @@ int __must_check __media_device_register(struct media_device *mdev, { int ret; + /* Check if mdev was ever registered at all */ + mutex_lock(&mdev->graph_mutex); + if (media_devnode_is_registered(&mdev->devnode)) { + kref_get(&mdev->kref); + mutex_unlock(&mdev->graph_mutex); + return 0; + } + kref_init(&mdev->kref); + /* Register the device node. */ mdev->devnode.fops = &media_device_fops; mdev->devnode.parent = mdev->dev; @@ -730,8 +739,10 @@ int __must_check __media_device_register(struct media_device *mdev, mdev->topology_version = 0; ret = media_devnode_register(&mdev->devnode, owner); - if (ret < 0) + if (ret < 0) { + media_devnode_unregister(&mdev->devnode); return ret; + } ret = device_create_file(&mdev->devnode.dev, &dev_attr_model); if (ret < 0) { @@ -739,6 +750,7 @@ int __must_check __media_device_register(struct media_device *mdev, return ret; } + mutex_unlock(&mdev->graph_mutex); dev_dbg(mdev->dev, "Media device registered\n"); return 0; @@ -773,23 +785,15 @@ void media_device_unregister_entity_notify(struct media_device *mdev, } EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify); -void media_device_unregister(struct media_device *mdev) +static void do_media_device_unregister(struct kref *kref) { + struct media_device *mdev; struct media_entity *entity; struct media_entity *next; struct media_interface *intf, *tmp_intf; struct media_entity_notify *notify, *nextp; - if (mdev == NULL) - return; - - mutex_lock(&mdev->graph_mutex); - - /* Check if mdev was ever registered at all */ - if (!media_devnode_is_registered(&mdev->devnode)) { - mutex_unlock(&mdev->graph_mutex); - return; - } + mdev = container_of(kref, struct media_device, kref); /* Remove all entities from the media device */ list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list) @@ -807,13 +811,26 @@ void media_device_unregister(struct media_device *mdev) kfree(intf); } - mutex_unlock(&mdev->graph_mutex); + /* Check if mdev devnode was registered */ + if (!media_devnode_is_registered(&mdev->devnode)) + return; device_remove_file(&mdev->devnode.dev, &dev_attr_model); media_devnode_unregister(&mdev->devnode); dev_dbg(mdev->dev, "Media device unregistered\n"); } + +void media_device_unregister(struct media_device *mdev) +{ + if (mdev == NULL) + return; + + mutex_lock(&mdev->graph_mutex); + kref_put(&mdev->kref, do_media_device_unregister); + mutex_unlock(&mdev->graph_mutex); + +} EXPORT_SYMBOL_GPL(media_device_unregister); static void media_device_release_devres(struct device *dev, void *res) @@ -825,13 +842,16 @@ struct media_device *media_device_get_devres(struct device *dev) struct media_device *mdev; mdev = devres_find(dev, media_device_release_devres, NULL, NULL); - if (mdev) + if (mdev) { + kref_get(&mdev->kref); return mdev; + } mdev = devres_alloc(media_device_release_devres, sizeof(struct media_device), GFP_KERNEL); if (!mdev) return NULL; + return devres_get(dev, mdev, NULL, NULL); } EXPORT_SYMBOL_GPL(media_device_get_devres); diff --git a/include/media/media-device.h b/include/media/media-device.h index ca3871b853ba..73c16e6e6b6b 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -23,6 +23,7 @@ #ifndef _MEDIA_DEVICE_H #define _MEDIA_DEVICE_H +#include #include #include @@ -283,6 +284,7 @@ struct media_entity_notify { * struct media_device - Media device * @dev: Parent device * @devnode: Media device node + * @kref: Object refcount * @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 @@ -347,6 +349,7 @@ struct media_device { /* dev->driver_data points to this struct. */ struct device *dev; struct media_devnode devnode; + struct kref kref; char model[32]; char driver_name[32];