aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-11-15 09:24:01 -0500
committerThomas Gleixner <tglx@linutronix.de>2014-11-23 07:01:46 -0500
commit36d727310cb9f85efb5ac089ffb1797e7c3538e1 (patch)
treee58639a6b10598f89db6adc66b03145ab1841f45 /kernel/irq
parent1b5377087cb4e68d719a875120894fddfbcbf0f9 (diff)
irqdomain: Implement a method to automatically call parent domains alloc/free
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 <jiang.liu@linux.intel.com> Cc: Tony Luck <tony.luck@intel.com> Cc: linux-arm-kernel@lists.infradead.org Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Grant Likely <grant.likely@linaro.org> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Yijing Wang <wangyijing@huawei.com> Cc: Yingjoe Chen <yingjoe.chen@mediatek.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Matthias Brugger <matthias.bgg@gmail.com> Link: http://lkml.kernel.org/r/1416061447-9472-4-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/irqdomain.c82
1 files changed, 80 insertions, 2 deletions
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 4e62832ace82..9c88db7056d4 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -960,6 +960,43 @@ void irq_domain_free_irqs_top(struct irq_domain *domain, unsigned int virq,
960 irq_domain_free_irqs_common(domain, virq, nr_irqs); 960 irq_domain_free_irqs_common(domain, virq, nr_irqs);
961} 961}
962 962
963static bool irq_domain_is_auto_recursive(struct irq_domain *domain)
964{
965 return domain->flags & IRQ_DOMAIN_FLAG_AUTO_RECURSIVE;
966}
967
968static void irq_domain_free_irqs_recursive(struct irq_domain *domain,
969 unsigned int irq_base,
970 unsigned int nr_irqs)
971{
972 domain->ops->free(domain, irq_base, nr_irqs);
973 if (irq_domain_is_auto_recursive(domain)) {
974 BUG_ON(!domain->parent);
975 irq_domain_free_irqs_recursive(domain->parent, irq_base,
976 nr_irqs);
977 }
978}
979
980static int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
981 unsigned int irq_base,
982 unsigned int nr_irqs, void *arg)
983{
984 int ret = 0;
985 struct irq_domain *parent = domain->parent;
986 bool recursive = irq_domain_is_auto_recursive(domain);
987
988 BUG_ON(recursive && !parent);
989 if (recursive)
990 ret = irq_domain_alloc_irqs_recursive(parent, irq_base,
991 nr_irqs, arg);
992 if (ret >= 0)
993 ret = domain->ops->alloc(domain, irq_base, nr_irqs, arg);
994 if (ret < 0 && recursive)
995 irq_domain_free_irqs_recursive(parent, irq_base, nr_irqs);
996
997 return ret;
998}
999
963/** 1000/**
964 * __irq_domain_alloc_irqs - Allocate IRQs from domain 1001 * __irq_domain_alloc_irqs - Allocate IRQs from domain
965 * @domain: domain to allocate from 1002 * @domain: domain to allocate from
@@ -1016,7 +1053,7 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
1016 } 1053 }
1017 1054
1018 mutex_lock(&irq_domain_mutex); 1055 mutex_lock(&irq_domain_mutex);
1019 ret = domain->ops->alloc(domain, virq, nr_irqs, arg); 1056 ret = irq_domain_alloc_irqs_recursive(domain, virq, nr_irqs, arg);
1020 if (ret < 0) { 1057 if (ret < 0) {
1021 mutex_unlock(&irq_domain_mutex); 1058 mutex_unlock(&irq_domain_mutex);
1022 goto out_free_irq_data; 1059 goto out_free_irq_data;
@@ -1051,7 +1088,7 @@ void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs)
1051 mutex_lock(&irq_domain_mutex); 1088 mutex_lock(&irq_domain_mutex);
1052 for (i = 0; i < nr_irqs; i++) 1089 for (i = 0; i < nr_irqs; i++)
1053 irq_domain_remove_irq(virq + i); 1090 irq_domain_remove_irq(virq + i);
1054 data->domain->ops->free(data->domain, virq, nr_irqs); 1091 irq_domain_free_irqs_recursive(data->domain, virq, nr_irqs);
1055 mutex_unlock(&irq_domain_mutex); 1092 mutex_unlock(&irq_domain_mutex);
1056 1093
1057 irq_domain_free_irq_data(virq, nr_irqs); 1094 irq_domain_free_irq_data(virq, nr_irqs);
@@ -1059,6 +1096,47 @@ void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs)
1059} 1096}
1060 1097
1061/** 1098/**
1099 * irq_domain_alloc_irqs_parent - Allocate interrupts from parent domain
1100 * @irq_base: Base IRQ number
1101 * @nr_irqs: Number of IRQs to allocate
1102 * @arg: Allocation data (arch/domain specific)
1103 *
1104 * Check whether the domain has been setup recursive. If not allocate
1105 * through the parent domain.
1106 */
1107int irq_domain_alloc_irqs_parent(struct irq_domain *domain,
1108 unsigned int irq_base, unsigned int nr_irqs,
1109 void *arg)
1110{
1111 /* irq_domain_alloc_irqs_recursive() has called parent's alloc() */
1112 if (irq_domain_is_auto_recursive(domain))
1113 return 0;
1114
1115 domain = domain->parent;
1116 if (domain)
1117 return irq_domain_alloc_irqs_recursive(domain, irq_base,
1118 nr_irqs, arg);
1119 return -ENOSYS;
1120}
1121
1122/**
1123 * irq_domain_free_irqs_parent - Free interrupts from parent domain
1124 * @irq_base: Base IRQ number
1125 * @nr_irqs: Number of IRQs to free
1126 *
1127 * Check whether the domain has been setup recursive. If not free
1128 * through the parent domain.
1129 */
1130void irq_domain_free_irqs_parent(struct irq_domain *domain,
1131 unsigned int irq_base, unsigned int nr_irqs)
1132{
1133 /* irq_domain_free_irqs_recursive() will call parent's free */
1134 if (!irq_domain_is_auto_recursive(domain) && domain->parent)
1135 irq_domain_free_irqs_recursive(domain->parent, irq_base,
1136 nr_irqs);
1137}
1138
1139/**
1062 * irq_domain_activate_irq - Call domain_ops->activate recursively to activate 1140 * irq_domain_activate_irq - Call domain_ops->activate recursively to activate
1063 * interrupt 1141 * interrupt
1064 * @irq_data: outermost irq_data associated with interrupt 1142 * @irq_data: outermost irq_data associated with interrupt