From patchwork Thu Sep 17 12:56:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomeu Vizoso X-Patchwork-Id: 7207201 Return-Path: X-Original-To: patchwork-linux-arm@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 0C2F5BEEC1 for ; Thu, 17 Sep 2015 13:11:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1385020852 for ; Thu, 17 Sep 2015 13:11:29 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1CF8D2084B for ; Thu, 17 Sep 2015 13:11:28 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZcYwk-00079F-JC; Thu, 17 Sep 2015 13:09:54 +0000 Received: from mail-wi0-x22f.google.com ([2a00:1450:400c:c05::22f]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZcYlD-0006iT-Ov for linux-arm-kernel@lists.infradead.org; Thu, 17 Sep 2015 12:58:00 +0000 Received: by wicgb1 with SMTP id gb1so116780314wic.1 for ; Thu, 17 Sep 2015 05:57:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=F9EkZlcM5yPN4lEmFLFlJ6J+b6zTqHLUanYKP+4D67g=; b=VVrJx0BKvcoF9LW8XkzNKme2nprjJEaiNTul4OqVovG/rTu7GqLj/nWvpS+ed6D1gu yYowdDI2v3ctVUBI8gWZ1Cd2W6ZXAOlMT69cE/U8dxQEfz6x+C5TK1wpBSTNpdcqOZnr TN1n6hqrEYnwQ44uSSbEK+q/ULtAy4pStGga/W8zgpFGcLQ2HiZoG5UunmITTiMNYYGB av175ILSeNFATSiGfQx+pZddddoPb1DPKhK2kqnVQzAAZ1d4vmivMebf0ZDiCRoMsH42 3YTn/iERi35dPdDvtvuckA6dKDML/w+HBdBcDWpybjAgQtx1HnG/7OOKn1gCpZNkc1iY /2Kw== X-Received: by 10.180.10.170 with SMTP id j10mr30364883wib.77.1442494661937; Thu, 17 Sep 2015 05:57:41 -0700 (PDT) Received: from cizrna.lan ([109.72.12.203]) by smtp.gmail.com with ESMTPSA id jr5sm2203032wjc.26.2015.09.17.05.57.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2015 05:57:40 -0700 (PDT) From: Tomeu Vizoso To: linux-kernel@vger.kernel.org Subject: [PATCH v5 01/23] driver core: Add pre_probe callback to bus_type Date: Thu, 17 Sep 2015 14:56:55 +0200 Message-Id: <1442494637-3674-2-git-send-email-tomeu.vizoso@collabora.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1442494637-3674-1-git-send-email-tomeu.vizoso@collabora.com> References: <1442494637-3674-1-git-send-email-tomeu.vizoso@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150917_055800_043864_EBF96381 X-CRM114-Status: GOOD ( 20.35 ) X-Spam-Score: -2.6 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tomeu Vizoso , devicetree@vger.kernel.org, linux-acpi@vger.kernel.org, Arnd Bergmann , Stephen Warren , Greg Kroah-Hartman , Linus Walleij , Dmitry Torokhov , "Rafael J. Wysocki" , Rob Herring , Javier Martinez Canillas , Mark Brown , Thierry Reding , Alan Stern , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_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 Some buses (eg. AMBA) need access to some HW resources (it may need a clock to be enabled so a device ID can be read) before a device can be matched to a driver. The pre_probe callback allows the device-driver core to request the bus to perform this initialization and can defer the probe if any of the resources needed are missing. This gives us more flexibility when setting the order in which devices are probed because the resources needed to get the matching information don't need to be available by the time that the bus devices are registered. Signed-off-by: Tomeu Vizoso --- Changes in v5: - Reduce some code duplication by adding device_pre_probe() - Print a warning if pre_probe() returns an error Changes in v4: None Changes in v3: None Changes in v2: None drivers/base/dd.c | 39 +++++++++++++++++++++++++++++++++++++++ include/linux/device.h | 4 ++++ 2 files changed, 43 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index be0eb4639128..5caa8478404d 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -539,6 +539,37 @@ static void __device_attach_async_helper(void *_dev, async_cookie_t cookie) put_device(dev); } +/** + * device_pre_probe - perform initializations before a device can be matched + * @dev: device. + * + * Call the pre_probe() callback in the bus, if any, to give it a chance to + * perform any initializations needed before the device can be matched to a + * driver (for example, read a device id from a register). + * + * Returns 1 if the operation was successful or there's no pre_probe callback + * 0 if an error happened and the device isn't ready to be matched to a driver + */ +static int device_pre_probe(struct device *dev) +{ + int ret; + + if (!dev->bus || !dev->bus->pre_probe) + return 1; + + ret = dev->bus->pre_probe(dev); + if (ret) { + if (ret == -EPROBE_DEFER) + driver_deferred_probe_add(dev); + else + dev_warn(dev, "pre-probe failed: %d\n", ret); + + return 0; + } + + return 1; +} + static int __device_attach(struct device *dev, bool allow_async) { int ret = 0; @@ -566,6 +597,11 @@ static int __device_attach(struct device *dev, bool allow_async) if (dev->parent) pm_runtime_get_sync(dev->parent); + if (!device_pre_probe(dev)) { + ret = 0; + goto out_unlock; + } + ret = bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver); if (!ret && allow_async && data.have_async) { @@ -630,6 +666,9 @@ static int __driver_attach(struct device *dev, void *data) * is an error. */ + if (!device_pre_probe(dev)) + return 0; + if (!driver_match_device(drv, dev)) return 0; diff --git a/include/linux/device.h b/include/linux/device.h index 5d7bc6349930..d8be07bc9c3f 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -74,6 +74,9 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); * given device can be handled by the given driver. * @uevent: Called when a device is added, removed, or a few other things * that generate uevents to add the environment variables. + * @pre_probe: Called when a new device or driver is added to this bus, to + * perform any initializations that are needed so the device can + * be matched to a driver. * @probe: Called when a new device or driver add to this bus, and callback * the specific driver's probe to initial the matched device. * @remove: Called when a device removed from this bus. @@ -113,6 +116,7 @@ struct bus_type { int (*match)(struct device *dev, struct device_driver *drv); int (*uevent)(struct device *dev, struct kobj_uevent_env *env); + int (*pre_probe)(struct device *dev); int (*probe)(struct device *dev); int (*remove)(struct device *dev); void (*shutdown)(struct device *dev);