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.c100
1 files changed, 43 insertions, 57 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 4eacd52eeb7..b713f27d7e8 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -94,6 +94,34 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
94#define vector_to_irq(vector) (vector) 94#define vector_to_irq(vector) (vector)
95#endif 95#endif
96 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
97/* 125/*
98 * 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
99 * 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
@@ -201,13 +229,9 @@ static void unmask_IO_APIC_irq (unsigned int irq)
201static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) 229static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
202{ 230{
203 struct IO_APIC_route_entry entry; 231 struct IO_APIC_route_entry entry;
204 unsigned long flags;
205 232
206 /* 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 */
207 spin_lock_irqsave(&ioapic_lock, flags); 234 entry = ioapic_read_entry(apic, pin);
208 *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
209 *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
210 spin_unlock_irqrestore(&ioapic_lock, flags);
211 if (entry.delivery_mode == dest_SMI) 235 if (entry.delivery_mode == dest_SMI)
212 return; 236 return;
213 237
@@ -216,10 +240,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
216 */ 240 */
217 memset(&entry, 0, sizeof(entry)); 241 memset(&entry, 0, sizeof(entry));
218 entry.mask = 1; 242 entry.mask = 1;
219 spin_lock_irqsave(&ioapic_lock, flags); 243 ioapic_write_entry(apic, pin, entry);
220 io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
221 io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
222 spin_unlock_irqrestore(&ioapic_lock, flags);
223} 244}
224 245
225static void clear_IO_APIC (void) 246static void clear_IO_APIC (void)
@@ -1284,9 +1305,8 @@ static void __init setup_IO_APIC_irqs(void)
1284 if (!apic && (irq < 16)) 1305 if (!apic && (irq < 16))
1285 disable_8259A_irq(irq); 1306 disable_8259A_irq(irq);
1286 } 1307 }
1308 ioapic_write_entry(apic, pin, entry);
1287 spin_lock_irqsave(&ioapic_lock, flags); 1309 spin_lock_irqsave(&ioapic_lock, flags);
1288 io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
1289 io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
1290 set_native_irq_info(irq, TARGET_CPUS); 1310 set_native_irq_info(irq, TARGET_CPUS);
1291 spin_unlock_irqrestore(&ioapic_lock, flags); 1311 spin_unlock_irqrestore(&ioapic_lock, flags);
1292 } 1312 }
@@ -1302,7 +1322,6 @@ static void __init setup_IO_APIC_irqs(void)
1302static 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)
1303{ 1323{
1304 struct IO_APIC_route_entry entry; 1324 struct IO_APIC_route_entry entry;
1305 unsigned long flags;
1306 1325
1307 memset(&entry,0,sizeof(entry)); 1326 memset(&entry,0,sizeof(entry));
1308 1327
@@ -1332,10 +1351,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
1332 /* 1351 /*
1333 * Add it to the IO-APIC irq-routing table: 1352 * Add it to the IO-APIC irq-routing table:
1334 */ 1353 */
1335 spin_lock_irqsave(&ioapic_lock, flags); 1354 ioapic_write_entry(apic, pin, entry);
1336 io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
1337 io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
1338 spin_unlock_irqrestore(&ioapic_lock, flags);
1339 1355
1340 enable_8259A_irq(0); 1356 enable_8259A_irq(0);
1341} 1357}
@@ -1445,10 +1461,7 @@ void __init print_IO_APIC(void)
1445 for (i = 0; i <= reg_01.bits.entries; i++) { 1461 for (i = 0; i <= reg_01.bits.entries; i++) {
1446 struct IO_APIC_route_entry entry; 1462 struct IO_APIC_route_entry entry;
1447 1463
1448 spin_lock_irqsave(&ioapic_lock, flags); 1464 entry = ioapic_read_entry(apic, i);
1449 *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
1450 *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
1451 spin_unlock_irqrestore(&ioapic_lock, flags);
1452 1465
1453 printk(KERN_DEBUG " %02x %03X %02X ", 1466 printk(KERN_DEBUG " %02x %03X %02X ",
1454 i, 1467 i,
@@ -1667,10 +1680,7 @@ static void __init enable_IO_APIC(void)
1667 /* See if any of the pins is in ExtINT mode */ 1680 /* See if any of the pins is in ExtINT mode */
1668 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { 1681 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
1669 struct IO_APIC_route_entry entry; 1682 struct IO_APIC_route_entry entry;
1670 spin_lock_irqsave(&ioapic_lock, flags); 1683 entry = ioapic_read_entry(apic, pin);
1671 *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
1672 *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
1673 spin_unlock_irqrestore(&ioapic_lock, flags);
1674 1684
1675 1685
1676 /* If the interrupt line is enabled and in ExtInt mode 1686 /* If the interrupt line is enabled and in ExtInt mode
@@ -1727,7 +1737,6 @@ void disable_IO_APIC(void)
1727 */ 1737 */
1728 if (ioapic_i8259.pin != -1) { 1738 if (ioapic_i8259.pin != -1) {
1729 struct IO_APIC_route_entry entry; 1739 struct IO_APIC_route_entry entry;
1730 unsigned long flags;
1731 1740
1732 memset(&entry, 0, sizeof(entry)); 1741 memset(&entry, 0, sizeof(entry));
1733 entry.mask = 0; /* Enabled */ 1742 entry.mask = 0; /* Enabled */
@@ -1744,12 +1753,7 @@ void disable_IO_APIC(void)
1744 /* 1753 /*
1745 * Add it to the IO-APIC irq-routing table: 1754 * Add it to the IO-APIC irq-routing table:
1746 */ 1755 */
1747 spin_lock_irqsave(&ioapic_lock, flags); 1756 ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
1748 io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
1749 *(((int *)&entry)+1));
1750 io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
1751 *(((int *)&entry)+0));
1752 spin_unlock_irqrestore(&ioapic_lock, flags);
1753 } 1757 }
1754 disconnect_bsp_APIC(ioapic_i8259.pin != -1); 1758 disconnect_bsp_APIC(ioapic_i8259.pin != -1);
1755} 1759}
@@ -2214,17 +2218,13 @@ static inline void unlock_ExtINT_logic(void)
2214 int apic, pin, i; 2218 int apic, pin, i;
2215 struct IO_APIC_route_entry entry0, entry1; 2219 struct IO_APIC_route_entry entry0, entry1;
2216 unsigned char save_control, save_freq_select; 2220 unsigned char save_control, save_freq_select;
2217 unsigned long flags;
2218 2221
2219 pin = find_isa_irq_pin(8, mp_INT); 2222 pin = find_isa_irq_pin(8, mp_INT);
2220 apic = find_isa_irq_apic(8, mp_INT); 2223 apic = find_isa_irq_apic(8, mp_INT);
2221 if (pin == -1) 2224 if (pin == -1)
2222 return; 2225 return;
2223 2226
2224 spin_lock_irqsave(&ioapic_lock, flags); 2227 entry0 = ioapic_read_entry(apic, pin);
2225 *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
2226 *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
2227 spin_unlock_irqrestore(&ioapic_lock, flags);
2228 clear_IO_APIC_pin(apic, pin); 2228 clear_IO_APIC_pin(apic, pin);
2229 2229
2230 memset(&entry1, 0, sizeof(entry1)); 2230 memset(&entry1, 0, sizeof(entry1));
@@ -2237,10 +2237,7 @@ static inline void unlock_ExtINT_logic(void)
2237 entry1.trigger = 0; 2237 entry1.trigger = 0;
2238 entry1.vector = 0; 2238 entry1.vector = 0;
2239 2239
2240 spin_lock_irqsave(&ioapic_lock, flags); 2240 ioapic_write_entry(apic, pin, entry1);
2241 io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
2242 io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
2243 spin_unlock_irqrestore(&ioapic_lock, flags);
2244 2241
2245 save_control = CMOS_READ(RTC_CONTROL); 2242 save_control = CMOS_READ(RTC_CONTROL);
2246 save_freq_select = CMOS_READ(RTC_FREQ_SELECT); 2243 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
@@ -2259,10 +2256,7 @@ static inline void unlock_ExtINT_logic(void)
2259 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 2256 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
2260 clear_IO_APIC_pin(apic, pin); 2257 clear_IO_APIC_pin(apic, pin);
2261 2258
2262 spin_lock_irqsave(&ioapic_lock, flags); 2259 ioapic_write_entry(apic, pin, entry0);
2263 io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
2264 io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
2265 spin_unlock_irqrestore(&ioapic_lock, flags);
2266} 2260}
2267 2261
2268int timer_uses_ioapic_pin_0; 2262int timer_uses_ioapic_pin_0;
@@ -2462,17 +2456,12 @@ static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
2462{ 2456{
2463 struct IO_APIC_route_entry *entry; 2457 struct IO_APIC_route_entry *entry;
2464 struct sysfs_ioapic_data *data; 2458 struct sysfs_ioapic_data *data;
2465 unsigned long flags;
2466 int i; 2459 int i;
2467 2460
2468 data = container_of(dev, struct sysfs_ioapic_data, dev); 2461 data = container_of(dev, struct sysfs_ioapic_data, dev);
2469 entry = data->entry; 2462 entry = data->entry;
2470 spin_lock_irqsave(&ioapic_lock, flags); 2463 for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
2471 for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) { 2464 entry[i] = ioapic_read_entry(dev->id, i);
2472 *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
2473 *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
2474 }
2475 spin_unlock_irqrestore(&ioapic_lock, flags);
2476 2465
2477 return 0; 2466 return 0;
2478} 2467}
@@ -2494,11 +2483,9 @@ static int ioapic_resume(struct sys_device *dev)
2494 reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid; 2483 reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
2495 io_apic_write(dev->id, 0, reg_00.raw); 2484 io_apic_write(dev->id, 0, reg_00.raw);
2496 } 2485 }
2497 for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
2498 io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
2499 io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
2500 }
2501 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]);
2502 2489
2503 return 0; 2490 return 0;
2504} 2491}
@@ -2695,9 +2682,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
2695 if (!ioapic && (irq < 16)) 2682 if (!ioapic && (irq < 16))
2696 disable_8259A_irq(irq); 2683 disable_8259A_irq(irq);
2697 2684
2685 ioapic_write_entry(ioapic, pin, entry);
2698 spin_lock_irqsave(&ioapic_lock, flags); 2686 spin_lock_irqsave(&ioapic_lock, flags);
2699 io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
2700 io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
2701 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);
2702 spin_unlock_irqrestore(&ioapic_lock, flags); 2688 spin_unlock_irqrestore(&ioapic_lock, flags);
2703 2689