From patchwork Wed Apr 23 22:57:41 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 4045031 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 628B39F387 for ; Wed, 23 Apr 2014 23:00:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5CD2B20260 for ; Wed, 23 Apr 2014 23:00:30 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5C4F120295 for ; Wed, 23 Apr 2014 23:00:29 +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 1Wd67c-0003Gx-0n; Wed, 23 Apr 2014 22:58:32 +0000 Received: from mail-oa0-x22d.google.com ([2607:f8b0:4003:c02::22d]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wd67V-00039Q-P5 for linux-arm-kernel@lists.infradead.org; Wed, 23 Apr 2014 22:58:26 +0000 Received: by mail-oa0-f45.google.com with SMTP id eb12so1794957oac.18 for ; Wed, 23 Apr 2014 15:58:02 -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=sE/uL7vtJLv+FegS7wDXDHtVQ4mRKIQuyGCt8OaONCU=; b=JvQJZnKy5Vq8LwXbNTzHc9Qz6B+mpxjGNlka+owmEOAbfp7Wib48tuHF/L6XgbwFB6 j2hH03uh0HFoeXN/TkWhTqaFDvXbsk7eWsdI5doQfPETqWX8AwgbnunOta5I46pesUFD jomCf30/3WN/1lDPZ88LfeHpZQKhduPc3w+USU5/Iv9Dxz2eW9G2v7vrCC1VpkPHmMYB nJSJft/v9ICSWYZDoN2Pl8p1mubTVcm55JGOZWOf6gWPv1M4dVjSi145Fhu30boAoK93 P9lhXXPKAx4mpM5FT9Orz7tOTjEnwwZXUhd4CX+i6HswMmSmO4Bar30dej7xGlYk84nj At/Q== X-Received: by 10.182.81.39 with SMTP id w7mr9928491obx.56.1398293882367; Wed, 23 Apr 2014 15:58:02 -0700 (PDT) Received: from localhost.localdomain (72-48-77-163.dyn.grandenetworks.net. [72.48.77.163]) by mx.google.com with ESMTPSA id cq1sm9577790oeb.4.2014.04.23.15.58.01 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 23 Apr 2014 15:58:01 -0700 (PDT) From: Rob Herring To: Russell King , Tony Lindgren , Grant Likely , Greg Kroah-Hartman Subject: [PATCH 2/2] of/irq: do irq resolution in platform_get_irq Date: Wed, 23 Apr 2014 17:57:41 -0500 Message-Id: <1398293861-7682-3-git-send-email-robherring2@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1398293861-7682-1-git-send-email-robherring2@gmail.com> References: <1398293861-7682-1-git-send-email-robherring2@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140423_155825_933084_7149DE9F X-CRM114-Status: GOOD ( 20.64 ) X-Spam-Score: 0.1 (/) Cc: devicetree@vger.kernel.org, Jean-Jacques Hiblot , Rob Herring , linux-kernel@vger.kernel.org, thierry.reding@gmail.com, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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=-2.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, 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 From: Rob Herring Currently we get the following kind of errors if we try to use interrupt phandles to irqchips that have not yet initialized: irq: no irq domain found for /ocp/pinmux@48002030 ! ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at drivers/of/platform.c:171 of_device_alloc+0x144/0x184() Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.12.0-00038-g42a9708 #1012 (show_stack+0x14/0x1c) (dump_stack+0x6c/0xa0) (warn_slowpath_common+0x64/0x84) (warn_slowpath_null+0x1c/0x24) (of_device_alloc+0x144/0x184) (of_platform_device_create_pdata+0x44/0x9c) (of_platform_bus_create+0xd0/0x170) (of_platform_bus_create+0x12c/0x170) (of_platform_populate+0x60/0x98) This is because we're wrongly trying to populate resources that are not yet available. It's perfectly valid to create irqchips dynamically, so let's fix up the issue by resolving the interrupt resources when platform_get_irq is called. And then we also need to accept the fact that some irqdomains do not exist that early on, and only get initialized later on. So we can make the current WARN_ON into just into a pr_debug(). We still attempt to populate irq resources when we create the devices. This allows current drivers which don't use platform_get_irq to continue to function. Once all drivers are fixed, this code can be removed. Suggested-by: Russell King Signed-off-by: Rob Herring Signed-off-by: Tony Lindgren Tested-by: Tony Lindgren --- drivers/base/platform.c | 7 ++++++- drivers/of/irq.c | 26 ++++++++++++++++++++++++++ drivers/of/platform.c | 4 +++- include/linux/of_irq.h | 7 ++++++- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index e714709..5b47210 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -87,7 +88,11 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) return -ENXIO; return dev->archdata.irqs[num]; #else - struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); + struct resource *r; + if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) + return of_irq_get(dev->dev.of_node, num); + + r = platform_get_resource(dev, IORESOURCE_IRQ, num); return r ? r->start : -ENXIO; #endif diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 9bcf2cf..ca01893 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -380,6 +380,32 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) EXPORT_SYMBOL_GPL(of_irq_to_resource); /** + * of_irq_get - Decode a node's IRQ and return it as a Linux irq number + * @dev: pointer to device tree node + * @index: zero-based index of the irq + * + * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain + * is not yet created. + * + */ +int of_irq_get(struct device_node *dev, int index) +{ + int rc; + struct of_phandle_args oirq; + struct irq_domain *domain; + + rc = of_irq_parse_one(dev, index, &oirq); + if (rc) + return rc; + + domain = irq_find_host(oirq.np); + if (!domain) + return -EPROBE_DEFER; + + return irq_create_of_mapping(&oirq); +} + +/** * of_irq_count - Count the number of IRQs a node uses * @dev: pointer to device tree node */ diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 404d1da..bd47fbc 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -168,7 +168,9 @@ struct platform_device *of_device_alloc(struct device_node *np, rc = of_address_to_resource(np, i, res); WARN_ON(rc); } - WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq); + if (of_irq_to_resource_table(np, res, num_irq) != num_irq) + pr_debug("not all legacy IRQ resources mapped for %s\n", + np->name); } dev->dev.of_node = of_node_get(np); diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index 3f23b44..bc9e51a 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -34,21 +34,26 @@ static inline int of_irq_parse_oldworld(struct device_node *device, int index, extern int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq); extern int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq); -extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data); extern int of_irq_to_resource(struct device_node *dev, int index, struct resource *r); extern int of_irq_to_resource_table(struct device_node *dev, struct resource *res, int nr_irqs); +extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data); extern void of_irq_init(const struct of_device_id *matches); #ifdef CONFIG_OF_IRQ extern int of_irq_count(struct device_node *dev); +extern int of_irq_get(struct device_node *dev, int index); #else static inline int of_irq_count(struct device_node *dev) { return 0; } +static inline int of_irq_get(struct device_node *dev, int index) +{ + return 0; +} #endif #if defined(CONFIG_OF)