diff options
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r-- | arch/i386/kernel/io_apic.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index a62df3e764c5..72ae414e4d49 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/desc.h> | 38 | #include <asm/desc.h> |
39 | #include <asm/timer.h> | 39 | #include <asm/timer.h> |
40 | #include <asm/i8259.h> | 40 | #include <asm/i8259.h> |
41 | #include <asm/nmi.h> | ||
41 | 42 | ||
42 | #include <mach_apic.h> | 43 | #include <mach_apic.h> |
43 | 44 | ||
@@ -50,6 +51,7 @@ atomic_t irq_mis_count; | |||
50 | static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; | 51 | static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; |
51 | 52 | ||
52 | static DEFINE_SPINLOCK(ioapic_lock); | 53 | static DEFINE_SPINLOCK(ioapic_lock); |
54 | static DEFINE_SPINLOCK(vector_lock); | ||
53 | 55 | ||
54 | int timer_over_8254 __initdata = 1; | 56 | int timer_over_8254 __initdata = 1; |
55 | 57 | ||
@@ -1161,10 +1163,17 @@ u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 }; | |||
1161 | int assign_irq_vector(int irq) | 1163 | int assign_irq_vector(int irq) |
1162 | { | 1164 | { |
1163 | static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; | 1165 | static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; |
1166 | unsigned long flags; | ||
1167 | int vector; | ||
1168 | |||
1169 | BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS); | ||
1164 | 1170 | ||
1165 | BUG_ON(irq >= NR_IRQ_VECTORS); | 1171 | spin_lock_irqsave(&vector_lock, flags); |
1166 | if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) | 1172 | |
1173 | if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) { | ||
1174 | spin_unlock_irqrestore(&vector_lock, flags); | ||
1167 | return IO_APIC_VECTOR(irq); | 1175 | return IO_APIC_VECTOR(irq); |
1176 | } | ||
1168 | next: | 1177 | next: |
1169 | current_vector += 8; | 1178 | current_vector += 8; |
1170 | if (current_vector == SYSCALL_VECTOR) | 1179 | if (current_vector == SYSCALL_VECTOR) |
@@ -1172,16 +1181,21 @@ next: | |||
1172 | 1181 | ||
1173 | if (current_vector >= FIRST_SYSTEM_VECTOR) { | 1182 | if (current_vector >= FIRST_SYSTEM_VECTOR) { |
1174 | offset++; | 1183 | offset++; |
1175 | if (!(offset%8)) | 1184 | if (!(offset%8)) { |
1185 | spin_unlock_irqrestore(&vector_lock, flags); | ||
1176 | return -ENOSPC; | 1186 | return -ENOSPC; |
1187 | } | ||
1177 | current_vector = FIRST_DEVICE_VECTOR + offset; | 1188 | current_vector = FIRST_DEVICE_VECTOR + offset; |
1178 | } | 1189 | } |
1179 | 1190 | ||
1180 | vector_irq[current_vector] = irq; | 1191 | vector = current_vector; |
1192 | vector_irq[vector] = irq; | ||
1181 | if (irq != AUTO_ASSIGN) | 1193 | if (irq != AUTO_ASSIGN) |
1182 | IO_APIC_VECTOR(irq) = current_vector; | 1194 | IO_APIC_VECTOR(irq) = vector; |
1183 | 1195 | ||
1184 | return current_vector; | 1196 | spin_unlock_irqrestore(&vector_lock, flags); |
1197 | |||
1198 | return vector; | ||
1185 | } | 1199 | } |
1186 | 1200 | ||
1187 | static struct hw_interrupt_type ioapic_level_type; | 1201 | static struct hw_interrupt_type ioapic_level_type; |
@@ -1193,21 +1207,14 @@ static struct hw_interrupt_type ioapic_edge_type; | |||
1193 | 1207 | ||
1194 | static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger) | 1208 | static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger) |
1195 | { | 1209 | { |
1196 | if (use_pci_vector() && !platform_legacy_irq(irq)) { | 1210 | unsigned idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq; |
1197 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || | 1211 | |
1198 | trigger == IOAPIC_LEVEL) | 1212 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || |
1199 | irq_desc[vector].handler = &ioapic_level_type; | 1213 | trigger == IOAPIC_LEVEL) |
1200 | else | 1214 | irq_desc[idx].handler = &ioapic_level_type; |
1201 | irq_desc[vector].handler = &ioapic_edge_type; | 1215 | else |
1202 | set_intr_gate(vector, interrupt[vector]); | 1216 | irq_desc[idx].handler = &ioapic_edge_type; |
1203 | } else { | 1217 | set_intr_gate(vector, interrupt[idx]); |
1204 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || | ||
1205 | trigger == IOAPIC_LEVEL) | ||
1206 | irq_desc[irq].handler = &ioapic_level_type; | ||
1207 | else | ||
1208 | irq_desc[irq].handler = &ioapic_edge_type; | ||
1209 | set_intr_gate(vector, interrupt[irq]); | ||
1210 | } | ||
1211 | } | 1218 | } |
1212 | 1219 | ||
1213 | static void __init setup_IO_APIC_irqs(void) | 1220 | static void __init setup_IO_APIC_irqs(void) |