From patchwork Sat Nov 15 14:24:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 5312011 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 57D619F2ED for ; Sat, 15 Nov 2014 14:25:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6F36A2017D for ; Sat, 15 Nov 2014 14:25:38 +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 85DAF20176 for ; Sat, 15 Nov 2014 14:25:37 +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 1XpeGH-0002UW-R6; Sat, 15 Nov 2014 14:23:37 +0000 Received: from mga11.intel.com ([192.55.52.93]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XpeEd-0001S2-2P for linux-arm-kernel@lists.infradead.org; Sat, 15 Nov 2014 14:21:56 +0000 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP; 15 Nov 2014 06:21:30 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,391,1413270000"; d="scan'208";a="632446322" Received: from gerry-dev.bj.intel.com ([10.238.158.52]) by fmsmga002.fm.intel.com with ESMTP; 15 Nov 2014 06:20:58 -0800 From: Jiang Liu To: Bjorn Helgaas , Thomas Gleixner , Ingo Molnar , Grant Likely , Marc Zyngier , Yijing Wang , Yingjoe Chen , Borislav Petkov , "H. Peter Anvin" , Benjamin Herrenschmidt , Matthias Brugger Subject: [Patch V2 3/9] irqdomain: Implement a method to automatically call parent domain's alloc/free Date: Sat, 15 Nov 2014 22:24:01 +0800 Message-Id: <1416061447-9472-4-git-send-email-jiang.liu@linux.intel.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1416061447-9472-1-git-send-email-jiang.liu@linux.intel.com> References: <1416061447-9472-1-git-send-email-jiang.liu@linux.intel.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20141115_062155_805325_C87D895E X-CRM114-Status: GOOD ( 16.24 ) X-Spam-Score: -5.0 (-----) Cc: linux-pci@vger.kernel.org, Tony Luck , Jiang Liu , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 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.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, 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 Add a flags to irq_domain.flags to control whether the irqdomain core should automatically call parent irqdomain's alloc/free callbacks. It help to reduce hierarchy irqdomains users' code size. Signed-off-by: Jiang Liu --- include/linux/irqdomain.h | 24 ++++++----------- kernel/irq/irqdomain.c | 66 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 18 deletions(-) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index fbe542967c20..ad92b0b15945 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -130,6 +130,8 @@ struct irq_domain { }; #define IRQ_DOMAIN_FLAG_HIERARCHY 0x1 +/* Framework automatically calls parent domain's alloc()/free() */ +#define IRQ_DOMAIN_FLAG_AUTO_RECURSIVE 0x2 #define IRQ_DOMAIN_FLAG_ARCH1 0x10000 #ifdef CONFIG_IRQ_DOMAIN @@ -274,22 +276,12 @@ extern void irq_domain_free_irqs_common(struct irq_domain *domain, unsigned int nr_irqs); extern void irq_domain_free_irqs_top(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs); - -static inline int irq_domain_alloc_irqs_parent(struct irq_domain *domain, - unsigned int irq_base, unsigned int nr_irqs, void *arg) -{ - if (domain->parent && domain->parent->ops->alloc) - return domain->parent->ops->alloc(domain->parent, irq_base, - nr_irqs, arg); - return -ENOSYS; -} - -static inline void irq_domain_free_irqs_parent(struct irq_domain *domain, - unsigned int irq_base, unsigned int nr_irqs) -{ - if (domain->parent && domain->parent->ops->free) - domain->parent->ops->free(domain->parent, irq_base, nr_irqs); -} +extern int irq_domain_alloc_irqs_parent(struct irq_domain *domain, + unsigned int irq_base, + unsigned int nr_irqs, void *arg); +extern void irq_domain_free_irqs_parent(struct irq_domain *domain, + unsigned int irq_base, + unsigned int nr_irqs); static inline bool irq_domain_is_hierarchy(struct irq_domain *domain) { diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 705fb573e509..03fc7d018324 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -925,6 +925,43 @@ void irq_domain_free_irqs_top(struct irq_domain *domain, unsigned int virq, irq_domain_free_irqs_common(domain, virq, nr_irqs); } +static bool irq_domain_is_auto_recursive(struct irq_domain *domain) +{ + return domain->flags & IRQ_DOMAIN_FLAG_AUTO_RECURSIVE; +} + +static void irq_domain_free_irqs_recursive(struct irq_domain *domain, + unsigned int irq_base, + unsigned int nr_irqs) +{ + domain->ops->free(domain, irq_base, nr_irqs); + if (irq_domain_is_auto_recursive(domain)) { + BUG_ON(!domain->parent); + irq_domain_free_irqs_recursive(domain->parent, irq_base, + nr_irqs); + } +} + +static int irq_domain_alloc_irqs_recursive(struct irq_domain *domain, + unsigned int irq_base, + unsigned int nr_irqs, void *arg) +{ + int ret = 0; + struct irq_domain *parent = domain->parent; + bool recursive = irq_domain_is_auto_recursive(domain); + + BUG_ON(recursive && !parent); + if (recursive) + ret = irq_domain_alloc_irqs_recursive(parent, irq_base, + nr_irqs, arg); + if (ret >= 0) + ret = domain->ops->alloc(domain, irq_base, nr_irqs, arg); + if (ret < 0 && recursive) + irq_domain_free_irqs_recursive(parent, irq_base, nr_irqs); + + return ret; +} + /** * __irq_domain_alloc_irqs - Allocate IRQs from domain * @domain: domain to allocate from @@ -981,7 +1018,7 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base, } mutex_lock(&irq_domain_mutex); - ret = domain->ops->alloc(domain, virq, nr_irqs, arg); + ret = irq_domain_alloc_irqs_recursive(domain, virq, nr_irqs, arg); if (ret < 0) { mutex_unlock(&irq_domain_mutex); goto out_free_irq_data; @@ -1016,13 +1053,38 @@ void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs) mutex_lock(&irq_domain_mutex); for (i = 0; i < nr_irqs; i++) irq_domain_remove_irq(virq + i); - data->domain->ops->free(data->domain, virq, nr_irqs); + irq_domain_free_irqs_recursive(data->domain, virq, nr_irqs); mutex_unlock(&irq_domain_mutex); irq_domain_free_irq_data(virq, nr_irqs); irq_free_descs(virq, nr_irqs); } +int irq_domain_alloc_irqs_parent(struct irq_domain *domain, + unsigned int irq_base, unsigned int nr_irqs, + void *arg) +{ + /* irq_domain_alloc_irqs_recursive() has called parent's alloc() */ + if (irq_domain_is_auto_recursive(domain)) + return 0; + + domain = domain->parent; + if (domain) + return irq_domain_alloc_irqs_recursive(domain, irq_base, + nr_irqs, arg); + + return -ENOSYS; +} + +void irq_domain_free_irqs_parent(struct irq_domain *domain, + unsigned int irq_base, unsigned int nr_irqs) +{ + /* irq_domain_free_irqs_recursive() will call parent's free */ + if (!irq_domain_is_auto_recursive(domain)) + irq_domain_free_irqs_recursive(domain->parent, irq_base, + nr_irqs); +} + /** * irq_domain_activate_irq - Call domain_ops->activate recursively to activate * interrupt