aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2012-02-15 17:06:08 -0500
committerGrant Likely <grant.likely@secretlab.ca>2012-04-12 02:37:48 -0400
commit6fa6c8e25e95bdc73e92e4c96b8e3299169b616e (patch)
tree34dc13fb2448eab4916f55edd10dfa34c36505df
parent15e06bf64f686befd2030da867a3dad965b96cc0 (diff)
irq_domain: Move irq_virq_count into NOMAP revmap
This patch replaces the old global setting of irq_virq_count that is only used by the NOMAP mapping and instead uses a revmap_data property so that the maximum NOMAP allocation can be set per NOMAP irq_domain. There is exactly one user of irq_virq_count in-tree right now: PS3. Also, irq_virq_count is only useful for the NOMAP mapping. So, instead of having a single global irq_virq_count values, this change drops it entirely and added a max_irq argument to irq_domain_add_nomap(). That makes it a property of an individual nomap irq domain instead of a global system settting. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Tested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Milton Miller <miltonm@bga.com>
-rw-r--r--arch/powerpc/platforms/cell/axon_msi.c2
-rw-r--r--arch/powerpc/platforms/cell/beat_interrupt.c2
-rw-r--r--arch/powerpc/platforms/powermac/smp.c2
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c3
-rw-r--r--include/linux/irqdomain.h6
-rw-r--r--kernel/irq/irqdomain.c33
6 files changed, 17 insertions, 31 deletions
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index db360fc4cf0e..d09f3e8e6867 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -392,7 +392,7 @@ static int axon_msi_probe(struct platform_device *device)
392 } 392 }
393 memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES); 393 memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES);
394 394
395 msic->irq_domain = irq_domain_add_nomap(dn, &msic_host_ops, msic); 395 msic->irq_domain = irq_domain_add_nomap(dn, 0, &msic_host_ops, msic);
396 if (!msic->irq_domain) { 396 if (!msic->irq_domain) {
397 printk(KERN_ERR "axon_msi: couldn't allocate irq_domain for %s\n", 397 printk(KERN_ERR "axon_msi: couldn't allocate irq_domain for %s\n",
398 dn->full_name); 398 dn->full_name);
diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c
index e5c3a2c6090d..f9a48af335cb 100644
--- a/arch/powerpc/platforms/cell/beat_interrupt.c
+++ b/arch/powerpc/platforms/cell/beat_interrupt.c
@@ -239,7 +239,7 @@ void __init beatic_init_IRQ(void)
239 ppc_md.get_irq = beatic_get_irq; 239 ppc_md.get_irq = beatic_get_irq;
240 240
241 /* Allocate an irq host */ 241 /* Allocate an irq host */
242 beatic_host = irq_domain_add_nomap(NULL, &beatic_pic_host_ops, NULL); 242 beatic_host = irq_domain_add_nomap(NULL, 0, &beatic_pic_host_ops, NULL);
243 BUG_ON(beatic_host == NULL); 243 BUG_ON(beatic_host == NULL);
244 irq_set_default_host(beatic_host); 244 irq_set_default_host(beatic_host);
245} 245}
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index a81e5a88fbdf..b4ddaa3fbb29 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -192,7 +192,7 @@ static int psurge_secondary_ipi_init(void)
192{ 192{
193 int rc = -ENOMEM; 193 int rc = -ENOMEM;
194 194
195 psurge_host = irq_domain_add_nomap(NULL, &psurge_host_ops, NULL); 195 psurge_host = irq_domain_add_nomap(NULL, 0, &psurge_host_ops, NULL);
196 196
197 if (psurge_host) 197 if (psurge_host)
198 psurge_secondary_virq = irq_create_direct_mapping(psurge_host); 198 psurge_secondary_virq = irq_create_direct_mapping(psurge_host);
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 2a4ff86cc21f..5f3b23220b8e 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -753,9 +753,8 @@ void __init ps3_init_IRQ(void)
753 unsigned cpu; 753 unsigned cpu;
754 struct irq_domain *host; 754 struct irq_domain *host;
755 755
756 host = irq_domain_add_nomap(NULL, &ps3_host_ops, NULL); 756 host = irq_domain_add_nomap(NULL, PS3_PLUG_MAX + 1, &ps3_host_ops, NULL);
757 irq_set_default_host(host); 757 irq_set_default_host(host);
758 irq_set_virq_count(PS3_PLUG_MAX + 1);
759 758
760 for_each_possible_cpu(cpu) { 759 for_each_possible_cpu(cpu) {
761 struct ps3_private *pd = &per_cpu(ps3_private, cpu); 760 struct ps3_private *pd = &per_cpu(ps3_private, cpu);
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index ac17b9b2e7be..c65740d76e66 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -98,6 +98,9 @@ struct irq_domain {
98 unsigned int size; 98 unsigned int size;
99 unsigned int *revmap; 99 unsigned int *revmap;
100 } linear; 100 } linear;
101 struct {
102 unsigned int max_irq;
103 } nomap;
101 struct radix_tree_root tree; 104 struct radix_tree_root tree;
102 } revmap_data; 105 } revmap_data;
103 const struct irq_domain_ops *ops; 106 const struct irq_domain_ops *ops;
@@ -120,6 +123,7 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
120 const struct irq_domain_ops *ops, 123 const struct irq_domain_ops *ops,
121 void *host_data); 124 void *host_data);
122struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, 125struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
126 unsigned int max_irq,
123 const struct irq_domain_ops *ops, 127 const struct irq_domain_ops *ops,
124 void *host_data); 128 void *host_data);
125struct irq_domain *irq_domain_add_tree(struct device_node *of_node, 129struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
@@ -128,7 +132,6 @@ struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
128 132
129extern struct irq_domain *irq_find_host(struct device_node *node); 133extern struct irq_domain *irq_find_host(struct device_node *node);
130extern void irq_set_default_host(struct irq_domain *host); 134extern void irq_set_default_host(struct irq_domain *host);
131extern void irq_set_virq_count(unsigned int count);
132 135
133static inline struct irq_domain *irq_domain_add_legacy_isa( 136static inline struct irq_domain *irq_domain_add_legacy_isa(
134 struct device_node *of_node, 137 struct device_node *of_node,
@@ -140,7 +143,6 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
140} 143}
141extern struct irq_domain *irq_find_host(struct device_node *node); 144extern struct irq_domain *irq_find_host(struct device_node *node);
142extern void irq_set_default_host(struct irq_domain *host); 145extern void irq_set_default_host(struct irq_domain *host);
143extern void irq_set_virq_count(unsigned int count);
144 146
145 147
146extern unsigned int irq_create_mapping(struct irq_domain *host, 148extern unsigned int irq_create_mapping(struct irq_domain *host,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index eb05e40f4553..d34413e78628 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -23,7 +23,6 @@ static LIST_HEAD(irq_domain_list);
23static DEFINE_MUTEX(irq_domain_mutex); 23static DEFINE_MUTEX(irq_domain_mutex);
24 24
25static DEFINE_MUTEX(revmap_trees_mutex); 25static DEFINE_MUTEX(revmap_trees_mutex);
26static unsigned int irq_virq_count = NR_IRQS;
27static struct irq_domain *irq_default_domain; 26static struct irq_domain *irq_default_domain;
28 27
29/** 28/**
@@ -184,13 +183,16 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
184} 183}
185 184
186struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, 185struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
186 unsigned int max_irq,
187 const struct irq_domain_ops *ops, 187 const struct irq_domain_ops *ops,
188 void *host_data) 188 void *host_data)
189{ 189{
190 struct irq_domain *domain = irq_domain_alloc(of_node, 190 struct irq_domain *domain = irq_domain_alloc(of_node,
191 IRQ_DOMAIN_MAP_NOMAP, ops, host_data); 191 IRQ_DOMAIN_MAP_NOMAP, ops, host_data);
192 if (domain) 192 if (domain) {
193 domain->revmap_data.nomap.max_irq = max_irq ? max_irq : ~0;
193 irq_domain_add(domain); 194 irq_domain_add(domain);
195 }
194 return domain; 196 return domain;
195} 197}
196 198
@@ -262,22 +264,6 @@ void irq_set_default_host(struct irq_domain *domain)
262 irq_default_domain = domain; 264 irq_default_domain = domain;
263} 265}
264 266
265/**
266 * irq_set_virq_count() - Set the maximum number of linux irqs
267 * @count: number of linux irqs, capped with NR_IRQS
268 *
269 * This is mainly for use by platforms like iSeries who want to program
270 * the virtual irq number in the controller to avoid the reverse mapping
271 */
272void irq_set_virq_count(unsigned int count)
273{
274 pr_debug("irq: Trying to set virq count to %d\n", count);
275
276 BUG_ON(count < NUM_ISA_INTERRUPTS);
277 if (count < NR_IRQS)
278 irq_virq_count = count;
279}
280
281static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, 267static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
282 irq_hw_number_t hwirq) 268 irq_hw_number_t hwirq)
283{ 269{
@@ -320,13 +306,12 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
320 pr_debug("irq: create_direct virq allocation failed\n"); 306 pr_debug("irq: create_direct virq allocation failed\n");
321 return 0; 307 return 0;
322 } 308 }
323 if (virq >= irq_virq_count) { 309 if (virq >= domain->revmap_data.nomap.max_irq) {
324 pr_err("ERROR: no free irqs available below %i maximum\n", 310 pr_err("ERROR: no free irqs available below %i maximum\n",
325 irq_virq_count); 311 domain->revmap_data.nomap.max_irq);
326 irq_free_desc(virq); 312 irq_free_desc(virq);
327 return 0; 313 return 0;
328 } 314 }
329
330 pr_debug("irq: create_direct obtained virq %d\n", virq); 315 pr_debug("irq: create_direct obtained virq %d\n", virq);
331 316
332 if (irq_setup_virq(domain, virq, virq)) { 317 if (irq_setup_virq(domain, virq, virq)) {
@@ -378,7 +363,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
378 return irq_domain_legacy_revmap(domain, hwirq); 363 return irq_domain_legacy_revmap(domain, hwirq);
379 364
380 /* Allocate a virtual interrupt number */ 365 /* Allocate a virtual interrupt number */
381 hint = hwirq % irq_virq_count; 366 hint = hwirq % nr_irqs;
382 if (hint == 0) 367 if (hint == 0)
383 hint++; 368 hint++;
384 virq = irq_alloc_desc_from(hint, 0); 369 virq = irq_alloc_desc_from(hint, 0);
@@ -516,7 +501,7 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
516 irq_hw_number_t hwirq) 501 irq_hw_number_t hwirq)
517{ 502{
518 unsigned int i; 503 unsigned int i;
519 unsigned int hint = hwirq % irq_virq_count; 504 unsigned int hint = hwirq % nr_irqs;
520 505
521 /* Look for default domain if nececssary */ 506 /* Look for default domain if nececssary */
522 if (domain == NULL) 507 if (domain == NULL)
@@ -537,7 +522,7 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
537 if (data && (data->domain == domain) && (data->hwirq == hwirq)) 522 if (data && (data->domain == domain) && (data->hwirq == hwirq))
538 return i; 523 return i;
539 i++; 524 i++;
540 if (i >= irq_virq_count) 525 if (i >= nr_irqs)
541 i = 1; 526 i = 1;
542 } while(i != hint); 527 } while(i != hint);
543 return 0; 528 return 0;