aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/io_apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r--arch/i386/kernel/io_apic.c125
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 */
66int nr_ioapic_registers[MAX_IO_APICS]; 67int nr_ioapic_registers[MAX_IO_APICS];
67 68
68int disable_timer_pin_1 __initdata; 69static 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
98union entry_union {
99 struct { u32 w1, w2; };
100 struct IO_APIC_route_entry entry;
101};
102
103static 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
114static 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)
200static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) 229static 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
224static void clear_IO_APIC (void) 246static 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)
1301static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector) 1322static 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
2267int timer_uses_ioapic_pin_0; 2262int 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
2695static int __init parse_disable_timer_pin_1(char *arg)
2696{
2697 disable_timer_pin_1 = 1;
2698 return 0;
2699}
2700early_param("disable_timer_pin_1", parse_disable_timer_pin_1);
2701
2702static int __init parse_enable_timer_pin_1(char *arg)
2703{
2704 disable_timer_pin_1 = -1;
2705 return 0;
2706}
2707early_param("enable_timer_pin_1", parse_enable_timer_pin_1);
2708
2709static int __init parse_noapic(char *arg)
2710{
2711 /* disable IO-APIC */
2712 disable_ioapic_setup();
2713 return 0;
2714}
2715early_param("noapic", parse_noapic);