From patchwork Mon Sep 7 12:23:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomeu Vizoso X-Patchwork-Id: 7134881 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 B6D80BEEC1 for ; Mon, 7 Sep 2015 12:48:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CE6D4206CB for ; Mon, 7 Sep 2015 12:48:47 +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 D4D02206D4 for ; Mon, 7 Sep 2015 12:48:46 +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 1ZYvoy-0003d1-Ou; Mon, 07 Sep 2015 12:46:52 +0000 Received: from merlin.infradead.org ([2001:4978:20e::2]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZYvoM-000349-IJ for linux-arm-kernel@bombadil.infradead.org; Mon, 07 Sep 2015 12:46:14 +0000 Received: from mail-wi0-x229.google.com ([2a00:1450:400c:c05::229]) by merlin.infradead.org with esmtps (Exim 4.85 #2 (Red Hat Linux)) id 1ZYvTW-000524-Jh for linux-arm-kernel@lists.infradead.org; Mon, 07 Sep 2015 12:24:44 +0000 Received: by wiclk2 with SMTP id lk2so82441355wic.1 for ; Mon, 07 Sep 2015 05:24:13 -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=4rgev4m8rdmrtXsa0GaUVCEuZNrs9qWf3QjB6pQPeOM=; b=I8uW+DiYzvf8gOT9tXCv//8XhG6YOsajX9lrzFtQowZJNQO1lhxb8g1k1L+xDh7Nq6 XcPobHyWl26zdF109u3VAoq8TcFxTlgJhLUiEJIOZNVmTEmna0IR1d3bmMGOxhD6XAO9 eS1YntPSf+9JRzXjaVFY+yD0Kmrdf9GA7jZUVL15sNV1VqpUCs1cZNTwhlVbQAjF8d9W nD9ipctHwIJIythfefbkdv6qTG8+NtqngdHihfcVpDF+DhUUKnvBLqzPxS4NoefHzZJq WJEHkLh8TVF4SOQHRd/WCKMRgTpf0P7P4chjsmdFYMklwP8NpGSu94yZhnz9xf3S9W84 UaNg== X-Received: by 10.194.77.104 with SMTP id r8mr22746257wjw.102.1441628653517; Mon, 07 Sep 2015 05:24:13 -0700 (PDT) Received: from cizrna.lan ([109.72.12.78]) by smtp.gmail.com with ESMTPSA id cm6sm15438wib.22.2015.09.07.05.24.12 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Sep 2015 05:24:12 -0700 (PDT) From: Tomeu Vizoso To: linux-kernel@vger.kernel.org Subject: [PATCH v4 04/22] of: add function to allow probing a device from a OF node Date: Mon, 7 Sep 2015 14:23:29 +0200 Message-Id: <1441628627-5143-5-git-send-email-tomeu.vizoso@collabora.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1441628627-5143-1-git-send-email-tomeu.vizoso@collabora.com> References: <1441628627-5143-1-git-send-email-tomeu.vizoso@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150907_082442_949239_838042F1 X-CRM114-Status: GOOD ( 24.48 ) X-Spam-Score: -2.4 (--) 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 , Linus Walleij , Dmitry Torokhov , "Rafael J. Wysocki" , Rob Herring , Javier Martinez Canillas , Mark Brown , Thierry Reding , Grant Likely , Frank Rowand , 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 Walks the OF tree up and finds the closest ancestor that has a struct device associated with it, probing it if isn't bound to a driver yet. The above should ensure that the dependency represented by the passed OF node is available, because probing a device should cause its descendants to be probed as well (when they get registered). Subsystems can use this when looking up resources for drivers, to reduce the chances of deferred probes because of the probing order of devices. Signed-off-by: Tomeu Vizoso --- Changes in v4: - Rename of_platform_probe to of_device_probe - Use device_node.device instead of device_node.platform_dev Changes in v3: - Set and use device_node.platform_dev instead of reversing the logic to find the platform device that encloses a device node. - Drop the fwnode API to probe firmware nodes and add OF-only API for now. I think this same scheme could be used for machines with ACPI, but I haven't been able to find one that had to defer its probes because of the device probe order. Changes in v2: None drivers/of/device.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/of/platform.c | 2 ++ include/linux/of_device.h | 3 +++ 3 files changed, 63 insertions(+) diff --git a/drivers/of/device.c b/drivers/of/device.c index 8b91ea241b10..c32ac7b6fbe2 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -286,3 +286,61 @@ int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) return 0; } + +/** + * of_device_probe() - Probe device associated with OF node + * @np: node to probe + * + * Probe the device associated with the passed device node. + */ +void of_device_probe(struct device_node *np) +{ + struct device_node *target; + struct device *dev = NULL; + + if (!of_root || !of_node_check_flag(of_root, OF_POPULATED_BUS)) + return; + + if (!np) + return; + + of_node_get(np); + + /* Find the closest ancestor that has a device associated */ + for (target = np; + !of_node_is_root(target); + target = of_get_next_parent(target)) + if (target->device) { + dev = target->device; + break; + } + + of_node_put(target); + + if (!dev) { + pr_warn("Couldn't find a device for node '%s'\n", + of_node_full_name(np)); + return; + } + + /* + * Device is bound or is being probed right now. If we have bad luck + * and the dependency isn't ready when it's needed, deferred probe + * will save us. + */ + if (dev->driver) + return; + + /* + * Probing a device should cause its descendants to be probed as + * well, which includes the passed device node. + */ + if (device_attach(dev) != 1) + /* + * This cannot be a warning for now because clock nodes have a + * compatible string but the clock framework doesn't follow + * the device/driver model yet. + */ + dev_dbg(dev, "Probe failed for %s\n", of_node_full_name(np)); +} +EXPORT_SYMBOL_GPL(of_device_probe); diff --git a/drivers/of/platform.c b/drivers/of/platform.c index baf04d7249bd..f089d95ac961 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -269,6 +269,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node, goto err_free; } + node->device = &dev->dev; + return dev; err_free: diff --git a/include/linux/of_device.h b/include/linux/of_device.h index cc7dd687a89d..da8d489e73ad 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -40,6 +40,7 @@ extern ssize_t of_device_get_modalias(struct device *dev, extern void of_device_uevent(struct device *dev, struct kobj_uevent_env *env); extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env); +extern void of_device_probe(struct device_node *np); static inline void of_device_node_put(struct device *dev) { @@ -84,6 +85,8 @@ static inline int of_device_uevent_modalias(struct device *dev, return -ENODEV; } +static inline void of_device_probe(struct device_node *np) { } + static inline void of_device_node_put(struct device *dev) { } static inline const struct of_device_id *__of_match_device(