From patchwork Sun Apr 24 21:08:18 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivaylo Dimitrov X-Patchwork-Id: 34023 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.84_2) (envelope-from ) id 1auRIe-0007BK-MQ; Sun, 24 Apr 2016 21:10:40 +0000 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.76/mailfrontend-7) with esmtp id 1auRIc-0000Ec-1p; Sun, 24 Apr 2016 23:10:40 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753334AbcDXVKd (ORCPT + 1 other); Sun, 24 Apr 2016 17:10:33 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:35745 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753259AbcDXVKc (ORCPT ); Sun, 24 Apr 2016 17:10:32 -0400 Received: by mail-wm0-f66.google.com with SMTP id e201so17587695wme.2 for ; Sun, 24 Apr 2016 14:10:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=d8+CpdcJaipz+22JDdZrb3m2wVrOzuWixoxZg3VWxEo=; b=hc2Ti4iym+erBetEMrjjPf0Zks4VaewTZM9Dei2eayfUuBA0zU5j/5DTBD3v8OsFiP TiJChxVSEOzTpIm5ohlqP8B39mG/N3BVN92jZztxvvbtQzbFxQFlRmLILWkOtTr4re2s Wc4Mr2u8ZeTivRLWdxRc5UtZLg3ECchmtY3owm6FpYRcr6NbcRFRs4L5Y6H8DOShiPYG 8AeqbNr97Nlj7Z+FrG72aa2WFJ83RtGydD5YfmNfBjHRm4AoJxvfcEFBdFEua1wdMp3q LbgpITTJySJPuYwM9j+grNrczHfuGyQL4YIygCgpTZ7TZVrbq4khr3m6LqCD941EZSJj VWgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=d8+CpdcJaipz+22JDdZrb3m2wVrOzuWixoxZg3VWxEo=; b=Oo6mEAIjE0NxMtQTggJx12ybOBN0kjaL8u/gUDKSPMFaWlY0J0h7UZK831UnSNKmqu 4G37pXk9vDlHphQ9ebKuDl8TN+9vqWydge4lm9qYXesedrTPcNm8lor54OgdVag4D3rK uZ2QWuPX/C94ub3cbKYb7E6F62PgFobGOxba0Dpn7xa3/85gRilGwYto8YN49lzdBDev IeTvJXjZEwV2O9ckt8jLhr6Xkctd6DUk+njZ0tht4lYu7QH+BoaQR9Hn4c+TDkkqZ1Yo oV3WIaU5Le+WbGqPfl18L0S2xlUIzKU8epS/xUGDVPg80GcdxnL1H5Zud02HP62V7Zmr aolA== X-Gm-Message-State: AOPr4FWrCUGlgHmG7yOstQJBxAnqm8BPXXKRWMB/T+Gsj5ixCnc9ushlLa90OXEQDUlh/A== X-Received: by 10.28.167.193 with SMTP id q184mr5229101wme.63.1461532230776; Sun, 24 Apr 2016 14:10:30 -0700 (PDT) Received: from localhost.localdomain ([46.249.74.23]) by smtp.gmail.com with ESMTPSA id b2sm15440182wmb.9.2016.04.24.14.10.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 24 Apr 2016 14:10:30 -0700 (PDT) From: Ivaylo Dimitrov To: sakari.ailus@iki.fi Cc: sre@kernel.org, pali.rohar@gmail.com, pavel@ucw.cz, linux-media@vger.kernel.org Subject: [RFC PATCH 18/24] v4l2-async: per notifier locking Date: Mon, 25 Apr 2016 00:08:18 +0300 Message-Id: <1461532104-24032-19-git-send-email-ivo.g.dimitrov.75@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1461532104-24032-1-git-send-email-ivo.g.dimitrov.75@gmail.com> References: <20160420081427.GZ32125@valkosipuli.retiisi.org.uk> <1461532104-24032-1-git-send-email-ivo.g.dimitrov.75@gmail.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2016.4.24.210315 X-PMX-Spam: Gauge=IIIIIIIII, Probability=9%, Report=' FORGED_FROM_GMAIL 0.1, MULTIPLE_RCPTS 0.1, HTML_00_01 0.05, HTML_00_10 0.05, BODY_SIZE_6000_6999 0, BODY_SIZE_7000_LESS 0, DKIM_SIGNATURE 0, NO_URI_HTTPS 0, REFERENCES 0, SINGLE_URI_IN_BODY 0, URI_ENDS_IN_HTML 0, __ANY_URI 0, __CP_URI_IN_BODY 0, __DATE_TZ_RU 0, __FRAUD_WEBMAIL 0, __FRAUD_WEBMAIL_FROM 0, __FROM_GMAIL 0, __HAS_FROM 0, __HAS_MSGID 0, __HAS_X_MAILER 0, __HAS_X_MAILING_LIST 0, __IN_REP_TO 0, __MIME_TEXT_ONLY 0, __MULTIPLE_RCPTS_CC_X2 0, __PHISH_SPEAR_STRUCTURE_1 0, __REFERENCES 0, __SANE_MSGID 0, __SINGLE_URI_TEXT 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_IN_BODY 0, __URI_NO_WWW 0, __URI_NS , __URI_WITH_PATH 0, __YOUTUBE_RCVD 0' From: Sebastian Reichel --- drivers/media/v4l2-core/v4l2-async.c | 50 ++++++++++++++++++------------------ include/media/v4l2-async.h | 2 ++ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index a4b224d..27789cd 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -56,7 +56,6 @@ static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) static LIST_HEAD(subdev_list); static LIST_HEAD(notifier_list); -static DEFINE_MUTEX(list_lock); static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd) @@ -106,14 +105,17 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, if (notifier->bound) { ret = notifier->bound(notifier, sd, asd); - if (ret < 0) + if (ret < 0) { + dev_warn(notifier->v4l2_dev->dev, "subdev bound failed\n"); return ret; + } } /* Move from the global subdevice list to notifier's done */ list_move(&sd->async_list, ¬ifier->done); ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd); if (ret < 0) { + dev_warn(notifier->v4l2_dev->dev, "subdev register failed\n"); if (notifier->unbind) notifier->unbind(notifier, sd, asd); return ret; @@ -146,7 +148,7 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, { struct v4l2_subdev *sd, *tmp; struct v4l2_async_subdev *asd; - int i; + int ret = 0, i; if (!notifier->num_subdevs || notifier->num_subdevs > V4L2_MAX_SUBDEVS) return -EINVAL; @@ -154,6 +156,7 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, notifier->v4l2_dev = v4l2_dev; INIT_LIST_HEAD(¬ifier->waiting); INIT_LIST_HEAD(¬ifier->done); + mutex_init(¬ifier->lock); for (i = 0; i < notifier->num_subdevs; i++) { asd = notifier->subdevs[i]; @@ -173,28 +176,22 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, list_add_tail(&asd->list, ¬ifier->waiting); } - mutex_lock(&list_lock); - /* Keep also completed notifiers on the list */ list_add(¬ifier->list, ¬ifier_list); + mutex_lock(¬ifier->lock); list_for_each_entry_safe(sd, tmp, &subdev_list, async_list) { - int ret; - asd = v4l2_async_belongs(notifier, sd); if (!asd) continue; ret = v4l2_async_test_notify(notifier, sd, asd); - if (ret < 0) { - mutex_unlock(&list_lock); - return ret; - } + if (ret < 0) + break; } + mutex_unlock(¬ifier->lock); - mutex_unlock(&list_lock); - - return 0; + return ret; } EXPORT_SYMBOL(v4l2_async_notifier_register); @@ -215,7 +212,7 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) "Failed to allocate device cache!\n"); } - mutex_lock(&list_lock); + mutex_lock(¬ifier->lock); list_del(¬ifier->list); @@ -242,7 +239,7 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) put_device(d); } - mutex_unlock(&list_lock); + mutex_unlock(¬ifier->lock); /* * Call device_attach() to reprobe devices @@ -267,6 +264,7 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) } kfree(dev); + mutex_destroy(¬ifier->lock); notifier->v4l2_dev = NULL; /* @@ -279,6 +277,7 @@ EXPORT_SYMBOL(v4l2_async_notifier_unregister); int v4l2_async_register_subdev(struct v4l2_subdev *sd) { struct v4l2_async_notifier *notifier; + struct v4l2_async_notifier *tmp; /* * No reference taken. The reference is held by the device @@ -288,24 +287,25 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) if (!sd->of_node && sd->dev) sd->of_node = sd->dev->of_node; - mutex_lock(&list_lock); - INIT_LIST_HEAD(&sd->async_list); - list_for_each_entry(notifier, ¬ifier_list, list) { - struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, sd); + list_for_each_entry_safe(notifier, tmp, ¬ifier_list, list) { + struct v4l2_async_subdev *asd; + + /* TODO: FIXME: if this is called by ->bound() we will also iterate over the locked notifier */ + mutex_lock_nested(¬ifier->lock, SINGLE_DEPTH_NESTING); + asd = v4l2_async_belongs(notifier, sd); if (asd) { int ret = v4l2_async_test_notify(notifier, sd, asd); - mutex_unlock(&list_lock); + mutex_unlock(¬ifier->lock); return ret; } + mutex_unlock(¬ifier->lock); } /* None matched, wait for hot-plugging */ list_add(&sd->async_list, &subdev_list); - mutex_unlock(&list_lock); - return 0; } EXPORT_SYMBOL(v4l2_async_register_subdev); @@ -320,7 +320,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) return; } - mutex_lock(&list_lock); + mutex_lock_nested(¬ifier->lock, SINGLE_DEPTH_NESTING); list_add(&sd->asd->list, ¬ifier->waiting); @@ -329,6 +329,6 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) if (notifier->unbind) notifier->unbind(notifier, sd, sd->asd); - mutex_unlock(&list_lock); + mutex_unlock(¬ifier->lock); } EXPORT_SYMBOL(v4l2_async_unregister_subdev); diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 1d6d7da..d2178c1 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -71,6 +71,7 @@ struct v4l2_async_subdev { * @waiting: list of struct v4l2_async_subdev, waiting for their drivers * @done: list of struct v4l2_subdev, already probed * @list: member in a global list of notifiers + * @lock: lock hold when the notifier is being processed * @bound: a subdevice driver has successfully probed one of subdevices * @complete: all subdevices have been probed successfully * @unbind: a subdevice is leaving @@ -82,6 +83,7 @@ struct v4l2_async_notifier { struct list_head waiting; struct list_head done; struct list_head list; + struct mutex lock; int (*bound)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd);