diff options
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r-- | arch/i386/kernel/io_apic.c | 125 |
1 files changed, 67 insertions, 58 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 4fb32c551fe0..fd0df75cfbda 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/nmi.h> | 40 | #include <asm/nmi.h> |
41 | 41 | ||
42 | #include <mach_apic.h> | 42 | #include <mach_apic.h> |
43 | #include <mach_apicdef.h> | ||
43 | 44 | ||
44 | #include "io_ports.h" | 45 | #include "io_ports.h" |
45 | 46 | ||
@@ -65,7 +66,7 @@ int sis_apic_bug = -1; | |||
65 | */ | 66 | */ |
66 | int nr_ioapic_registers[MAX_IO_APICS]; | 67 | int nr_ioapic_registers[MAX_IO_APICS]; |
67 | 68 | ||
68 | int disable_timer_pin_1 __initdata; | 69 | static int disable_timer_pin_1 __initdata; |
69 | 70 | ||
70 | /* | 71 | /* |
71 | * Rough estimation of how many shared IRQs there are, can | 72 | * Rough estimation of how many shared IRQs there are, can |
@@ -93,6 +94,34 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1}; | |||
93 | #define vector_to_irq(vector) (vector) | 94 | #define vector_to_irq(vector) (vector) |
94 | #endif | 95 | #endif |
95 | 96 | ||
97 | |||
98 | union entry_union { | ||
99 | struct { u32 w1, w2; }; | ||
100 | struct IO_APIC_route_entry entry; | ||
101 | }; | ||
102 | |||
103 | static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) | ||
104 | { | ||
105 | union entry_union eu; | ||
106 | unsigned long flags; | ||
107 | spin_lock_irqsave(&ioapic_lock, flags); | ||
108 | eu.w1 = io_apic_read(apic, 0x10 + 2 * pin); | ||
109 | eu.w2 = io_apic_read(apic, 0x11 + 2 * pin); | ||
110 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
111 | return eu.entry; | ||
112 | } | ||
113 | |||
114 | static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | ||
115 | { | ||
116 | unsigned long flags; | ||
117 | union entry_union eu; | ||
118 | eu.entry = e; | ||
119 | spin_lock_irqsave(&ioapic_lock, flags); | ||
120 | io_apic_write(apic, 0x10 + 2*pin, eu.w1); | ||
121 | io_apic_write(apic, 0x11 + 2*pin, eu.w2); | ||
122 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
123 | } | ||
124 | |||
96 | /* | 125 | /* |
97 | * The common case is 1:1 IRQ<->pin mappings. Sometimes there are | 126 | * The common case is 1:1 IRQ<->pin mappings. Sometimes there are |
98 | * shared ISA-space IRQs, so we have to support them. We are super | 127 | * shared ISA-space IRQs, so we have to support them. We are super |
@@ -200,13 +229,9 @@ static void unmask_IO_APIC_irq (unsigned int irq) | |||
200 | static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) | 229 | static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) |
201 | { | 230 | { |
202 | struct IO_APIC_route_entry entry; | 231 | struct IO_APIC_route_entry entry; |
203 | unsigned long flags; | ||
204 | 232 | ||
205 | /* Check delivery_mode to be sure we're not clearing an SMI pin */ | 233 | /* Check delivery_mode to be sure we're not clearing an SMI pin */ |
206 | spin_lock_irqsave(&ioapic_lock, flags); | 234 | entry = ioapic_read_entry(apic, pin); |
207 | *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); | ||
208 | *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin); | ||
209 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
210 | if (entry.delivery_mode == dest_SMI) | 235 | if (entry.delivery_mode == dest_SMI) |
211 | return; | 236 | return; |
212 | 237 | ||
@@ -215,10 +240,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) | |||
215 | */ | 240 | */ |
216 | memset(&entry, 0, sizeof(entry)); | 241 | memset(&entry, 0, sizeof(entry)); |
217 | entry.mask = 1; | 242 | entry.mask = 1; |
218 | spin_lock_irqsave(&ioapic_lock, flags); | 243 | ioapic_write_entry(apic, pin, entry); |
219 | io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0)); | ||
220 | io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1)); | ||
221 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
222 | } | 244 | } |
223 | 245 | ||
224 | static void clear_IO_APIC (void) | 246 | static void clear_IO_APIC (void) |
@@ -1283,9 +1305,8 @@ static void __init setup_IO_APIC_irqs(void) | |||
1283 | if (!apic && (irq < 16)) | 1305 | if (!apic && (irq < 16)) |
1284 | disable_8259A_irq(irq); | 1306 | disable_8259A_irq(irq); |
1285 | } | 1307 | } |
1308 | ioapic_write_entry(apic, pin, entry); | ||
1286 | spin_lock_irqsave(&ioapic_lock, flags); | 1309 | spin_lock_irqsave(&ioapic_lock, flags); |
1287 | io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); | ||
1288 | io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); | ||
1289 | set_native_irq_info(irq, TARGET_CPUS); | 1310 | set_native_irq_info(irq, TARGET_CPUS); |
1290 | spin_unlock_irqrestore(&ioapic_lock, flags); | 1311 | spin_unlock_irqrestore(&ioapic_lock, flags); |
1291 | } | 1312 | } |
@@ -1301,7 +1322,6 @@ static void __init setup_IO_APIC_irqs(void) | |||
1301 | static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector) | 1322 | static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector) |
1302 | { | 1323 | { |
1303 | struct IO_APIC_route_entry entry; | 1324 | struct IO_APIC_route_entry entry; |
1304 | unsigned long flags; | ||
1305 | 1325 | ||
1306 | memset(&entry,0,sizeof(entry)); | 1326 | memset(&entry,0,sizeof(entry)); |
1307 | 1327 | ||
@@ -1331,10 +1351,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in | |||
1331 | /* | 1351 | /* |
1332 | * Add it to the IO-APIC irq-routing table: | 1352 | * Add it to the IO-APIC irq-routing table: |
1333 | */ | 1353 | */ |
1334 | spin_lock_irqsave(&ioapic_lock, flags); | 1354 | ioapic_write_entry(apic, pin, entry); |
1335 | io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); | ||
1336 | io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); | ||
1337 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
1338 | 1355 | ||
1339 | enable_8259A_irq(0); | 1356 | enable_8259A_irq(0); |
1340 | } | 1357 | } |
@@ -1444,10 +1461,7 @@ void __init print_IO_APIC(void) | |||
1444 | for (i = 0; i <= reg_01.bits.entries; i++) { | 1461 | for (i = 0; i <= reg_01.bits.entries; i++) { |
1445 | struct IO_APIC_route_entry entry; | 1462 | struct IO_APIC_route_entry entry; |
1446 | 1463 | ||
1447 | spin_lock_irqsave(&ioapic_lock, flags); | 1464 | entry = ioapic_read_entry(apic, i); |
1448 | *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2); | ||
1449 | *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2); | ||
1450 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
1451 | 1465 | ||
1452 | printk(KERN_DEBUG " %02x %03X %02X ", | 1466 | printk(KERN_DEBUG " %02x %03X %02X ", |
1453 | i, | 1467 | i, |
@@ -1666,10 +1680,7 @@ static void __init enable_IO_APIC(void) | |||
1666 | /* See if any of the pins is in ExtINT mode */ | 1680 | /* See if any of the pins is in ExtINT mode */ |
1667 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { | 1681 | for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { |
1668 | struct IO_APIC_route_entry entry; | 1682 | struct IO_APIC_route_entry entry; |
1669 | spin_lock_irqsave(&ioapic_lock, flags); | 1683 | entry = ioapic_read_entry(apic, pin); |
1670 | *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); | ||
1671 | *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin); | ||
1672 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
1673 | 1684 | ||
1674 | 1685 | ||
1675 | /* If the interrupt line is enabled and in ExtInt mode | 1686 | /* If the interrupt line is enabled and in ExtInt mode |
@@ -1726,7 +1737,6 @@ void disable_IO_APIC(void) | |||
1726 | */ | 1737 | */ |
1727 | if (ioapic_i8259.pin != -1) { | 1738 | if (ioapic_i8259.pin != -1) { |
1728 | struct IO_APIC_route_entry entry; | 1739 | struct IO_APIC_route_entry entry; |
1729 | unsigned long flags; | ||
1730 | 1740 | ||
1731 | memset(&entry, 0, sizeof(entry)); | 1741 | memset(&entry, 0, sizeof(entry)); |
1732 | entry.mask = 0; /* Enabled */ | 1742 | entry.mask = 0; /* Enabled */ |
@@ -1743,12 +1753,7 @@ void disable_IO_APIC(void) | |||
1743 | /* | 1753 | /* |
1744 | * Add it to the IO-APIC irq-routing table: | 1754 | * Add it to the IO-APIC irq-routing table: |
1745 | */ | 1755 | */ |
1746 | spin_lock_irqsave(&ioapic_lock, flags); | 1756 | ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry); |
1747 | io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin, | ||
1748 | *(((int *)&entry)+1)); | ||
1749 | io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin, | ||
1750 | *(((int *)&entry)+0)); | ||
1751 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
1752 | } | 1757 | } |
1753 | disconnect_bsp_APIC(ioapic_i8259.pin != -1); | 1758 | disconnect_bsp_APIC(ioapic_i8259.pin != -1); |
1754 | } | 1759 | } |
@@ -2213,17 +2218,13 @@ static inline void unlock_ExtINT_logic(void) | |||
2213 | int apic, pin, i; | 2218 | int apic, pin, i; |
2214 | struct IO_APIC_route_entry entry0, entry1; | 2219 | struct IO_APIC_route_entry entry0, entry1; |
2215 | unsigned char save_control, save_freq_select; | 2220 | unsigned char save_control, save_freq_select; |
2216 | unsigned long flags; | ||
2217 | 2221 | ||
2218 | pin = find_isa_irq_pin(8, mp_INT); | 2222 | pin = find_isa_irq_pin(8, mp_INT); |
2219 | apic = find_isa_irq_apic(8, mp_INT); | 2223 | apic = find_isa_irq_apic(8, mp_INT); |
2220 | if (pin == -1) | 2224 | if (pin == -1) |
2221 | return; | 2225 | return; |
2222 | 2226 | ||
2223 | spin_lock_irqsave(&ioapic_lock, flags); | 2227 | entry0 = ioapic_read_entry(apic, pin); |
2224 | *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin); | ||
2225 | *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin); | ||
2226 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
2227 | clear_IO_APIC_pin(apic, pin); | 2228 | clear_IO_APIC_pin(apic, pin); |
2228 | 2229 | ||
2229 | memset(&entry1, 0, sizeof(entry1)); | 2230 | memset(&entry1, 0, sizeof(entry1)); |
@@ -2236,10 +2237,7 @@ static inline void unlock_ExtINT_logic(void) | |||
2236 | entry1.trigger = 0; | 2237 | entry1.trigger = 0; |
2237 | entry1.vector = 0; | 2238 | entry1.vector = 0; |
2238 | 2239 | ||
2239 | spin_lock_irqsave(&ioapic_lock, flags); | 2240 | ioapic_write_entry(apic, pin, entry1); |
2240 | io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1)); | ||
2241 | io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0)); | ||
2242 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
2243 | 2241 | ||
2244 | save_control = CMOS_READ(RTC_CONTROL); | 2242 | save_control = CMOS_READ(RTC_CONTROL); |
2245 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); | 2243 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); |
@@ -2258,10 +2256,7 @@ static inline void unlock_ExtINT_logic(void) | |||
2258 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | 2256 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); |
2259 | clear_IO_APIC_pin(apic, pin); | 2257 | clear_IO_APIC_pin(apic, pin); |
2260 | 2258 | ||
2261 | spin_lock_irqsave(&ioapic_lock, flags); | 2259 | ioapic_write_entry(apic, pin, entry0); |
2262 | io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1)); | ||
2263 | io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0)); | ||
2264 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
2265 | } | 2260 | } |
2266 | 2261 | ||
2267 | int timer_uses_ioapic_pin_0; | 2262 | int timer_uses_ioapic_pin_0; |
@@ -2461,17 +2456,12 @@ static int ioapic_suspend(struct sys_device *dev, pm_message_t state) | |||
2461 | { | 2456 | { |
2462 | struct IO_APIC_route_entry *entry; | 2457 | struct IO_APIC_route_entry *entry; |
2463 | struct sysfs_ioapic_data *data; | 2458 | struct sysfs_ioapic_data *data; |
2464 | unsigned long flags; | ||
2465 | int i; | 2459 | int i; |
2466 | 2460 | ||
2467 | data = container_of(dev, struct sysfs_ioapic_data, dev); | 2461 | data = container_of(dev, struct sysfs_ioapic_data, dev); |
2468 | entry = data->entry; | 2462 | entry = data->entry; |
2469 | spin_lock_irqsave(&ioapic_lock, flags); | 2463 | for (i = 0; i < nr_ioapic_registers[dev->id]; i ++) |
2470 | for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) { | 2464 | entry[i] = ioapic_read_entry(dev->id, i); |
2471 | *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i); | ||
2472 | *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i); | ||
2473 | } | ||
2474 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
2475 | 2465 | ||
2476 | return 0; | 2466 | return 0; |
2477 | } | 2467 | } |
@@ -2493,11 +2483,9 @@ static int ioapic_resume(struct sys_device *dev) | |||
2493 | reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid; | 2483 | reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid; |
2494 | io_apic_write(dev->id, 0, reg_00.raw); | 2484 | io_apic_write(dev->id, 0, reg_00.raw); |
2495 | } | 2485 | } |
2496 | for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) { | ||
2497 | io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1)); | ||
2498 | io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0)); | ||
2499 | } | ||
2500 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2486 | spin_unlock_irqrestore(&ioapic_lock, flags); |
2487 | for (i = 0; i < nr_ioapic_registers[dev->id]; i ++) | ||
2488 | ioapic_write_entry(dev->id, i, entry[i]); | ||
2501 | 2489 | ||
2502 | return 0; | 2490 | return 0; |
2503 | } | 2491 | } |
@@ -2694,9 +2682,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a | |||
2694 | if (!ioapic && (irq < 16)) | 2682 | if (!ioapic && (irq < 16)) |
2695 | disable_8259A_irq(irq); | 2683 | disable_8259A_irq(irq); |
2696 | 2684 | ||
2685 | ioapic_write_entry(ioapic, pin, entry); | ||
2697 | spin_lock_irqsave(&ioapic_lock, flags); | 2686 | spin_lock_irqsave(&ioapic_lock, flags); |
2698 | io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); | ||
2699 | io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); | ||
2700 | set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS); | 2687 | set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS); |
2701 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2688 | spin_unlock_irqrestore(&ioapic_lock, flags); |
2702 | 2689 | ||
@@ -2704,3 +2691,25 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a | |||
2704 | } | 2691 | } |
2705 | 2692 | ||
2706 | #endif /* CONFIG_ACPI */ | 2693 | #endif /* CONFIG_ACPI */ |
2694 | |||
2695 | static int __init parse_disable_timer_pin_1(char *arg) | ||
2696 | { | ||
2697 | disable_timer_pin_1 = 1; | ||
2698 | return 0; | ||
2699 | } | ||
2700 | early_param("disable_timer_pin_1", parse_disable_timer_pin_1); | ||
2701 | |||
2702 | static int __init parse_enable_timer_pin_1(char *arg) | ||
2703 | { | ||
2704 | disable_timer_pin_1 = -1; | ||
2705 | return 0; | ||
2706 | } | ||
2707 | early_param("enable_timer_pin_1", parse_enable_timer_pin_1); | ||
2708 | |||
2709 | static int __init parse_noapic(char *arg) | ||
2710 | { | ||
2711 | /* disable IO-APIC */ | ||
2712 | disable_ioapic_setup(); | ||
2713 | return 0; | ||
2714 | } | ||
2715 | early_param("noapic", parse_noapic); | ||