aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/irq.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-04-06 03:02:57 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-06 03:02:57 -0400
commitf541ae326fa120fa5c57433e4d9a133df212ce41 (patch)
treebdbd94ec72cfc601118051cb35e8617d55510177 /arch/x86/kernel/irq.c
parente255357764f92afcafafbd4879b222b8c752065a (diff)
parent0221c81b1b8eb0cbb6b30a0ced52ead32d2b4e4c (diff)
Merge branch 'linus' into perfcounters/core-v2
Merge reason: we have gathered quite a few conflicts, need to merge upstream Conflicts: arch/powerpc/kernel/Makefile arch/x86/ia32/ia32entry.S arch/x86/include/asm/hardirq.h arch/x86/include/asm/unistd_32.h arch/x86/include/asm/unistd_64.h arch/x86/kernel/cpu/common.c arch/x86/kernel/irq.c arch/x86/kernel/syscall_table_32.S arch/x86/mm/iomap_32.c include/linux/sched.h kernel/Makefile Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/irq.c')
-rw-r--r--arch/x86/kernel/irq.c88
1 files changed, 57 insertions, 31 deletions
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 7c95c8918a8f..9c2754302ecc 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -15,6 +15,9 @@
15 15
16atomic_t irq_err_count; 16atomic_t irq_err_count;
17 17
18/* Function pointer for generic interrupt vector handling */
19void (*generic_interrupt_extension)(void) = NULL;
20
18/* 21/*
19 * 'what should we do if we get a hw irq event on an illegal vector'. 22 * 'what should we do if we get a hw irq event on an illegal vector'.
20 * each architecture has to answer this themselves. 23 * each architecture has to answer this themselves.
@@ -42,59 +45,64 @@ void ack_bad_irq(unsigned int irq)
42/* 45/*
43 * /proc/interrupts printing: 46 * /proc/interrupts printing:
44 */ 47 */
45static int show_other_interrupts(struct seq_file *p) 48static int show_other_interrupts(struct seq_file *p, int prec)
46{ 49{
47 int j; 50 int j;
48 51
49 seq_printf(p, "NMI: "); 52 seq_printf(p, "%*s: ", prec, "NMI");
50 for_each_online_cpu(j) 53 for_each_online_cpu(j)
51 seq_printf(p, "%10u ", irq_stats(j)->__nmi_count); 54 seq_printf(p, "%10u ", irq_stats(j)->__nmi_count);
52 seq_printf(p, " Non-maskable interrupts\n"); 55 seq_printf(p, " Non-maskable interrupts\n");
53#ifdef CONFIG_X86_LOCAL_APIC 56#ifdef CONFIG_X86_LOCAL_APIC
54 seq_printf(p, "LOC: "); 57 seq_printf(p, "%*s: ", prec, "LOC");
55 for_each_online_cpu(j) 58 for_each_online_cpu(j)
56 seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs); 59 seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
57 seq_printf(p, " Local timer interrupts\n"); 60 seq_printf(p, " Local timer interrupts\n");
61
62 seq_printf(p, "%*s: ", prec, "SPU");
63 for_each_online_cpu(j)
64 seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
65 seq_printf(p, " Spurious interrupts\n");
58 seq_printf(p, "CNT: "); 66 seq_printf(p, "CNT: ");
59 for_each_online_cpu(j) 67 for_each_online_cpu(j)
60 seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs); 68 seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
61 seq_printf(p, " Performance counter interrupts\n"); 69 seq_printf(p, " Performance counter interrupts\n");
62#endif 70#endif
71 if (generic_interrupt_extension) {
72 seq_printf(p, "PLT: ");
73 for_each_online_cpu(j)
74 seq_printf(p, "%10u ", irq_stats(j)->generic_irqs);
75 seq_printf(p, " Platform interrupts\n");
76 }
63#ifdef CONFIG_SMP 77#ifdef CONFIG_SMP
64 seq_printf(p, "RES: "); 78 seq_printf(p, "%*s: ", prec, "RES");
65 for_each_online_cpu(j) 79 for_each_online_cpu(j)
66 seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count); 80 seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
67 seq_printf(p, " Rescheduling interrupts\n"); 81 seq_printf(p, " Rescheduling interrupts\n");
68 seq_printf(p, "CAL: "); 82 seq_printf(p, "%*s: ", prec, "CAL");
69 for_each_online_cpu(j) 83 for_each_online_cpu(j)
70 seq_printf(p, "%10u ", irq_stats(j)->irq_call_count); 84 seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
71 seq_printf(p, " Function call interrupts\n"); 85 seq_printf(p, " Function call interrupts\n");
72 seq_printf(p, "TLB: "); 86 seq_printf(p, "%*s: ", prec, "TLB");
73 for_each_online_cpu(j) 87 for_each_online_cpu(j)
74 seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); 88 seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
75 seq_printf(p, " TLB shootdowns\n"); 89 seq_printf(p, " TLB shootdowns\n");
76#endif 90#endif
77#ifdef CONFIG_X86_MCE 91#ifdef CONFIG_X86_MCE
78 seq_printf(p, "TRM: "); 92 seq_printf(p, "%*s: ", prec, "TRM");
79 for_each_online_cpu(j) 93 for_each_online_cpu(j)
80 seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count); 94 seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
81 seq_printf(p, " Thermal event interrupts\n"); 95 seq_printf(p, " Thermal event interrupts\n");
82# ifdef CONFIG_X86_64 96# ifdef CONFIG_X86_64
83 seq_printf(p, "THR: "); 97 seq_printf(p, "%*s: ", prec, "THR");
84 for_each_online_cpu(j) 98 for_each_online_cpu(j)
85 seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count); 99 seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
86 seq_printf(p, " Threshold APIC interrupts\n"); 100 seq_printf(p, " Threshold APIC interrupts\n");
87# endif 101# endif
88#endif 102#endif
89#ifdef CONFIG_X86_LOCAL_APIC 103 seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
90 seq_printf(p, "SPU: ");
91 for_each_online_cpu(j)
92 seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
93 seq_printf(p, " Spurious interrupts\n");
94#endif
95 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
96#if defined(CONFIG_X86_IO_APIC) 104#if defined(CONFIG_X86_IO_APIC)
97 seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); 105 seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count));
98#endif 106#endif
99 return 0; 107 return 0;
100} 108}
@@ -102,19 +110,22 @@ static int show_other_interrupts(struct seq_file *p)
102int show_interrupts(struct seq_file *p, void *v) 110int show_interrupts(struct seq_file *p, void *v)
103{ 111{
104 unsigned long flags, any_count = 0; 112 unsigned long flags, any_count = 0;
105 int i = *(loff_t *) v, j; 113 int i = *(loff_t *) v, j, prec;
106 struct irqaction *action; 114 struct irqaction *action;
107 struct irq_desc *desc; 115 struct irq_desc *desc;
108 116
109 if (i > nr_irqs) 117 if (i > nr_irqs)
110 return 0; 118 return 0;
111 119
120 for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
121 j *= 10;
122
112 if (i == nr_irqs) 123 if (i == nr_irqs)
113 return show_other_interrupts(p); 124 return show_other_interrupts(p, prec);
114 125
115 /* print header */ 126 /* print header */
116 if (i == 0) { 127 if (i == 0) {
117 seq_printf(p, " "); 128 seq_printf(p, "%*s", prec + 8, "");
118 for_each_online_cpu(j) 129 for_each_online_cpu(j)
119 seq_printf(p, "CPU%-8d", j); 130 seq_printf(p, "CPU%-8d", j);
120 seq_putc(p, '\n'); 131 seq_putc(p, '\n');
@@ -125,23 +136,15 @@ int show_interrupts(struct seq_file *p, void *v)
125 return 0; 136 return 0;
126 137
127 spin_lock_irqsave(&desc->lock, flags); 138 spin_lock_irqsave(&desc->lock, flags);
128#ifndef CONFIG_SMP
129 any_count = kstat_irqs(i);
130#else
131 for_each_online_cpu(j) 139 for_each_online_cpu(j)
132 any_count |= kstat_irqs_cpu(i, j); 140 any_count |= kstat_irqs_cpu(i, j);
133#endif
134 action = desc->action; 141 action = desc->action;
135 if (!action && !any_count) 142 if (!action && !any_count)
136 goto out; 143 goto out;
137 144
138 seq_printf(p, "%3d: ", i); 145 seq_printf(p, "%*d: ", prec, i);
139#ifndef CONFIG_SMP
140 seq_printf(p, "%10u ", kstat_irqs(i));
141#else
142 for_each_online_cpu(j) 146 for_each_online_cpu(j)
143 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); 147 seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
144#endif
145 seq_printf(p, " %8s", desc->chip->name); 148 seq_printf(p, " %8s", desc->chip->name);
146 seq_printf(p, "-%-8s", desc->name); 149 seq_printf(p, "-%-8s", desc->name);
147 150
@@ -166,8 +169,11 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
166 169
167#ifdef CONFIG_X86_LOCAL_APIC 170#ifdef CONFIG_X86_LOCAL_APIC
168 sum += irq_stats(cpu)->apic_timer_irqs; 171 sum += irq_stats(cpu)->apic_timer_irqs;
172 sum += irq_stats(cpu)->irq_spurious_count;
169 sum += irq_stats(cpu)->apic_perf_irqs; 173 sum += irq_stats(cpu)->apic_perf_irqs;
170#endif 174#endif
175 if (generic_interrupt_extension)
176 sum += irq_stats(cpu)->generic_irqs;
171#ifdef CONFIG_SMP 177#ifdef CONFIG_SMP
172 sum += irq_stats(cpu)->irq_resched_count; 178 sum += irq_stats(cpu)->irq_resched_count;
173 sum += irq_stats(cpu)->irq_call_count; 179 sum += irq_stats(cpu)->irq_call_count;
@@ -179,9 +185,6 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
179 sum += irq_stats(cpu)->irq_threshold_count; 185 sum += irq_stats(cpu)->irq_threshold_count;
180#endif 186#endif
181#endif 187#endif
182#ifdef CONFIG_X86_LOCAL_APIC
183 sum += irq_stats(cpu)->irq_spurious_count;
184#endif
185 return sum; 188 return sum;
186} 189}
187 190
@@ -231,4 +234,27 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
231 return 1; 234 return 1;
232} 235}
233 236
237/*
238 * Handler for GENERIC_INTERRUPT_VECTOR.
239 */
240void smp_generic_interrupt(struct pt_regs *regs)
241{
242 struct pt_regs *old_regs = set_irq_regs(regs);
243
244 ack_APIC_irq();
245
246 exit_idle();
247
248 irq_enter();
249
250 inc_irq_stat(generic_irqs);
251
252 if (generic_interrupt_extension)
253 generic_interrupt_extension();
254
255 irq_exit();
256
257 set_irq_regs(old_regs);
258}
259
234EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); 260EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);