irq.c (f3d607c6b39bd9cb5000e03e2c0dc2afe1241374) irq.c (40d50cf7ca956183f3a573bc21082e1c7d04fa7b)
1/*
2 * Derived from arch/i386/kernel/irq.c
3 * Copyright (C) 1992 Linus Torvalds
4 * Adapted from arch/i386 by Gary Thomas
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 * Updated and modified by Cort Dougan <cort@fsmlabs.com>
7 * Copyright (C) 1996-2001 Cort Dougan
8 * Adapted for Power Macintosh by Paul Mackerras

--- 56 unchanged lines hidden (view full) ---

65#include <asm/ptrace.h>
66#include <asm/machdep.h>
67#include <asm/udbg.h>
68#ifdef CONFIG_PPC64
69#include <asm/paca.h>
70#include <asm/firmware.h>
71#include <asm/lv1call.h>
72#endif
1/*
2 * Derived from arch/i386/kernel/irq.c
3 * Copyright (C) 1992 Linus Torvalds
4 * Adapted from arch/i386 by Gary Thomas
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 * Updated and modified by Cort Dougan <cort@fsmlabs.com>
7 * Copyright (C) 1996-2001 Cort Dougan
8 * Adapted for Power Macintosh by Paul Mackerras

--- 56 unchanged lines hidden (view full) ---

65#include <asm/ptrace.h>
66#include <asm/machdep.h>
67#include <asm/udbg.h>
68#ifdef CONFIG_PPC64
69#include <asm/paca.h>
70#include <asm/firmware.h>
71#include <asm/lv1call.h>
72#endif
73#define CREATE_TRACE_POINTS
74#include <asm/trace.h>
75
76int __irq_offset_value;
77static int ppc_spurious_interrupts;
78
79#ifdef CONFIG_PPC32
80EXPORT_SYMBOL(__irq_offset_value);
81atomic_t ppc_n_lost_interrupts;
82
83#ifdef CONFIG_TAU_INT
84extern int tau_initialized;
85extern int tau_interrupts(int);
86#endif
87#endif /* CONFIG_PPC32 */
88
89#ifdef CONFIG_PPC64
73
74int __irq_offset_value;
75static int ppc_spurious_interrupts;
76
77#ifdef CONFIG_PPC32
78EXPORT_SYMBOL(__irq_offset_value);
79atomic_t ppc_n_lost_interrupts;
80
81#ifdef CONFIG_TAU_INT
82extern int tau_initialized;
83extern int tau_interrupts(int);
84#endif
85#endif /* CONFIG_PPC32 */
86
87#ifdef CONFIG_PPC64
88
89#ifndef CONFIG_SPARSE_IRQ
90EXPORT_SYMBOL(irq_desc);
90EXPORT_SYMBOL(irq_desc);
91#endif
91
92int distribute_irqs = 1;
93
94static inline notrace unsigned long get_hard_enabled(void)
95{
96 unsigned long enabled;
97
98 __asm__ __volatile__("lbz %0,%1(13)"

--- 85 unchanged lines hidden (view full) ---

184 struct irq_desc *desc;
185 unsigned long flags;
186
187 if (i == 0) {
188 seq_puts(p, " ");
189 for_each_online_cpu(j)
190 seq_printf(p, "CPU%d ", j);
191 seq_putc(p, '\n');
92
93int distribute_irqs = 1;
94
95static inline notrace unsigned long get_hard_enabled(void)
96{
97 unsigned long enabled;
98
99 __asm__ __volatile__("lbz %0,%1(13)"

--- 85 unchanged lines hidden (view full) ---

185 struct irq_desc *desc;
186 unsigned long flags;
187
188 if (i == 0) {
189 seq_puts(p, " ");
190 for_each_online_cpu(j)
191 seq_printf(p, "CPU%d ", j);
192 seq_putc(p, '\n');
192 }
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');
216skip:
217 spin_unlock_irqrestore(&desc->lock, flags);
218 } else if (i == NR_IRQS) {
193 } else if (i == nr_irqs) {
219#if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT)
220 if (tau_initialized){
221 seq_puts(p, "TAU: ");
222 for_each_online_cpu(j)
223 seq_printf(p, "%10u ", tau_interrupts(j));
224 seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n");
225 }
226#endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/
227 seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
194#if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT)
195 if (tau_initialized){
196 seq_puts(p, "TAU: ");
197 for_each_online_cpu(j)
198 seq_printf(p, "%10u ", tau_interrupts(j));
199 seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n");
200 }
201#endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/
202 seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
203
204 return 0;
228 }
205 }
206
207 desc = irq_to_desc(i);
208 if (!desc)
209 return 0;
210
211 spin_lock_irqsave(&desc->lock, flags);
212
213 action = desc->action;
214 if (!action || !action->handler)
215 goto skip;
216
217 seq_printf(p, "%3d: ", i);
218#ifdef CONFIG_SMP
219 for_each_online_cpu(j)
220 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
221#else
222 seq_printf(p, "%10u ", kstat_irqs(i));
223#endif /* CONFIG_SMP */
224
225 if (desc->chip)
226 seq_printf(p, " %s ", desc->chip->name);
227 else
228 seq_puts(p, " None ");
229
230 seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge ");
231 seq_printf(p, " %s", action->name);
232
233 for (action = action->next; action; action = action->next)
234 seq_printf(p, ", %s", action->name);
235 seq_putc(p, '\n');
236
237skip:
238 spin_unlock_irqrestore(&desc->lock, flags);
239
229 return 0;
230}
231
232#ifdef CONFIG_HOTPLUG_CPU
233void fixup_irqs(cpumask_t map)
234{
240 return 0;
241}
242
243#ifdef CONFIG_HOTPLUG_CPU
244void fixup_irqs(cpumask_t map)
245{
246 struct irq_desc *desc;
235 unsigned int irq;
236 static int warned;
237
238 for_each_irq(irq) {
239 cpumask_t mask;
240
247 unsigned int irq;
248 static int warned;
249
250 for_each_irq(irq) {
251 cpumask_t mask;
252
241 if (irq_desc[irq].status & IRQ_PER_CPU)
253 desc = irq_to_desc(irq);
254 if (desc && desc->status & IRQ_PER_CPU)
242 continue;
243
255 continue;
256
244 cpumask_and(&mask, irq_desc[irq].affinity, &map);
257 cpumask_and(&mask, desc->affinity, &map);
245 if (any_online_cpu(mask) == NR_CPUS) {
246 printk("Breaking affinity for irq %i\n", irq);
247 mask = map;
248 }
258 if (any_online_cpu(mask) == NR_CPUS) {
259 printk("Breaking affinity for irq %i\n", irq);
260 mask = map;
261 }
249 if (irq_desc[irq].chip->set_affinity)
250 irq_desc[irq].chip->set_affinity(irq, &mask);
251 else if (irq_desc[irq].action && !(warned++))
262 if (desc->chip->set_affinity)
263 desc->chip->set_affinity(irq, &mask);
264 else if (desc->action && !(warned++))
252 printk("Cannot set affinity for irq %i\n", irq);
253 }
254
255 local_irq_enable();
256 mdelay(1);
257 local_irq_disable();
258}
259#endif

--- 10 unchanged lines hidden (view full) ---

270 irqtp = hardirq_ctx[smp_processor_id()];
271
272 if (curtp == irqtp) {
273 /* We're already on the irq stack, just handle it */
274 generic_handle_irq(irq);
275 return;
276 }
277
265 printk("Cannot set affinity for irq %i\n", irq);
266 }
267
268 local_irq_enable();
269 mdelay(1);
270 local_irq_disable();
271}
272#endif

--- 10 unchanged lines hidden (view full) ---

283 irqtp = hardirq_ctx[smp_processor_id()];
284
285 if (curtp == irqtp) {
286 /* We're already on the irq stack, just handle it */
287 generic_handle_irq(irq);
288 return;
289 }
290
278 desc = irq_desc + irq;
291 desc = irq_to_desc(irq);
279 saved_sp_limit = current->thread.ksp_limit;
280
281 irqtp->task = curtp->task;
282 irqtp->flags = 0;
283
284 /* Copy the softirq bits in preempt_count so that the
285 * softirq checks work in the hardirq context. */
286 irqtp->preempt_count = (irqtp->preempt_count & ~SOFTIRQ_MASK) |

--- 35 unchanged lines hidden (view full) ---

322#endif
323}
324
325void do_IRQ(struct pt_regs *regs)
326{
327 struct pt_regs *old_regs = set_irq_regs(regs);
328 unsigned int irq;
329
292 saved_sp_limit = current->thread.ksp_limit;
293
294 irqtp->task = curtp->task;
295 irqtp->flags = 0;
296
297 /* Copy the softirq bits in preempt_count so that the
298 * softirq checks work in the hardirq context. */
299 irqtp->preempt_count = (irqtp->preempt_count & ~SOFTIRQ_MASK) |

--- 35 unchanged lines hidden (view full) ---

335#endif
336}
337
338void do_IRQ(struct pt_regs *regs)
339{
340 struct pt_regs *old_regs = set_irq_regs(regs);
341 unsigned int irq;
342
330 trace_irq_entry(regs);
331
332 irq_enter();
333
334 check_stack_overflow();
335
336 irq = ppc_md.get_irq();
337
338 if (irq != NO_IRQ && irq != NO_IRQ_IGNORE)
339 handle_one_irq(irq);

--- 7 unchanged lines hidden (view full) ---

347#ifdef CONFIG_PPC_ISERIES
348 if (firmware_has_feature(FW_FEATURE_ISERIES) &&
349 get_lppaca()->int_dword.fields.decr_int) {
350 get_lppaca()->int_dword.fields.decr_int = 0;
351 /* Signal a fake decrementer interrupt */
352 timer_interrupt(regs);
353 }
354#endif
343 irq_enter();
344
345 check_stack_overflow();
346
347 irq = ppc_md.get_irq();
348
349 if (irq != NO_IRQ && irq != NO_IRQ_IGNORE)
350 handle_one_irq(irq);

--- 7 unchanged lines hidden (view full) ---

358#ifdef CONFIG_PPC_ISERIES
359 if (firmware_has_feature(FW_FEATURE_ISERIES) &&
360 get_lppaca()->int_dword.fields.decr_int) {
361 get_lppaca()->int_dword.fields.decr_int = 0;
362 /* Signal a fake decrementer interrupt */
363 timer_interrupt(regs);
364 }
365#endif
355
356 trace_irq_exit(regs);
357}
358
359void __init init_IRQ(void)
360{
361 if (ppc_md.init_IRQ)
362 ppc_md.init_IRQ();
363
364 exc_lvl_ctx_init();

--- 171 unchanged lines hidden (view full) ---

536 /* setup us as the host for all legacy interrupts */
537 for (i = 1; i < NUM_ISA_INTERRUPTS; i++) {
538 irq_map[i].hwirq = i;
539 smp_wmb();
540 irq_map[i].host = host;
541 smp_wmb();
542
543 /* Clear norequest flags */
366}
367
368void __init init_IRQ(void)
369{
370 if (ppc_md.init_IRQ)
371 ppc_md.init_IRQ();
372
373 exc_lvl_ctx_init();

--- 171 unchanged lines hidden (view full) ---

545 /* setup us as the host for all legacy interrupts */
546 for (i = 1; i < NUM_ISA_INTERRUPTS; i++) {
547 irq_map[i].hwirq = i;
548 smp_wmb();
549 irq_map[i].host = host;
550 smp_wmb();
551
552 /* Clear norequest flags */
544 get_irq_desc(i)->status &= ~IRQ_NOREQUEST;
553 irq_to_desc(i)->status &= ~IRQ_NOREQUEST;
545
546 /* Legacy flags are left to default at this point,
547 * one can then use irq_create_mapping() to
548 * explicitly change them
549 */
550 ops->map(host, i, i);
551 }
552 break;

--- 49 unchanged lines hidden (view full) ---

602 BUG_ON(count < NUM_ISA_INTERRUPTS);
603 if (count < NR_IRQS)
604 irq_virq_count = count;
605}
606
607static int irq_setup_virq(struct irq_host *host, unsigned int virq,
608 irq_hw_number_t hwirq)
609{
554
555 /* Legacy flags are left to default at this point,
556 * one can then use irq_create_mapping() to
557 * explicitly change them
558 */
559 ops->map(host, i, i);
560 }
561 break;

--- 49 unchanged lines hidden (view full) ---

611 BUG_ON(count < NUM_ISA_INTERRUPTS);
612 if (count < NR_IRQS)
613 irq_virq_count = count;
614}
615
616static int irq_setup_virq(struct irq_host *host, unsigned int virq,
617 irq_hw_number_t hwirq)
618{
619 struct irq_desc *desc;
620
621 desc = irq_to_desc_alloc_node(virq, 0);
622 if (!desc) {
623 pr_debug("irq: -> allocating desc failed\n");
624 goto error;
625 }
626
610 /* Clear IRQ_NOREQUEST flag */
627 /* Clear IRQ_NOREQUEST flag */
611 get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
628 desc->status &= ~IRQ_NOREQUEST;
612
613 /* map it */
614 smp_wmb();
615 irq_map[virq].hwirq = hwirq;
616 smp_mb();
617
618 if (host->ops->map(host, virq, hwirq)) {
619 pr_debug("irq: -> mapping failed, freeing\n");
629
630 /* map it */
631 smp_wmb();
632 irq_map[virq].hwirq = hwirq;
633 smp_mb();
634
635 if (host->ops->map(host, virq, hwirq)) {
636 pr_debug("irq: -> mapping failed, freeing\n");
620 irq_free_virt(virq, 1);
621 return -1;
637 goto error;
622 }
623
624 return 0;
638 }
639
640 return 0;
641
642error:
643 irq_free_virt(virq, 1);
644 return -1;
625}
626
627unsigned int irq_create_direct_mapping(struct irq_host *host)
628{
629 unsigned int virq;
630
631 if (host == NULL)
632 host = irq_default_host;

--- 67 unchanged lines hidden (view full) ---

700 printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n",
701 hwirq, host->of_node ? host->of_node->full_name : "null", virq);
702
703 return virq;
704}
705EXPORT_SYMBOL_GPL(irq_create_mapping);
706
707unsigned int irq_create_of_mapping(struct device_node *controller,
645}
646
647unsigned int irq_create_direct_mapping(struct irq_host *host)
648{
649 unsigned int virq;
650
651 if (host == NULL)
652 host = irq_default_host;

--- 67 unchanged lines hidden (view full) ---

720 printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n",
721 hwirq, host->of_node ? host->of_node->full_name : "null", virq);
722
723 return virq;
724}
725EXPORT_SYMBOL_GPL(irq_create_mapping);
726
727unsigned int irq_create_of_mapping(struct device_node *controller,
708 u32 *intspec, unsigned int intsize)
728 const u32 *intspec, unsigned int intsize)
709{
710 struct irq_host *host;
711 irq_hw_number_t hwirq;
712 unsigned int type = IRQ_TYPE_NONE;
713 unsigned int virq;
714
715 if (controller == NULL)
716 host = irq_default_host;

--- 16 unchanged lines hidden (view full) ---

733
734 /* Create mapping */
735 virq = irq_create_mapping(host, hwirq);
736 if (virq == NO_IRQ)
737 return virq;
738
739 /* Set type if specified and different than the current one */
740 if (type != IRQ_TYPE_NONE &&
729{
730 struct irq_host *host;
731 irq_hw_number_t hwirq;
732 unsigned int type = IRQ_TYPE_NONE;
733 unsigned int virq;
734
735 if (controller == NULL)
736 host = irq_default_host;

--- 16 unchanged lines hidden (view full) ---

753
754 /* Create mapping */
755 virq = irq_create_mapping(host, hwirq);
756 if (virq == NO_IRQ)
757 return virq;
758
759 /* Set type if specified and different than the current one */
760 if (type != IRQ_TYPE_NONE &&
741 type != (get_irq_desc(virq)->status & IRQF_TRIGGER_MASK))
761 type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
742 set_irq_type(virq, type);
743 return virq;
744}
745EXPORT_SYMBOL_GPL(irq_create_of_mapping);
746
747unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
748{
749 struct of_irq oirq;

--- 55 unchanged lines hidden (view full) ---

805 break;
806 }
807
808 /* Destroy map */
809 smp_mb();
810 irq_map[virq].hwirq = host->inval_irq;
811
812 /* Set some flags */
762 set_irq_type(virq, type);
763 return virq;
764}
765EXPORT_SYMBOL_GPL(irq_create_of_mapping);
766
767unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
768{
769 struct of_irq oirq;

--- 55 unchanged lines hidden (view full) ---

825 break;
826 }
827
828 /* Destroy map */
829 smp_mb();
830 irq_map[virq].hwirq = host->inval_irq;
831
832 /* Set some flags */
813 get_irq_desc(virq)->status |= IRQ_NOREQUEST;
833 irq_to_desc(virq)->status |= IRQ_NOREQUEST;
814
815 /* Free it */
816 irq_free_virt(virq, 1);
817}
818EXPORT_SYMBOL_GPL(irq_dispose_mapping);
819
820unsigned int irq_find_mapping(struct irq_host *host,
821 irq_hw_number_t hwirq)

