aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/kernel/i8259.c50
-rw-r--r--arch/x86_64/kernel/io_apic.c130
-rw-r--r--arch/x86_64/kernel/irq.c5
-rw-r--r--include/asm-x86_64/hw_irq.h2
4 files changed, 44 insertions, 143 deletions
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index 2dd51f364ea2..ae1101cd5252 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -121,42 +121,15 @@ void (*interrupt[NR_IRQS])(void) = {
121 * moves to arch independent land 121 * moves to arch independent land
122 */ 122 */
123 123
124DEFINE_SPINLOCK(i8259A_lock);
125
126static int i8259A_auto_eoi; 124static int i8259A_auto_eoi;
127 125DEFINE_SPINLOCK(i8259A_lock);
128static void end_8259A_irq (unsigned int irq)
129{
130 if (irq > 256) {
131 char var;
132 printk("return %p stack %p ti %p\n", __builtin_return_address(0), &var, task_thread_info(current));
133
134 BUG();
135 }
136
137 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
138 irq_desc[irq].action)
139 enable_8259A_irq(irq);
140}
141
142#define shutdown_8259A_irq disable_8259A_irq
143
144static void mask_and_ack_8259A(unsigned int); 126static void mask_and_ack_8259A(unsigned int);
145 127
146static unsigned int startup_8259A_irq(unsigned int irq) 128static struct irq_chip i8259A_chip = {
147{ 129 .name = "XT-PIC",
148 enable_8259A_irq(irq); 130 .mask = disable_8259A_irq,
149 return 0; /* never anything pending */ 131 .unmask = enable_8259A_irq,
150} 132 .mask_ack = mask_and_ack_8259A,
151
152static struct hw_interrupt_type i8259A_irq_type = {
153 .typename = "XT-PIC",
154 .startup = startup_8259A_irq,
155 .shutdown = shutdown_8259A_irq,
156 .enable = enable_8259A_irq,
157 .disable = disable_8259A_irq,
158 .ack = mask_and_ack_8259A,
159 .end = end_8259A_irq,
160}; 133};
161 134
162/* 135/*
@@ -231,7 +204,7 @@ void make_8259A_irq(unsigned int irq)
231{ 204{
232 disable_irq_nosync(irq); 205 disable_irq_nosync(irq);
233 io_apic_irqs &= ~(1<<irq); 206 io_apic_irqs &= ~(1<<irq);
234 irq_desc[irq].chip = &i8259A_irq_type; 207 set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
235 enable_irq(irq); 208 enable_irq(irq);
236} 209}
237 210
@@ -367,9 +340,9 @@ void init_8259A(int auto_eoi)
367 * in AEOI mode we just have to mask the interrupt 340 * in AEOI mode we just have to mask the interrupt
368 * when acking. 341 * when acking.
369 */ 342 */
370 i8259A_irq_type.ack = disable_8259A_irq; 343 i8259A_chip.mask_ack = disable_8259A_irq;
371 else 344 else
372 i8259A_irq_type.ack = mask_and_ack_8259A; 345 i8259A_chip.mask_ack = mask_and_ack_8259A;
373 346
374 udelay(100); /* wait for 8259A to initialize */ 347 udelay(100); /* wait for 8259A to initialize */
375 348
@@ -464,12 +437,13 @@ void __init init_ISA_irqs (void)
464 /* 437 /*
465 * 16 old-style INTA-cycle interrupts: 438 * 16 old-style INTA-cycle interrupts:
466 */ 439 */
467 irq_desc[i].chip = &i8259A_irq_type; 440 set_irq_chip_and_handler(i, &i8259A_chip,
441 handle_level_irq);
468 } else { 442 } else {
469 /* 443 /*
470 * 'high' PCI IRQs filled in on demand 444 * 'high' PCI IRQs filled in on demand
471 */ 445 */
472 irq_desc[i].chip = &no_irq_type; 446 irq_desc[i].chip = &no_irq_chip;
473 } 447 }
474 } 448 }
475} 449}
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 0491019d4c8d..e1d1b4217cb2 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -633,8 +633,8 @@ next:
633} 633}
634 634
635extern void (*interrupt[NR_IRQS])(void); 635extern void (*interrupt[NR_IRQS])(void);
636static struct hw_interrupt_type ioapic_level_type; 636
637static struct hw_interrupt_type ioapic_edge_type; 637static struct irq_chip ioapic_chip;
638 638
639#define IOAPIC_AUTO -1 639#define IOAPIC_AUTO -1
640#define IOAPIC_EDGE 0 640#define IOAPIC_EDGE 0
@@ -648,9 +648,11 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
648 648
649 if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || 649 if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
650 trigger == IOAPIC_LEVEL) 650 trigger == IOAPIC_LEVEL)
651 irq_desc[idx].chip = &ioapic_level_type; 651 set_irq_chip_and_handler(idx, &ioapic_chip,
652 handle_fasteoi_irq);
652 else 653 else
653 irq_desc[idx].chip = &ioapic_edge_type; 654 set_irq_chip_and_handler(idx, &ioapic_chip,
655 handle_edge_irq);
654 set_intr_gate(vector, interrupt[idx]); 656 set_intr_gate(vector, interrupt[idx]);
655} 657}
656 658
@@ -752,7 +754,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
752 * The timer IRQ doesn't have to know that behind the 754 * The timer IRQ doesn't have to know that behind the
753 * scene we have a 8259A-master in AEOI mode ... 755 * scene we have a 8259A-master in AEOI mode ...
754 */ 756 */
755 irq_desc[0].chip = &ioapic_edge_type; 757 set_irq_chip_and_handler(0, &ioapic_chip, handle_edge_irq);
756 758
757 /* 759 /*
758 * Add it to the IO-APIC irq-routing table: 760 * Add it to the IO-APIC irq-routing table:
@@ -1185,7 +1187,7 @@ static int __init timer_irq_works(void)
1185 * an edge even if it isn't on the 8259A... 1187 * an edge even if it isn't on the 8259A...
1186 */ 1188 */
1187 1189
1188static unsigned int startup_edge_ioapic_irq(unsigned int irq) 1190static unsigned int startup_ioapic_irq(unsigned int irq)
1189{ 1191{
1190 int was_pending = 0; 1192 int was_pending = 0;
1191 unsigned long flags; 1193 unsigned long flags;
@@ -1202,86 +1204,21 @@ static unsigned int startup_edge_ioapic_irq(unsigned int irq)
1202 return was_pending; 1204 return was_pending;
1203} 1205}
1204 1206
1205/* 1207static unsigned int startup_ioapic_vector(unsigned int vector)
1206 * Once we have recorded IRQ_PENDING already, we can mask the
1207 * interrupt for real. This prevents IRQ storms from unhandled
1208 * devices.
1209 */
1210static void ack_edge_ioapic_irq(unsigned int irq)
1211{
1212 move_irq(irq);
1213 if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
1214 == (IRQ_PENDING | IRQ_DISABLED))
1215 mask_IO_APIC_irq(irq);
1216 ack_APIC_irq();
1217}
1218
1219/*
1220 * Level triggered interrupts can just be masked,
1221 * and shutting down and starting up the interrupt
1222 * is the same as enabling and disabling them -- except
1223 * with a startup need to return a "was pending" value.
1224 *
1225 * Level triggered interrupts are special because we
1226 * do not touch any IO-APIC register while handling
1227 * them. We ack the APIC in the end-IRQ handler, not
1228 * in the start-IRQ-handler. Protection against reentrance
1229 * from the same interrupt is still provided, both by the
1230 * generic IRQ layer and by the fact that an unacked local
1231 * APIC does not accept IRQs.
1232 */
1233static unsigned int startup_level_ioapic_irq (unsigned int irq)
1234{
1235 unmask_IO_APIC_irq(irq);
1236
1237 return 0; /* don't check for pending */
1238}
1239
1240static void end_level_ioapic_irq (unsigned int irq)
1241{
1242 move_irq(irq);
1243 ack_APIC_irq();
1244}
1245
1246#ifdef CONFIG_PCI_MSI
1247static unsigned int startup_edge_ioapic_vector(unsigned int vector)
1248{ 1208{
1249 int irq = vector_to_irq(vector); 1209 int irq = vector_to_irq(vector);
1250 1210
1251 return startup_edge_ioapic_irq(irq); 1211 return startup_ioapic_irq(irq);
1252} 1212}
1253 1213
1254static void ack_edge_ioapic_vector(unsigned int vector) 1214static void mask_ioapic_vector (unsigned int vector)
1255{
1256 int irq = vector_to_irq(vector);
1257
1258 move_native_irq(vector);
1259 ack_edge_ioapic_irq(irq);
1260}
1261
1262static unsigned int startup_level_ioapic_vector (unsigned int vector)
1263{
1264 int irq = vector_to_irq(vector);
1265
1266 return startup_level_ioapic_irq (irq);
1267}
1268
1269static void end_level_ioapic_vector (unsigned int vector)
1270{
1271 int irq = vector_to_irq(vector);
1272
1273 move_native_irq(vector);
1274 end_level_ioapic_irq(irq);
1275}
1276
1277static void mask_IO_APIC_vector (unsigned int vector)
1278{ 1215{
1279 int irq = vector_to_irq(vector); 1216 int irq = vector_to_irq(vector);
1280 1217
1281 mask_IO_APIC_irq(irq); 1218 mask_IO_APIC_irq(irq);
1282} 1219}
1283 1220
1284static void unmask_IO_APIC_vector (unsigned int vector) 1221static void unmask_ioapic_vector (unsigned int vector)
1285{ 1222{
1286 int irq = vector_to_irq(vector); 1223 int irq = vector_to_irq(vector);
1287 1224
@@ -1298,10 +1235,11 @@ static void set_ioapic_affinity_vector (unsigned int vector,
1298 set_ioapic_affinity_irq(irq, cpu_mask); 1235 set_ioapic_affinity_irq(irq, cpu_mask);
1299} 1236}
1300#endif // CONFIG_SMP 1237#endif // CONFIG_SMP
1301#endif // CONFIG_PCI_MSI
1302 1238
1303static int ioapic_retrigger(unsigned int irq) 1239static int ioapic_retrigger_vector(unsigned int vector)
1304{ 1240{
1241 int irq = vector_to_irq(vector);
1242
1305 send_IPI_self(IO_APIC_VECTOR(irq)); 1243 send_IPI_self(IO_APIC_VECTOR(irq));
1306 1244
1307 return 1; 1245 return 1;
@@ -1316,32 +1254,22 @@ static int ioapic_retrigger(unsigned int irq)
1316 * races. 1254 * races.
1317 */ 1255 */
1318 1256
1319static struct hw_interrupt_type ioapic_edge_type __read_mostly = { 1257static void ack_apic(unsigned int vector)
1320 .typename = "IO-APIC-edge", 1258{
1321 .startup = startup_edge_ioapic, 1259 ack_APIC_irq();
1322 .shutdown = shutdown_edge_ioapic, 1260}
1323 .enable = enable_edge_ioapic,
1324 .disable = disable_edge_ioapic,
1325 .ack = ack_edge_ioapic,
1326 .end = end_edge_ioapic,
1327#ifdef CONFIG_SMP
1328 .set_affinity = set_ioapic_affinity,
1329#endif
1330 .retrigger = ioapic_retrigger,
1331};
1332 1261
1333static struct hw_interrupt_type ioapic_level_type __read_mostly = { 1262static struct irq_chip ioapic_chip __read_mostly = {
1334 .typename = "IO-APIC-level", 1263 .name = "IO-APIC",
1335 .startup = startup_level_ioapic, 1264 .startup = startup_ioapic_vector,
1336 .shutdown = shutdown_level_ioapic, 1265 .mask = mask_ioapic_vector,
1337 .enable = enable_level_ioapic, 1266 .unmask = unmask_ioapic_vector,
1338 .disable = disable_level_ioapic, 1267 .ack = ack_apic,
1339 .ack = mask_and_ack_level_ioapic, 1268 .eoi = ack_apic,
1340 .end = end_level_ioapic,
1341#ifdef CONFIG_SMP 1269#ifdef CONFIG_SMP
1342 .set_affinity = set_ioapic_affinity, 1270 .set_affinity = set_ioapic_affinity_vector,
1343#endif 1271#endif
1344 .retrigger = ioapic_retrigger, 1272 .retrigger = ioapic_retrigger_vector,
1345}; 1273};
1346 1274
1347static inline void init_IO_APIC_traps(void) 1275static inline void init_IO_APIC_traps(void)
@@ -1376,7 +1304,7 @@ static inline void init_IO_APIC_traps(void)
1376 make_8259A_irq(irq); 1304 make_8259A_irq(irq);
1377 else 1305 else
1378 /* Strange. Oh, well.. */ 1306 /* Strange. Oh, well.. */
1379 irq_desc[irq].chip = &no_irq_type; 1307 irq_desc[irq].chip = &no_irq_chip;
1380 } 1308 }
1381 } 1309 }
1382} 1310}
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index b3677e6ccc6e..609f97153b88 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -74,7 +74,8 @@ int show_interrupts(struct seq_file *p, void *v)
74 for_each_online_cpu(j) 74 for_each_online_cpu(j)
75 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); 75 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
76#endif 76#endif
77 seq_printf(p, " %14s", irq_desc[i].chip->typename); 77 seq_printf(p, " %8s", irq_desc[i].chip->name);
78 seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq));
78 79
79 seq_printf(p, " %s", action->name); 80 seq_printf(p, " %s", action->name);
80 for (action=action->next; action; action = action->next) 81 for (action=action->next; action; action = action->next)
@@ -117,7 +118,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
117#ifdef CONFIG_DEBUG_STACKOVERFLOW 118#ifdef CONFIG_DEBUG_STACKOVERFLOW
118 stack_overflow_check(regs); 119 stack_overflow_check(regs);
119#endif 120#endif
120 __do_IRQ(irq, regs); 121 generic_handle_irq(irq, regs);
121 irq_exit(); 122 irq_exit();
122 123
123 return 1; 124 return 1;
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index 48a4a5364e85..f5da94af9c41 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -19,8 +19,6 @@
19#include <asm/irq.h> 19#include <asm/irq.h>
20#include <linux/profile.h> 20#include <linux/profile.h>
21#include <linux/smp.h> 21#include <linux/smp.h>
22
23struct hw_interrupt_type;
24#endif 22#endif
25 23
26#define NMI_VECTOR 0x02 24#define NMI_VECTOR 0x02