]>
Commit | Line | Data |
---|---|---|
6b39ba77 TG |
1 | /* |
2 | * Common interrupt code for 32 and 64 bit | |
3 | */ | |
4 | #include <linux/cpu.h> | |
5 | #include <linux/interrupt.h> | |
6 | #include <linux/kernel_stat.h> | |
7 | #include <linux/seq_file.h> | |
8 | ||
9 | #include <asm/apic.h> | |
10 | #include <asm/io_apic.h> | |
11 | #include <asm/smp.h> | |
12 | ||
13 | atomic_t irq_err_count; | |
14 | ||
15 | #ifdef CONFIG_X86_32 | |
16 | # define irq_stats(x) (&per_cpu(irq_stat,x)) | |
17 | #else | |
18 | # define irq_stats(x) cpu_pda(x) | |
19 | #endif | |
20 | /* | |
21 | * /proc/interrupts printing: | |
22 | */ | |
23 | static int show_other_interrupts(struct seq_file *p) | |
24 | { | |
25 | int j; | |
26 | ||
27 | seq_printf(p, "NMI: "); | |
28 | for_each_online_cpu(j) | |
29 | seq_printf(p, "%10u ", irq_stats(j)->__nmi_count); | |
30 | seq_printf(p, " Non-maskable interrupts\n"); | |
31 | #ifdef CONFIG_X86_LOCAL_APIC | |
32 | seq_printf(p, "LOC: "); | |
33 | for_each_online_cpu(j) | |
34 | seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs); | |
35 | seq_printf(p, " Local timer interrupts\n"); | |
36 | #endif | |
37 | #ifdef CONFIG_SMP | |
38 | seq_printf(p, "RES: "); | |
39 | for_each_online_cpu(j) | |
40 | seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count); | |
41 | seq_printf(p, " Rescheduling interrupts\n"); | |
42 | seq_printf(p, "CAL: "); | |
43 | for_each_online_cpu(j) | |
44 | seq_printf(p, "%10u ", irq_stats(j)->irq_call_count); | |
45 | seq_printf(p, " Function call interrupts\n"); | |
46 | seq_printf(p, "TLB: "); | |
47 | for_each_online_cpu(j) | |
48 | seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); | |
49 | seq_printf(p, " TLB shootdowns\n"); | |
50 | #endif | |
51 | #ifdef CONFIG_X86_MCE | |
52 | seq_printf(p, "TRM: "); | |
53 | for_each_online_cpu(j) | |
54 | seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count); | |
55 | seq_printf(p, " Thermal event interrupts\n"); | |
56 | # ifdef CONFIG_X86_64 | |
57 | seq_printf(p, "THR: "); | |
58 | for_each_online_cpu(j) | |
59 | seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count); | |
60 | seq_printf(p, " Threshold APIC interrupts\n"); | |
61 | # endif | |
62 | #endif | |
63 | #ifdef CONFIG_X86_LOCAL_APIC | |
64 | seq_printf(p, "SPU: "); | |
65 | for_each_online_cpu(j) | |
66 | seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count); | |
67 | seq_printf(p, " Spurious interrupts\n"); | |
68 | #endif | |
69 | seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); | |
70 | #if defined(CONFIG_X86_IO_APIC) | |
71 | seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); | |
72 | #endif | |
73 | return 0; | |
74 | } | |
75 | ||
76 | int show_interrupts(struct seq_file *p, void *v) | |
77 | { | |
78 | unsigned long flags, any_count = 0; | |
79 | int i = *(loff_t *) v, j; | |
80 | struct irqaction *action; | |
81 | struct irq_desc *desc; | |
82 | ||
83 | if (i > nr_irqs) | |
84 | return 0; | |
85 | ||
86 | if (i == nr_irqs) | |
87 | return show_other_interrupts(p); | |
88 | ||
89 | /* print header */ | |
90 | if (i == 0) { | |
91 | seq_printf(p, " "); | |
92 | for_each_online_cpu(j) | |
93 | seq_printf(p, "CPU%-8d",j); | |
94 | seq_putc(p, '\n'); | |
95 | } | |
96 | ||
97 | desc = irq_to_desc(i); | |
98 | spin_lock_irqsave(&desc->lock, flags); | |
99 | #ifndef CONFIG_SMP | |
100 | any_count = kstat_irqs(i); | |
101 | #else | |
102 | for_each_online_cpu(j) | |
103 | any_count |= kstat_irqs_cpu(i, j); | |
104 | #endif | |
105 | action = desc->action; | |
106 | if (!action && !any_count) | |
107 | goto out; | |
108 | ||
109 | seq_printf(p, "%3d: ", i); | |
110 | #ifndef CONFIG_SMP | |
111 | seq_printf(p, "%10u ", kstat_irqs(i)); | |
112 | #else | |
113 | for_each_online_cpu(j) | |
114 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | |
115 | #endif | |
116 | seq_printf(p, " %8s", desc->chip->name); | |
117 | seq_printf(p, "-%-8s", desc->name); | |
118 | ||
119 | if (action) { | |
120 | seq_printf(p, " %s", action->name); | |
121 | while ((action = action->next) != NULL) | |
122 | seq_printf(p, ", %s", action->name); | |
123 | } | |
124 | ||
125 | seq_putc(p, '\n'); | |
126 | out: | |
127 | spin_unlock_irqrestore(&desc->lock, flags); | |
128 | return 0; | |
129 | } | |
130 | ||
131 | /* | |
132 | * /proc/stat helpers | |
133 | */ | |
134 | u64 arch_irq_stat_cpu(unsigned int cpu) | |
135 | { | |
136 | u64 sum = irq_stats(cpu)->__nmi_count; | |
137 | ||
138 | #ifdef CONFIG_X86_LOCAL_APIC | |
139 | sum += irq_stats(cpu)->apic_timer_irqs; | |
140 | #endif | |
141 | #ifdef CONFIG_SMP | |
142 | sum += irq_stats(cpu)->irq_resched_count; | |
143 | sum += irq_stats(cpu)->irq_call_count; | |
144 | sum += irq_stats(cpu)->irq_tlb_count; | |
145 | #endif | |
146 | #ifdef CONFIG_X86_MCE | |
147 | sum += irq_stats(cpu)->irq_thermal_count; | |
148 | # ifdef CONFIG_X86_64 | |
149 | sum += irq_stats(cpu)->irq_threshold_count; | |
150 | #endif | |
151 | #endif | |
152 | #ifdef CONFIG_X86_LOCAL_APIC | |
153 | sum += irq_stats(cpu)->irq_spurious_count; | |
154 | #endif | |
155 | return sum; | |
156 | } | |
157 | ||
158 | u64 arch_irq_stat(void) | |
159 | { | |
160 | u64 sum = atomic_read(&irq_err_count); | |
161 | ||
162 | #ifdef CONFIG_X86_IO_APIC | |
163 | sum += atomic_read(&irq_mis_count); | |
164 | #endif | |
165 | return sum; | |
166 | } |