--- 175 unchanged lines hidden (view full) ---

997 host = irq_map[i].host;
998 irq_map[i].hwirq = host->inval_irq;
999 smp_wmb();
1000 irq_map[i].host = NULL;
1001 }
1002 spin_unlock_irqrestore(&irq_big_lock, flags);
1003}
1004
834
835 /* Free it */
836 irq_free_virt(virq, 1);
837}
838EXPORT_SYMBOL_GPL(irq_dispose_mapping);
839
840unsigned int irq_find_mapping(struct irq_host *host,
841 irq_hw_number_t hwirq)

--- 175 unchanged lines hidden (view full) ---

1017 host = irq_map[i].host;
1018 irq_map[i].hwirq = host->inval_irq;
1019 smp_wmb();
1020 irq_map[i].host = NULL;
1021 }
1022 spin_unlock_irqrestore(&irq_big_lock, flags);
1023}
1024
1005void irq_early_init(void)
1025int arch_early_irq_init(void)
1006{
1026{
1007 unsigned int i;
1027 struct irq_desc *desc;
1028 int i;
1008
1029
1009 for (i = 0; i < NR_IRQS; i++)
1010 get_irq_desc(i)->status |= IRQ_NOREQUEST;
1030 for (i = 0; i < NR_IRQS; i++) {
1031 desc = irq_to_desc(i);
1032 if (desc)
1033 desc->status |= IRQ_NOREQUEST;
1034 }
1035
1036 return 0;
1011}
1012
1037}
1038
1039int arch_init_chip_data(struct irq_desc *desc, int node)
1040{
1041 desc->status |= IRQ_NOREQUEST;
1042 return 0;
1043}
1044
1013/* We need to create the radix trees late */
1014static int irq_late_init(void)
1015{
1016 struct irq_host *h;
1017 unsigned int i;
1018
1019 /*
1020 * No mutual exclusion with respect to accessors of the tree is needed

--- 43 unchanged lines hidden (view full) ---

1064 struct irq_desc *desc;
1065 const char *p;
1066 char none[] = "none";
1067 int i;
1068
1069 seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq",
1070 "chip name", "host name");
1071
1045/* We need to create the radix trees late */
1046static int irq_late_init(void)
1047{
1048 struct irq_host *h;
1049 unsigned int i;
1050
1051 /*
1052 * No mutual exclusion with respect to accessors of the tree is needed

--- 43 unchanged lines hidden (view full) ---

1096 struct irq_desc *desc;
1097 const char *p;
1098 char none[] = "none";
1099 int i;
1100
1101 seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq",
1102 "chip name", "host name");
1103
1072 for (i = 1; i < NR_IRQS; i++) {
1073 desc = get_irq_desc(i);
1104 for (i = 1; i < nr_irqs; i++) {
1105 desc = irq_to_desc(i);
1106 if (!desc)
1107 continue;
1108
1074 spin_lock_irqsave(&desc->lock, flags);
1075
1076 if (desc->action && desc->action->handler) {
1077 seq_printf(m, "%5d ", i);
1078 seq_printf(m, "0x%05lx ", virq_to_hw(i));
1079
1109 spin_lock_irqsave(&desc->lock, flags);
1110
1111 if (desc->action && desc->action->handler) {
1112 seq_printf(m, "%5d ", i);
1113 seq_printf(m, "0x%05lx ", virq_to_hw(i));
1114
1080 if (desc->chip && desc->chip->typename)
1081 p = desc->chip->typename;
1115 if (desc->chip && desc->chip->name)
1116 p = desc->chip->name;
1082 else
1083 p = none;
1084 seq_printf(m, "%-15s ", p);
1085
1086 if (irq_map[i].host && irq_map[i].host->of_node)
1087 p = irq_map[i].host->of_node->full_name;
1088 else
1089 p = none;

--- 41 unchanged lines hidden ---
1117 else
1118 p = none;
1119 seq_printf(m, "%-15s ", p);
1120
1121 if (irq_map[i].host && irq_map[i].host->of_node)
1122 p = irq_map[i].host->of_node->full_name;
1123 else
1124 p = none;

--- 41 unchanged lines hidden ---