From patchwork Wed May 24 00:15:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 9744615 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CD3936032B for ; Wed, 24 May 2017 00:17:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C02B528840 for ; Wed, 24 May 2017 00:17:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B52DA28863; Wed, 24 May 2017 00:17:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EF4CD28840 for ; Wed, 24 May 2017 00:17:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965594AbdEXARJ (ORCPT ); Tue, 23 May 2017 20:17:09 -0400 Received: from smtp-4.sys.kth.se ([130.237.48.193]:46769 "EHLO smtp-4.sys.kth.se" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1765675AbdEXARF (ORCPT ); Tue, 23 May 2017 20:17:05 -0400 Received: from smtp-4.sys.kth.se (localhost.localdomain [127.0.0.1]) by smtp-4.sys.kth.se (Postfix) with ESMTP id B94F23333; Wed, 24 May 2017 02:17:03 +0200 (CEST) X-Virus-Scanned: by amavisd-new at kth.se Received: from smtp-4.sys.kth.se ([127.0.0.1]) by smtp-4.sys.kth.se (smtp-4.sys.kth.se [127.0.0.1]) (amavisd-new, port 10024) with LMTP id y3QAp5mmSncV; Wed, 24 May 2017 02:17:02 +0200 (CEST) X-KTH-Auth: niso [89.233.230.99] X-KTH-mail-from: niklas.soderlund@ragnatech.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by smtp-4.sys.kth.se (Postfix) with ESMTPSA id A49FB32FD; Wed, 24 May 2017 02:17:01 +0200 (CEST) From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= To: Laurent Pinchart , Hans Verkuil , linux-media@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org, tomoharu.fukawa.eb@renesas.com, Kieran Bingham , Sakari Ailus , =?UTF-8?q?Niklas=20S=C3=B6derlund?= Subject: [PATCH v2 15/17] rcar-vin: register the video device at probe time Date: Wed, 24 May 2017 02:15:38 +0200 Message-Id: <20170524001540.13613-16-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170524001540.13613-1-niklas.soderlund@ragnatech.se> References: <20170524001540.13613-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Niklas Söderlund The driver registers the video device from the async complete callback and unregistered in the async unbind callback. This creates problems if if the subdevice is bound, unbound and later rebound. The second time video_register_device() is called it fails: kobject (eb3be918): tried to init an initialized object, something is seriously wrong. To prevent this register the video device at prob time and don't allow user-space to open the video device if the subdevice have not yet been bound. Signed-off-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-core.c | 47 ++++++++++++++++++++++++++--- drivers/media/platform/rcar-vin/rcar-v4l2.c | 42 ++++---------------------- drivers/media/platform/rcar-vin/rcar-vin.h | 1 + 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index dcca906ba58435f5..0e1757301a0bca1e 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -74,6 +74,7 @@ static bool rvin_mbus_supported(struct rvin_graph_entity *entity) static int rvin_digital_notify_complete(struct v4l2_async_notifier *notifier) { struct rvin_dev *vin = notifier_to_vin(notifier); + struct v4l2_subdev *sd = vin_to_source(vin); int ret; /* Verify subdevices mbus format */ @@ -92,7 +93,35 @@ static int rvin_digital_notify_complete(struct v4l2_async_notifier *notifier) return ret; } - return rvin_v4l2_probe(vin); + /* Add the controls */ + /* + * Currently the subdev with the largest number of controls (13) is + * ov6550. So let's pick 16 as a hint for the control handler. Note + * that this is a hint only: too large and you waste some memory, too + * small and there is a (very) small performance hit when looking up + * controls in the internal hash. + */ + ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16); + if (ret < 0) + return ret; + + ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, sd->ctrl_handler, NULL); + if (ret < 0) + return ret; + + ret = v4l2_subdev_call(sd, video, g_tvnorms, &vin->vdev.tvnorms); + if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) + return ret; + + if (vin->vdev.tvnorms == 0) { + /* Disable the STD API if there are no tvnorms defined */ + v4l2_disable_ioctl(&vin->vdev, VIDIOC_G_STD); + v4l2_disable_ioctl(&vin->vdev, VIDIOC_S_STD); + v4l2_disable_ioctl(&vin->vdev, VIDIOC_QUERYSTD); + v4l2_disable_ioctl(&vin->vdev, VIDIOC_ENUMSTD); + } + + return rvin_reset_format(vin); } static void rvin_digital_notify_unbind(struct v4l2_async_notifier *notifier, @@ -102,7 +131,7 @@ static void rvin_digital_notify_unbind(struct v4l2_async_notifier *notifier, struct rvin_dev *vin = notifier_to_vin(notifier); vin_dbg(vin, "unbind digital subdev %s\n", subdev->name); - rvin_v4l2_remove(vin); + v4l2_ctrl_handler_free(&vin->ctrl_handler); vin->digital.subdev = NULL; } @@ -290,9 +319,13 @@ static int rcar_vin_probe(struct platform_device *pdev) if (ret) return ret; + ret = rvin_v4l2_probe(vin); + if (ret) + goto error_dma; + ret = rvin_digital_graph_init(vin); if (ret < 0) - goto error; + goto error_v4l2; pm_suspend_ignore_children(&pdev->dev, true); pm_runtime_enable(&pdev->dev); @@ -300,7 +333,9 @@ static int rcar_vin_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vin); return 0; -error: +error_v4l2: + rvin_v4l2_remove(vin); +error_dma: rvin_dma_remove(vin); return ret; @@ -314,6 +349,10 @@ static int rcar_vin_remove(struct platform_device *pdev) v4l2_async_notifier_unregister(&vin->notifier); + /* Checks internaly if handlers have been init or not */ + v4l2_ctrl_handler_free(&vin->ctrl_handler); + + rvin_v4l2_remove(vin); rvin_dma_remove(vin); return 0; diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index be6f41bf82ac3bc5..6f1c27fc828fe57e 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -103,7 +103,7 @@ static void rvin_reset_crop_compose(struct rvin_dev *vin) vin->compose.height = vin->format.height; } -static int rvin_reset_format(struct rvin_dev *vin) +int rvin_reset_format(struct rvin_dev *vin) { struct v4l2_subdev_format fmt = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, @@ -785,6 +785,11 @@ static int rvin_open(struct file *file) mutex_lock(&vin->lock); + if (!vin->digital.subdev) { + ret = -ENODEV; + goto unlock; + } + file->private_data = vin; ret = v4l2_fh_open(file); @@ -848,9 +853,6 @@ void rvin_v4l2_remove(struct rvin_dev *vin) v4l2_info(&vin->v4l2_dev, "Removing %s\n", video_device_node_name(&vin->vdev)); - /* Checks internaly if handlers have been init or not */ - v4l2_ctrl_handler_free(&vin->ctrl_handler); - /* Checks internaly if vdev have been init or not */ video_unregister_device(&vin->vdev); } @@ -873,41 +875,10 @@ static void rvin_notify(struct v4l2_subdev *sd, int rvin_v4l2_probe(struct rvin_dev *vin) { struct video_device *vdev = &vin->vdev; - struct v4l2_subdev *sd = vin_to_source(vin); int ret; - v4l2_set_subdev_hostdata(sd, vin); - vin->v4l2_dev.notify = rvin_notify; - ret = v4l2_subdev_call(sd, video, g_tvnorms, &vin->vdev.tvnorms); - if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) - return ret; - - if (vin->vdev.tvnorms == 0) { - /* Disable the STD API if there are no tvnorms defined */ - v4l2_disable_ioctl(&vin->vdev, VIDIOC_G_STD); - v4l2_disable_ioctl(&vin->vdev, VIDIOC_S_STD); - v4l2_disable_ioctl(&vin->vdev, VIDIOC_QUERYSTD); - v4l2_disable_ioctl(&vin->vdev, VIDIOC_ENUMSTD); - } - - /* Add the controls */ - /* - * Currently the subdev with the largest number of controls (13) is - * ov6550. So let's pick 16 as a hint for the control handler. Note - * that this is a hint only: too large and you waste some memory, too - * small and there is a (very) small performance hit when looking up - * controls in the internal hash. - */ - ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16); - if (ret < 0) - return ret; - - ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, sd->ctrl_handler, NULL); - if (ret < 0) - return ret; - /* video node */ vdev->fops = &rvin_fops; vdev->v4l2_dev = &vin->v4l2_dev; @@ -921,7 +892,6 @@ int rvin_v4l2_probe(struct rvin_dev *vin) V4L2_CAP_READWRITE; vin->format.pixelformat = RVIN_DEFAULT_FORMAT; - rvin_reset_format(vin); ret = video_register_device(&vin->vdev, VFL_TYPE_GRABBER, -1); if (ret) { diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h index 9bfb5a7c4dc4f215..9d0d4a5001b6ccd8 100644 --- a/drivers/media/platform/rcar-vin/rcar-vin.h +++ b/drivers/media/platform/rcar-vin/rcar-vin.h @@ -158,6 +158,7 @@ void rvin_dma_remove(struct rvin_dev *vin); int rvin_v4l2_probe(struct rvin_dev *vin); void rvin_v4l2_remove(struct rvin_dev *vin); +int rvin_reset_format(struct rvin_dev *vin); const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat);