diff options
Diffstat (limited to 'arch/x86/kernel/irq.c')
-rw-r--r-- | arch/x86/kernel/irq.c | 102 |
1 files changed, 29 insertions, 73 deletions
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 91fd0c70a18a..6c0802eb2f7f 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -4,9 +4,11 @@ | |||
4 | #include <linux/cpu.h> | 4 | #include <linux/cpu.h> |
5 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel_stat.h> | 6 | #include <linux/kernel_stat.h> |
7 | #include <linux/of.h> | ||
7 | #include <linux/seq_file.h> | 8 | #include <linux/seq_file.h> |
8 | #include <linux/smp.h> | 9 | #include <linux/smp.h> |
9 | #include <linux/ftrace.h> | 10 | #include <linux/ftrace.h> |
11 | #include <linux/delay.h> | ||
10 | 12 | ||
11 | #include <asm/apic.h> | 13 | #include <asm/apic.h> |
12 | #include <asm/io_apic.h> | 14 | #include <asm/io_apic.h> |
@@ -43,9 +45,9 @@ void ack_bad_irq(unsigned int irq) | |||
43 | 45 | ||
44 | #define irq_stats(x) (&per_cpu(irq_stat, x)) | 46 | #define irq_stats(x) (&per_cpu(irq_stat, x)) |
45 | /* | 47 | /* |
46 | * /proc/interrupts printing: | 48 | * /proc/interrupts printing for arch specific interrupts |
47 | */ | 49 | */ |
48 | static int show_other_interrupts(struct seq_file *p, int prec) | 50 | int arch_show_interrupts(struct seq_file *p, int prec) |
49 | { | 51 | { |
50 | int j; | 52 | int j; |
51 | 53 | ||
@@ -67,10 +69,10 @@ static int show_other_interrupts(struct seq_file *p, int prec) | |||
67 | for_each_online_cpu(j) | 69 | for_each_online_cpu(j) |
68 | seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs); | 70 | seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs); |
69 | seq_printf(p, " Performance monitoring interrupts\n"); | 71 | seq_printf(p, " Performance monitoring interrupts\n"); |
70 | seq_printf(p, "%*s: ", prec, "PND"); | 72 | seq_printf(p, "%*s: ", prec, "IWI"); |
71 | for_each_online_cpu(j) | 73 | for_each_online_cpu(j) |
72 | seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs); | 74 | seq_printf(p, "%10u ", irq_stats(j)->apic_irq_work_irqs); |
73 | seq_printf(p, " Performance pending work\n"); | 75 | seq_printf(p, " IRQ work interrupts\n"); |
74 | #endif | 76 | #endif |
75 | if (x86_platform_ipi_callback) { | 77 | if (x86_platform_ipi_callback) { |
76 | seq_printf(p, "%*s: ", prec, "PLT"); | 78 | seq_printf(p, "%*s: ", prec, "PLT"); |
@@ -121,59 +123,6 @@ static int show_other_interrupts(struct seq_file *p, int prec) | |||
121 | return 0; | 123 | return 0; |
122 | } | 124 | } |
123 | 125 | ||
124 | int show_interrupts(struct seq_file *p, void *v) | ||
125 | { | ||
126 | unsigned long flags, any_count = 0; | ||
127 | int i = *(loff_t *) v, j, prec; | ||
128 | struct irqaction *action; | ||
129 | struct irq_desc *desc; | ||
130 | |||
131 | if (i > nr_irqs) | ||
132 | return 0; | ||
133 | |||
134 | for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec) | ||
135 | j *= 10; | ||
136 | |||
137 | if (i == nr_irqs) | ||
138 | return show_other_interrupts(p, prec); | ||
139 | |||
140 | /* print header */ | ||
141 | if (i == 0) { | ||
142 | seq_printf(p, "%*s", prec + 8, ""); | ||
143 | for_each_online_cpu(j) | ||
144 | seq_printf(p, "CPU%-8d", j); | ||
145 | seq_putc(p, '\n'); | ||
146 | } | ||
147 | |||
148 | desc = irq_to_desc(i); | ||
149 | if (!desc) | ||
150 | return 0; | ||
151 | |||
152 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
153 | for_each_online_cpu(j) | ||
154 | any_count |= kstat_irqs_cpu(i, j); | ||
155 | action = desc->action; | ||
156 | if (!action && !any_count) | ||
157 | goto out; | ||
158 | |||
159 | seq_printf(p, "%*d: ", prec, i); | ||
160 | for_each_online_cpu(j) | ||
161 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | ||
162 | seq_printf(p, " %8s", desc->chip->name); | ||
163 | seq_printf(p, "-%-8s", desc->name); | ||
164 | |||
165 | if (action) { | ||
166 | seq_printf(p, " %s", action->name); | ||
167 | while ((action = action->next) != NULL) | ||
168 | seq_printf(p, ", %s", action->name); | ||
169 | } | ||
170 | |||
171 | seq_putc(p, '\n'); | ||
172 | out: | ||
173 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | /* | 126 | /* |
178 | * /proc/stat helpers | 127 | * /proc/stat helpers |
179 | */ | 128 | */ |
@@ -185,7 +134,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
185 | sum += irq_stats(cpu)->apic_timer_irqs; | 134 | sum += irq_stats(cpu)->apic_timer_irqs; |
186 | sum += irq_stats(cpu)->irq_spurious_count; | 135 | sum += irq_stats(cpu)->irq_spurious_count; |
187 | sum += irq_stats(cpu)->apic_perf_irqs; | 136 | sum += irq_stats(cpu)->apic_perf_irqs; |
188 | sum += irq_stats(cpu)->apic_pending_irqs; | 137 | sum += irq_stats(cpu)->apic_irq_work_irqs; |
189 | #endif | 138 | #endif |
190 | if (x86_platform_ipi_callback) | 139 | if (x86_platform_ipi_callback) |
191 | sum += irq_stats(cpu)->x86_platform_ipis; | 140 | sum += irq_stats(cpu)->x86_platform_ipis; |
@@ -234,7 +183,7 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs) | |||
234 | exit_idle(); | 183 | exit_idle(); |
235 | irq_enter(); | 184 | irq_enter(); |
236 | 185 | ||
237 | irq = __get_cpu_var(vector_irq)[vector]; | 186 | irq = __this_cpu_read(vector_irq[vector]); |
238 | 187 | ||
239 | if (!handle_irq(irq, regs)) { | 188 | if (!handle_irq(irq, regs)) { |
240 | ack_APIC_irq(); | 189 | ack_APIC_irq(); |
@@ -282,6 +231,8 @@ void fixup_irqs(void) | |||
282 | unsigned int irq, vector; | 231 | unsigned int irq, vector; |
283 | static int warned; | 232 | static int warned; |
284 | struct irq_desc *desc; | 233 | struct irq_desc *desc; |
234 | struct irq_data *data; | ||
235 | struct irq_chip *chip; | ||
285 | 236 | ||
286 | for_each_irq_desc(irq, desc) { | 237 | for_each_irq_desc(irq, desc) { |
287 | int break_affinity = 0; | 238 | int break_affinity = 0; |
@@ -296,9 +247,10 @@ void fixup_irqs(void) | |||
296 | /* interrupt's are disabled at this point */ | 247 | /* interrupt's are disabled at this point */ |
297 | raw_spin_lock(&desc->lock); | 248 | raw_spin_lock(&desc->lock); |
298 | 249 | ||
299 | affinity = desc->affinity; | 250 | data = irq_desc_get_irq_data(desc); |
300 | if (!irq_has_action(irq) || | 251 | affinity = data->affinity; |
301 | cpumask_equal(affinity, cpu_online_mask)) { | 252 | if (!irq_has_action(irq) || irqd_is_per_cpu(data) || |
253 | cpumask_subset(affinity, cpu_online_mask)) { | ||
302 | raw_spin_unlock(&desc->lock); | 254 | raw_spin_unlock(&desc->lock); |
303 | continue; | 255 | continue; |
304 | } | 256 | } |
@@ -315,16 +267,18 @@ void fixup_irqs(void) | |||
315 | affinity = cpu_all_mask; | 267 | affinity = cpu_all_mask; |
316 | } | 268 | } |
317 | 269 | ||
318 | if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->mask) | 270 | chip = irq_data_get_irq_chip(data); |
319 | desc->chip->mask(irq); | 271 | if (!irqd_can_move_in_process_context(data) && chip->irq_mask) |
272 | chip->irq_mask(data); | ||
320 | 273 | ||
321 | if (desc->chip->set_affinity) | 274 | if (chip->irq_set_affinity) |
322 | desc->chip->set_affinity(irq, affinity); | 275 | chip->irq_set_affinity(data, affinity, true); |
323 | else if (!(warned++)) | 276 | else if (!(warned++)) |
324 | set_affinity = 0; | 277 | set_affinity = 0; |
325 | 278 | ||
326 | if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->unmask) | 279 | if (!irqd_can_move_in_process_context(data) && |
327 | desc->chip->unmask(irq); | 280 | !irqd_irq_disabled(data) && chip->irq_unmask) |
281 | chip->irq_unmask(data); | ||
328 | 282 | ||
329 | raw_spin_unlock(&desc->lock); | 283 | raw_spin_unlock(&desc->lock); |
330 | 284 | ||
@@ -348,17 +302,19 @@ void fixup_irqs(void) | |||
348 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { | 302 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { |
349 | unsigned int irr; | 303 | unsigned int irr; |
350 | 304 | ||
351 | if (__get_cpu_var(vector_irq)[vector] < 0) | 305 | if (__this_cpu_read(vector_irq[vector]) < 0) |
352 | continue; | 306 | continue; |
353 | 307 | ||
354 | irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); | 308 | irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); |
355 | if (irr & (1 << (vector % 32))) { | 309 | if (irr & (1 << (vector % 32))) { |
356 | irq = __get_cpu_var(vector_irq)[vector]; | 310 | irq = __this_cpu_read(vector_irq[vector]); |
357 | 311 | ||
358 | desc = irq_to_desc(irq); | 312 | desc = irq_to_desc(irq); |
313 | data = irq_desc_get_irq_data(desc); | ||
314 | chip = irq_data_get_irq_chip(data); | ||
359 | raw_spin_lock(&desc->lock); | 315 | raw_spin_lock(&desc->lock); |
360 | if (desc->chip->retrigger) | 316 | if (chip->irq_retrigger) |
361 | desc->chip->retrigger(irq); | 317 | chip->irq_retrigger(data); |
362 | raw_spin_unlock(&desc->lock); | 318 | raw_spin_unlock(&desc->lock); |
363 | } | 319 | } |
364 | } | 320 | } |