aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/irq.c')
-rw-r--r--arch/x86/kernel/irq.c102
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 */
48static int show_other_interrupts(struct seq_file *p, int prec) 50int 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
124int 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');
172out:
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 }