From patchwork Thu Aug 6 14:11:39 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomeu Vizoso X-Patchwork-Id: 6959551 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 C716AC05AD for ; Thu, 6 Aug 2015 14:21:41 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7896F206FD for ; Thu, 6 Aug 2015 14:21:40 +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 4D6602066E for ; Thu, 6 Aug 2015 14:21:39 +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 1ZNM1N-0003Ab-Rj; Thu, 06 Aug 2015 14:19:49 +0000 Received: from mail-wi0-x232.google.com ([2a00:1450:400c:c05::232]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZNM0o-0002pV-0g for linux-arm-kernel@lists.infradead.org; Thu, 06 Aug 2015 14:19:18 +0000 Received: by wijp15 with SMTP id p15so24627077wij.0 for ; Thu, 06 Aug 2015 07:18:51 -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=udYkoqbHELBNXqaxupHeT/5CbEGR+bb+64yerv8Wx9A=; b=yUEEEqsdtFuqAM2Ez5ADcadU4lQvij7GS/O8GKm6HbpIYI0+Z0gCachhFP7PyvA40A uqvNQOp5IZe2dN1SqtYcuLZLEwaVMSh4aie9kH48OfsxgXcG0GzwNh2naFBycONVOZx/ zjPrYI4fJGfBssjrrjdiQdZxgAYtgfDaJPklTrsCN1kUpVgzjLFIQk7rYXQFhMiibHAN sMehMyQVSeWjnuh5Xsooo8xrjMtc1NoTuVGFjZl28ctrLIXVxV2LhGpUdChcErF08TN5 BFR7AuYGUgTR/tD///eO8htWpweA3Pn+szyNQA5SqL8fFywEUVoJE7gbGv09kU9l+ykH tyPA== X-Received: by 10.180.20.198 with SMTP id p6mr6988532wie.38.1438870731150; Thu, 06 Aug 2015 07:18:51 -0700 (PDT) Received: from cizrna.lan ([109.72.12.154]) by smtp.gmail.com with ESMTPSA id z5sm9727282wjr.42.2015.08.06.07.18.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Aug 2015 07:18:50 -0700 (PDT) From: Tomeu Vizoso To: linux-kernel@vger.kernel.org Subject: [PATCH v3 02/18] of/platform: add of_platform_probe Date: Thu, 6 Aug 2015 16:11:39 +0200 Message-Id: <1438870315-18689-3-git-send-email-tomeu.vizoso@collabora.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1438870315-18689-1-git-send-email-tomeu.vizoso@collabora.com> References: <1438870315-18689-1-git-send-email-tomeu.vizoso@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150806_071914_341724_86CF51EE X-CRM114-Status: GOOD ( 21.41 ) 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 , 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.2 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,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 platform 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 platform device should cause its descendants to be probed as well. Subsystems can use this when looking up resources for drivers, to reduce the chances of deferred probes because of the probing order of devices. Also adds a platform_dev member to struct device_node, pointing to the platform device that was registered based on that node, if any. Signed-off-by: Tomeu Vizoso --- 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/platform.c | 61 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/of.h | 1 + include/linux/of_platform.h | 2 ++ 3 files changed, 64 insertions(+) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 8a002d6151f2..a1930c0d1fee 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -192,6 +192,8 @@ static struct platform_device *of_platform_device_create_pdata( goto err_clear_flag; } + np->platform_dev = dev; + return dev; err_clear_flag: @@ -501,6 +503,65 @@ void of_platform_depopulate(struct device *parent) } EXPORT_SYMBOL_GPL(of_platform_depopulate); +/** + * of_platform_probe() - Probe platform device associated with OF node + * @np: node to probe + * + * Walks the OF tree up and finds the closest ancestor that has a platform + * 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 platform device should cause its + * descendants to be probed as well. + */ +void of_platform_probe(struct device_node *np) +{ + struct device_node *target; + struct platform_device *pdev = NULL; + + if (!of_root || !of_node_check_flag(of_root, OF_POPULATED_BUS)) + return; + + if (!np) + return; + + of_node_get(np); + + for (target = np; + !of_node_is_root(target); + target = of_get_next_parent(target)) + if (target->platform_dev) { + pdev = target->platform_dev; + break; + } + + of_node_put(target); + + if (!pdev) { + pr_warn("Couldn't find a platform 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 (pdev->dev.driver) + return; + + if (device_attach(&pdev->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. + */ + pr_debug("Probe failed for %s (%s)\n", of_node_full_name(np), + dev_name(&pdev->dev)); +} +EXPORT_SYMBOL_GPL(of_platform_probe); + #ifdef CONFIG_OF_DYNAMIC static int of_platform_notify(struct notifier_block *nb, unsigned long action, void *arg) diff --git a/include/linux/of.h b/include/linux/of.h index edc068d19c79..2ace86a5fa2d 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -52,6 +52,7 @@ struct device_node { phandle phandle; const char *full_name; struct fwnode_handle fwnode; + struct platform_device *platform_dev; struct property *properties; struct property *deadprops; /* removed properties */ diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 611a691145c4..91ca92c7c061 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -73,6 +73,7 @@ extern int of_platform_populate(struct device_node *root, const struct of_dev_auxdata *lookup, struct device *parent); extern void of_platform_depopulate(struct device *parent); +extern void of_platform_probe(struct device_node *np); #else static inline int of_platform_populate(struct device_node *root, const struct of_device_id *matches, @@ -82,6 +83,7 @@ static inline int of_platform_populate(struct device_node *root, return -ENODEV; } static inline void of_platform_depopulate(struct device *parent) { } +static inline void of_platform_probe(struct device_node *np) { } #endif #if defined(CONFIG_OF_DYNAMIC) && defined(CONFIG_OF_ADDRESS)