diff options
Diffstat (limited to 'arch/powerpc/kernel/irq.c')
-rw-r--r-- | arch/powerpc/kernel/irq.c | 137 |
1 files changed, 89 insertions, 48 deletions
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 02a334662cc0..f6dca4f4b295 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -87,7 +87,10 @@ extern int tau_interrupts(int); | |||
87 | #endif /* CONFIG_PPC32 */ | 87 | #endif /* CONFIG_PPC32 */ |
88 | 88 | ||
89 | #ifdef CONFIG_PPC64 | 89 | #ifdef CONFIG_PPC64 |
90 | |||
91 | #ifndef CONFIG_SPARSE_IRQ | ||
90 | EXPORT_SYMBOL(irq_desc); | 92 | EXPORT_SYMBOL(irq_desc); |
93 | #endif | ||
91 | 94 | ||
92 | int distribute_irqs = 1; | 95 | int distribute_irqs = 1; |
93 | 96 | ||
@@ -189,33 +192,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
189 | for_each_online_cpu(j) | 192 | for_each_online_cpu(j) |
190 | seq_printf(p, "CPU%d ", j); | 193 | seq_printf(p, "CPU%d ", j); |
191 | seq_putc(p, '\n'); | 194 | seq_putc(p, '\n'); |
192 | } | 195 | } else if (i == nr_irqs) { |
193 | |||
194 | if (i < NR_IRQS) { | ||
195 | desc = get_irq_desc(i); | ||
196 | spin_lock_irqsave(&desc->lock, flags); | ||
197 | action = desc->action; | ||
198 | if (!action || !action->handler) | ||
199 | goto skip; | ||
200 | seq_printf(p, "%3d: ", i); | ||
201 | #ifdef CONFIG_SMP | ||
202 | for_each_online_cpu(j) | ||
203 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | ||
204 | #else | ||
205 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
206 | #endif /* CONFIG_SMP */ | ||
207 | if (desc->chip) | ||
208 | seq_printf(p, " %s ", desc->chip->typename); | ||
209 | else | ||
210 | seq_puts(p, " None "); | ||
211 | seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); | ||
212 | seq_printf(p, " %s", action->name); | ||
213 | for (action = action->next; action; action = action->next) | ||
214 | seq_printf(p, ", %s", action->name); | ||
215 | seq_putc(p, '\n'); | ||
216 | skip: | ||
217 | spin_unlock_irqrestore(&desc->lock, flags); | ||
218 | } else if (i == NR_IRQS) { | ||
219 | #if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT) | 196 | #if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT) |
220 | if (tau_initialized){ | 197 | if (tau_initialized){ |
221 | seq_puts(p, "TAU: "); | 198 | seq_puts(p, "TAU: "); |
@@ -225,30 +202,68 @@ skip: | |||
225 | } | 202 | } |
226 | #endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/ | 203 | #endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/ |
227 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); | 204 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); |
205 | |||
206 | return 0; | ||
228 | } | 207 | } |
208 | |||
209 | desc = irq_to_desc(i); | ||
210 | if (!desc) | ||
211 | return 0; | ||
212 | |||
213 | spin_lock_irqsave(&desc->lock, flags); | ||
214 | |||
215 | action = desc->action; | ||
216 | if (!action || !action->handler) | ||
217 | goto skip; | ||
218 | |||
219 | seq_printf(p, "%3d: ", i); | ||
220 | #ifdef CONFIG_SMP | ||
221 | for_each_online_cpu(j) | ||
222 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | ||
223 | #else | ||
224 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
225 | #endif /* CONFIG_SMP */ | ||
226 | |||
227 | if (desc->chip) | ||
228 | seq_printf(p, " %s ", desc->chip->name); | ||
229 | else | ||
230 | seq_puts(p, " None "); | ||
231 | |||
232 | seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); | ||
233 | seq_printf(p, " %s", action->name); | ||
234 | |||
235 | for (action = action->next; action; action = action->next) | ||
236 | seq_printf(p, ", %s", action->name); | ||
237 | seq_putc(p, '\n'); | ||
238 | |||
239 | skip: | ||
240 | spin_unlock_irqrestore(&desc->lock, flags); | ||
241 | |||
229 | return 0; | 242 | return 0; |
230 | } | 243 | } |
231 | 244 | ||
232 | #ifdef CONFIG_HOTPLUG_CPU | 245 | #ifdef CONFIG_HOTPLUG_CPU |
233 | void fixup_irqs(cpumask_t map) | 246 | void fixup_irqs(cpumask_t map) |
234 | { | 247 | { |
248 | struct irq_desc *desc; | ||
235 | unsigned int irq; | 249 | unsigned int irq; |
236 | static int warned; | 250 | static int warned; |
237 | 251 | ||
238 | for_each_irq(irq) { | 252 | for_each_irq(irq) { |
239 | cpumask_t mask; | 253 | cpumask_t mask; |
240 | 254 | ||
241 | if (irq_desc[irq].status & IRQ_PER_CPU) | 255 | desc = irq_to_desc(irq); |
256 | if (desc && desc->status & IRQ_PER_CPU) | ||
242 | continue; | 257 | continue; |
243 | 258 | ||
244 | cpumask_and(&mask, irq_desc[irq].affinity, &map); | 259 | cpumask_and(&mask, desc->affinity, &map); |
245 | if (any_online_cpu(mask) == NR_CPUS) { | 260 | if (any_online_cpu(mask) == NR_CPUS) { |
246 | printk("Breaking affinity for irq %i\n", irq); | 261 | printk("Breaking affinity for irq %i\n", irq); |
247 | mask = map; | 262 | mask = map; |
248 | } | 263 | } |
249 | if (irq_desc[irq].chip->set_affinity) | 264 | if (desc->chip->set_affinity) |
250 | irq_desc[irq].chip->set_affinity(irq, &mask); | 265 | desc->chip->set_affinity(irq, &mask); |
251 | else if (irq_desc[irq].action && !(warned++)) | 266 | else if (desc->action && !(warned++)) |
252 | printk("Cannot set affinity for irq %i\n", irq); | 267 | printk("Cannot set affinity for irq %i\n", irq); |
253 | } | 268 | } |
254 | 269 | ||
@@ -275,7 +290,7 @@ static inline void handle_one_irq(unsigned int irq) | |||
275 | return; | 290 | return; |
276 | } | 291 | } |
277 | 292 | ||
278 | desc = irq_desc + irq; | 293 | desc = irq_to_desc(irq); |
279 | saved_sp_limit = current->thread.ksp_limit; | 294 | saved_sp_limit = current->thread.ksp_limit; |
280 | 295 | ||
281 | irqtp->task = curtp->task; | 296 | irqtp->task = curtp->task; |
@@ -541,7 +556,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node, | |||
541 | smp_wmb(); | 556 | smp_wmb(); |
542 | 557 | ||
543 | /* Clear norequest flags */ | 558 | /* Clear norequest flags */ |
544 | get_irq_desc(i)->status &= ~IRQ_NOREQUEST; | 559 | irq_to_desc(i)->status &= ~IRQ_NOREQUEST; |
545 | 560 | ||
546 | /* Legacy flags are left to default at this point, | 561 | /* Legacy flags are left to default at this point, |
547 | * one can then use irq_create_mapping() to | 562 | * one can then use irq_create_mapping() to |
@@ -607,8 +622,16 @@ void irq_set_virq_count(unsigned int count) | |||
607 | static int irq_setup_virq(struct irq_host *host, unsigned int virq, | 622 | static int irq_setup_virq(struct irq_host *host, unsigned int virq, |
608 | irq_hw_number_t hwirq) | 623 | irq_hw_number_t hwirq) |
609 | { | 624 | { |
625 | struct irq_desc *desc; | ||
626 | |||
627 | desc = irq_to_desc_alloc_node(virq, 0); | ||
628 | if (!desc) { | ||
629 | pr_debug("irq: -> allocating desc failed\n"); | ||
630 | goto error; | ||
631 | } | ||
632 | |||
610 | /* Clear IRQ_NOREQUEST flag */ | 633 | /* Clear IRQ_NOREQUEST flag */ |
611 | get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | 634 | desc->status &= ~IRQ_NOREQUEST; |
612 | 635 | ||
613 | /* map it */ | 636 | /* map it */ |
614 | smp_wmb(); | 637 | smp_wmb(); |
@@ -617,11 +640,14 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq, | |||
617 | 640 | ||
618 | if (host->ops->map(host, virq, hwirq)) { | 641 | if (host->ops->map(host, virq, hwirq)) { |
619 | pr_debug("irq: -> mapping failed, freeing\n"); | 642 | pr_debug("irq: -> mapping failed, freeing\n"); |
620 | irq_free_virt(virq, 1); | 643 | goto error; |
621 | return -1; | ||
622 | } | 644 | } |
623 | 645 | ||
624 | return 0; | 646 | return 0; |
647 | |||
648 | error: | ||
649 | irq_free_virt(virq, 1); | ||
650 | return -1; | ||
625 | } | 651 | } |
626 | 652 | ||
627 | unsigned int irq_create_direct_mapping(struct irq_host *host) | 653 | unsigned int irq_create_direct_mapping(struct irq_host *host) |
@@ -705,7 +731,7 @@ unsigned int irq_create_mapping(struct irq_host *host, | |||
705 | EXPORT_SYMBOL_GPL(irq_create_mapping); | 731 | EXPORT_SYMBOL_GPL(irq_create_mapping); |
706 | 732 | ||
707 | unsigned int irq_create_of_mapping(struct device_node *controller, | 733 | unsigned int irq_create_of_mapping(struct device_node *controller, |
708 | u32 *intspec, unsigned int intsize) | 734 | const u32 *intspec, unsigned int intsize) |
709 | { | 735 | { |
710 | struct irq_host *host; | 736 | struct irq_host *host; |
711 | irq_hw_number_t hwirq; | 737 | irq_hw_number_t hwirq; |
@@ -738,7 +764,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller, | |||
738 | 764 | ||
739 | /* Set type if specified and different than the current one */ | 765 | /* Set type if specified and different than the current one */ |
740 | if (type != IRQ_TYPE_NONE && | 766 | if (type != IRQ_TYPE_NONE && |
741 | type != (get_irq_desc(virq)->status & IRQF_TRIGGER_MASK)) | 767 | type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK)) |
742 | set_irq_type(virq, type); | 768 | set_irq_type(virq, type); |
743 | return virq; | 769 | return virq; |
744 | } | 770 | } |
@@ -810,7 +836,7 @@ void irq_dispose_mapping(unsigned int virq) | |||
810 | irq_map[virq].hwirq = host->inval_irq; | 836 | irq_map[virq].hwirq = host->inval_irq; |
811 | 837 | ||
812 | /* Set some flags */ | 838 | /* Set some flags */ |
813 | get_irq_desc(virq)->status |= IRQ_NOREQUEST; | 839 | irq_to_desc(virq)->status |= IRQ_NOREQUEST; |
814 | 840 | ||
815 | /* Free it */ | 841 | /* Free it */ |
816 | irq_free_virt(virq, 1); | 842 | irq_free_virt(virq, 1); |
@@ -1002,12 +1028,24 @@ void irq_free_virt(unsigned int virq, unsigned int count) | |||
1002 | spin_unlock_irqrestore(&irq_big_lock, flags); | 1028 | spin_unlock_irqrestore(&irq_big_lock, flags); |
1003 | } | 1029 | } |
1004 | 1030 | ||
1005 | void irq_early_init(void) | 1031 | int arch_early_irq_init(void) |
1006 | { | 1032 | { |
1007 | unsigned int i; | 1033 | struct irq_desc *desc; |
1034 | int i; | ||
1035 | |||
1036 | for (i = 0; i < NR_IRQS; i++) { | ||
1037 | desc = irq_to_desc(i); | ||
1038 | if (desc) | ||
1039 | desc->status |= IRQ_NOREQUEST; | ||
1040 | } | ||
1008 | 1041 | ||
1009 | for (i = 0; i < NR_IRQS; i++) | 1042 | return 0; |
1010 | get_irq_desc(i)->status |= IRQ_NOREQUEST; | 1043 | } |
1044 | |||
1045 | int arch_init_chip_data(struct irq_desc *desc, int node) | ||
1046 | { | ||
1047 | desc->status |= IRQ_NOREQUEST; | ||
1048 | return 0; | ||
1011 | } | 1049 | } |
1012 | 1050 | ||
1013 | /* We need to create the radix trees late */ | 1051 | /* We need to create the radix trees late */ |
@@ -1069,16 +1107,19 @@ static int virq_debug_show(struct seq_file *m, void *private) | |||
1069 | seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", | 1107 | seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", |
1070 | "chip name", "host name"); | 1108 | "chip name", "host name"); |
1071 | 1109 | ||
1072 | for (i = 1; i < NR_IRQS; i++) { | 1110 | for (i = 1; i < nr_irqs; i++) { |
1073 | desc = get_irq_desc(i); | 1111 | desc = irq_to_desc(i); |
1112 | if (!desc) | ||
1113 | continue; | ||
1114 | |||
1074 | spin_lock_irqsave(&desc->lock, flags); | 1115 | spin_lock_irqsave(&desc->lock, flags); |
1075 | 1116 | ||
1076 | if (desc->action && desc->action->handler) { | 1117 | if (desc->action && desc->action->handler) { |
1077 | seq_printf(m, "%5d ", i); | 1118 | seq_printf(m, "%5d ", i); |
1078 | seq_printf(m, "0x%05lx ", virq_to_hw(i)); | 1119 | seq_printf(m, "0x%05lx ", virq_to_hw(i)); |
1079 | 1120 | ||
1080 | if (desc->chip && desc->chip->typename) | 1121 | if (desc->chip && desc->chip->name) |
1081 | p = desc->chip->typename; | 1122 | p = desc->chip->name; |
1082 | else | 1123 | else |
1083 | p = none; | 1124 | p = none; |
1084 | seq_printf(m, "%-15s ", p); | 1125 | seq_printf(m, "%-15s ", p); |