aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@linaro.org>2013-06-06 07:10:24 -0400
committerGrant Likely <grant.likely@linaro.org>2013-06-10 06:52:09 -0400
commit9bbf877d3b6b8c5991000296f40a3f0fe66fa89b (patch)
tree0bad73ca231bbdff6b989482a3c8c375c631c90f /kernel/irq
parent5e1cda5b8ae93f5f02e8c5a30390ac9b4d2c20e6 (diff)
irqdomain: Replace LEGACY mapping with LINEAR
The LEGACY mapping unnecessarily complicates the irqdomain code and can easily be implemented with a linear mapping. By ripping it out and replacing it with the LINEAR mapping the object size of irqdomain.c shrinks by about 330 bytes (ARMv7) which offsets the additional allocation required by the linear map. It also makes it possible for current LEGACY map users to pre-allocate irq_descs for a subset of the hwirqs and dynamically allocate the rest as needed. Signed-off-by: Grant Likely <grant.likely@linaro.org> Cc: Paul Mundt <lethal@linux-sh.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Rob Herring <rob.herring@calxeda.com>
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/irqdomain.c84
1 files changed, 6 insertions, 78 deletions
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 61d6d3c80fee..1ac8cf41b9a5 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -82,13 +82,6 @@ void irq_domain_remove(struct irq_domain *domain)
82 mutex_lock(&irq_domain_mutex); 82 mutex_lock(&irq_domain_mutex);
83 83
84 switch (domain->revmap_type) { 84 switch (domain->revmap_type) {
85 case IRQ_DOMAIN_MAP_LEGACY:
86 /*
87 * Legacy domains don't manage their own irq_desc
88 * allocations, we expect the caller to handle irq_desc
89 * freeing on their own.
90 */
91 break;
92 case IRQ_DOMAIN_MAP_TREE: 85 case IRQ_DOMAIN_MAP_TREE:
93 /* 86 /*
94 * radix_tree_delete() takes care of destroying the root 87 * radix_tree_delete() takes care of destroying the root
@@ -122,17 +115,6 @@ void irq_domain_remove(struct irq_domain *domain)
122} 115}
123EXPORT_SYMBOL_GPL(irq_domain_remove); 116EXPORT_SYMBOL_GPL(irq_domain_remove);
124 117
125static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
126 irq_hw_number_t hwirq)
127{
128 irq_hw_number_t first_hwirq = domain->revmap_data.legacy.first_hwirq;
129 int size = domain->revmap_data.legacy.size;
130
131 if (WARN_ON(hwirq < first_hwirq || hwirq >= first_hwirq + size))
132 return 0;
133 return hwirq - first_hwirq + domain->revmap_data.legacy.first_irq;
134}
135
136/** 118/**
137 * irq_domain_add_simple() - Allocate and register a simple irq_domain. 119 * irq_domain_add_simple() - Allocate and register a simple irq_domain.
138 * @of_node: pointer to interrupt controller's device tree node. 120 * @of_node: pointer to interrupt controller's device tree node.
@@ -213,57 +195,17 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
213 void *host_data) 195 void *host_data)
214{ 196{
215 struct irq_domain *domain; 197 struct irq_domain *domain;
216 unsigned int i;
217 198
218 domain = irq_domain_alloc(of_node, IRQ_DOMAIN_MAP_LEGACY, ops, host_data); 199 pr_debug("Setting up legacy domain virq[%i:%i] ==> hwirq[%i:%i]\n",
200 first_irq, first_irq + size - 1,
201 (int)first_hwirq, (int)first_hwirq + size -1);
202
203 domain = irq_domain_add_linear(of_node, first_hwirq + size, ops, host_data);
219 if (!domain) 204 if (!domain)
220 return NULL; 205 return NULL;
221 206
222 domain->revmap_data.legacy.first_irq = first_irq; 207 WARN_ON(irq_domain_associate_many(domain, first_irq, first_hwirq, size));
223 domain->revmap_data.legacy.first_hwirq = first_hwirq;
224 domain->revmap_data.legacy.size = size;
225
226 mutex_lock(&irq_domain_mutex);
227 /* Verify that all the irqs are available */
228 for (i = 0; i < size; i++) {
229 int irq = first_irq + i;
230 struct irq_data *irq_data = irq_get_irq_data(irq);
231
232 if (WARN_ON(!irq_data || irq_data->domain)) {
233 mutex_unlock(&irq_domain_mutex);
234 irq_domain_free(domain);
235 return NULL;
236 }
237 }
238 208
239 /* Claim all of the irqs before registering a legacy domain */
240 for (i = 0; i < size; i++) {
241 struct irq_data *irq_data = irq_get_irq_data(first_irq + i);
242 irq_data->hwirq = first_hwirq + i;
243 irq_data->domain = domain;
244 }
245 mutex_unlock(&irq_domain_mutex);
246
247 for (i = 0; i < size; i++) {
248 int irq = first_irq + i;
249 int hwirq = first_hwirq + i;
250
251 /* IRQ0 gets ignored */
252 if (!irq)
253 continue;
254
255 /* Legacy flags are left to default at this point,
256 * one can then use irq_create_mapping() to
257 * explicitly change them
258 */
259 if (ops->map)
260 ops->map(domain, irq, hwirq);
261
262 /* Clear norequest flags */
263 irq_clear_status_flags(irq, IRQ_NOREQUEST);
264 }
265
266 irq_domain_add(domain);
267 return domain; 209 return domain;
268} 210}
269EXPORT_SYMBOL_GPL(irq_domain_add_legacy); 211EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
@@ -492,10 +434,6 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
492 } 434 }
493 435
494 return 0; 436 return 0;
495
496 err_unmap:
497 irq_domain_disassociate_many(domain, irq_base, i);
498 return -EINVAL;
499} 437}
500EXPORT_SYMBOL_GPL(irq_domain_associate_many); 438EXPORT_SYMBOL_GPL(irq_domain_associate_many);
501 439
@@ -575,10 +513,6 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
575 return virq; 513 return virq;
576 } 514 }
577 515
578 /* Get a virtual interrupt number */
579 if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY)
580 return irq_domain_legacy_revmap(domain, hwirq);
581
582 /* Allocate a virtual interrupt number */ 516 /* Allocate a virtual interrupt number */
583 hint = hwirq % nr_irqs; 517 hint = hwirq % nr_irqs;
584 if (hint == 0) 518 if (hint == 0)
@@ -706,10 +640,6 @@ void irq_dispose_mapping(unsigned int virq)
706 if (WARN_ON(domain == NULL)) 640 if (WARN_ON(domain == NULL))
707 return; 641 return;
708 642
709 /* Never unmap legacy interrupts */
710 if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY)
711 return;
712
713 irq_domain_disassociate_many(domain, virq, 1); 643 irq_domain_disassociate_many(domain, virq, 1);
714 irq_free_desc(virq); 644 irq_free_desc(virq);
715} 645}
@@ -732,8 +662,6 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
732 return 0; 662 return 0;
733 663
734 switch (domain->revmap_type) { 664 switch (domain->revmap_type) {
735 case IRQ_DOMAIN_MAP_LEGACY:
736 return irq_domain_legacy_revmap(domain, hwirq);
737 case IRQ_DOMAIN_MAP_LINEAR: 665 case IRQ_DOMAIN_MAP_LINEAR:
738 return irq_linear_revmap(domain, hwirq); 666 return irq_linear_revmap(domain, hwirq);
739 case IRQ_DOMAIN_MAP_TREE: 667 case IRQ_DOMAIN_MAP_TREE: