diff options
author | Ingo Molnar <mingo@elte.hu> | 2006-10-04 05:16:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:25 -0400 |
commit | f29bd1ba68c8c6a0f50bd678bbd5a26674018f7c (patch) | |
tree | 5a2f6086397b94e9094fa065a344bcb7e6a05ac0 /arch/x86_64/kernel/io_apic.c | |
parent | 0271eb947db2704a0ff8be68d72915ab021d1ead (diff) |
[PATCH] genirq: convert the x86_64 architecture to irq-chips
This patch converts all the x86_64 PIC controllers layers to the new and
simpler irq-chip interrupt handling layer.
[mingo@elte.hu: The patch also enables the fasteoi handler for x86_64]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Roland Dreier <rolandd@cisco.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/io_apic.c')
-rw-r--r-- | arch/x86_64/kernel/io_apic.c | 130 |
1 files changed, 29 insertions, 101 deletions
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 | ||
635 | extern void (*interrupt[NR_IRQS])(void); | 635 | extern void (*interrupt[NR_IRQS])(void); |
636 | static struct hw_interrupt_type ioapic_level_type; | 636 | |
637 | static struct hw_interrupt_type ioapic_edge_type; | 637 | static 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 | ||
1188 | static unsigned int startup_edge_ioapic_irq(unsigned int irq) | 1190 | static 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 | /* | 1207 | static 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 | */ | ||
1210 | static 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 | */ | ||
1233 | static 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 | |||
1240 | static void end_level_ioapic_irq (unsigned int irq) | ||
1241 | { | ||
1242 | move_irq(irq); | ||
1243 | ack_APIC_irq(); | ||
1244 | } | ||
1245 | |||
1246 | #ifdef CONFIG_PCI_MSI | ||
1247 | static 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 | ||
1254 | static void ack_edge_ioapic_vector(unsigned int vector) | 1214 | static 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 | |||
1262 | static 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 | |||
1269 | static 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 | |||
1277 | static 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 | ||
1284 | static void unmask_IO_APIC_vector (unsigned int vector) | 1221 | static 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 | ||
1303 | static int ioapic_retrigger(unsigned int irq) | 1239 | static 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 | ||
1319 | static struct hw_interrupt_type ioapic_edge_type __read_mostly = { | 1257 | static 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 | ||
1333 | static struct hw_interrupt_type ioapic_level_type __read_mostly = { | 1262 | static 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 | ||
1347 | static inline void init_IO_APIC_traps(void) | 1275 | static 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 | } |