diff options
| author | Grant Likely <grant.likely@secretlab.ca> | 2012-02-15 17:06:08 -0500 |
|---|---|---|
| committer | Grant Likely <grant.likely@secretlab.ca> | 2012-04-12 02:37:48 -0400 |
| commit | 6fa6c8e25e95bdc73e92e4c96b8e3299169b616e (patch) | |
| tree | 34dc13fb2448eab4916f55edd10dfa34c36505df | |
| parent | 15e06bf64f686befd2030da867a3dad965b96cc0 (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.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/cell/beat_interrupt.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powermac/smp.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/interrupt.c | 3 | ||||
| -rw-r--r-- | include/linux/irqdomain.h | 6 | ||||
| -rw-r--r-- | kernel/irq/irqdomain.c | 33 |
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); |
| 122 | struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, | 125 | struct 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); |
| 125 | struct irq_domain *irq_domain_add_tree(struct device_node *of_node, | 129 | struct 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 | ||
| 129 | extern struct irq_domain *irq_find_host(struct device_node *node); | 133 | extern struct irq_domain *irq_find_host(struct device_node *node); |
| 130 | extern void irq_set_default_host(struct irq_domain *host); | 134 | extern void irq_set_default_host(struct irq_domain *host); |
| 131 | extern void irq_set_virq_count(unsigned int count); | ||
| 132 | 135 | ||
| 133 | static inline struct irq_domain *irq_domain_add_legacy_isa( | 136 | static 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 | } |
| 141 | extern struct irq_domain *irq_find_host(struct device_node *node); | 144 | extern struct irq_domain *irq_find_host(struct device_node *node); |
| 142 | extern void irq_set_default_host(struct irq_domain *host); | 145 | extern void irq_set_default_host(struct irq_domain *host); |
| 143 | extern void irq_set_virq_count(unsigned int count); | ||
| 144 | 146 | ||
| 145 | 147 | ||
| 146 | extern unsigned int irq_create_mapping(struct irq_domain *host, | 148 | extern 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); | |||
| 23 | static DEFINE_MUTEX(irq_domain_mutex); | 23 | static DEFINE_MUTEX(irq_domain_mutex); |
| 24 | 24 | ||
| 25 | static DEFINE_MUTEX(revmap_trees_mutex); | 25 | static DEFINE_MUTEX(revmap_trees_mutex); |
| 26 | static unsigned int irq_virq_count = NR_IRQS; | ||
| 27 | static struct irq_domain *irq_default_domain; | 26 | static 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 | ||
| 186 | struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, | 185 | struct 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 | */ | ||
| 272 | void 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 | |||
| 281 | static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, | 267 | static 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 | } | ||
