aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/io_apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/io_apic.c')
-rw-r--r--arch/x86_64/kernel/io_apic.c102
1 files changed, 64 insertions, 38 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index d206d7e49cf5..76bcc4e6979d 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -78,6 +78,54 @@ int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
78#define vector_to_irq(vector) (vector) 78#define vector_to_irq(vector) (vector)
79#endif 79#endif
80 80
81#define __DO_ACTION(R, ACTION, FINAL) \
82 \
83{ \
84 int pin; \
85 struct irq_pin_list *entry = irq_2_pin + irq; \
86 \
87 for (;;) { \
88 unsigned int reg; \
89 pin = entry->pin; \
90 if (pin == -1) \
91 break; \
92 reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \
93 reg ACTION; \
94 io_apic_modify(entry->apic, reg); \
95 if (!entry->next) \
96 break; \
97 entry = irq_2_pin + entry->next; \
98 } \
99 FINAL; \
100}
101
102#ifdef CONFIG_SMP
103static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
104{
105 unsigned long flags;
106 unsigned int dest;
107 cpumask_t tmp;
108
109 cpus_and(tmp, mask, cpu_online_map);
110 if (cpus_empty(tmp))
111 tmp = TARGET_CPUS;
112
113 cpus_and(mask, tmp, CPU_MASK_ALL);
114
115 dest = cpu_mask_to_apicid(mask);
116
117 /*
118 * Only the high 8 bits are valid.
119 */
120 dest = SET_APIC_LOGICAL_ID(dest);
121
122 spin_lock_irqsave(&ioapic_lock, flags);
123 __DO_ACTION(1, = dest, )
124 set_irq_info(irq, mask);
125 spin_unlock_irqrestore(&ioapic_lock, flags);
126}
127#endif
128
81/* 129/*
82 * The common case is 1:1 IRQ<->pin mappings. Sometimes there are 130 * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
83 * shared ISA-space IRQs, so we have to support them. We are super 131 * shared ISA-space IRQs, so we have to support them. We are super
@@ -101,26 +149,6 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
101 entry->pin = pin; 149 entry->pin = pin;
102} 150}
103 151
104#define __DO_ACTION(R, ACTION, FINAL) \
105 \
106{ \
107 int pin; \
108 struct irq_pin_list *entry = irq_2_pin + irq; \
109 \
110 for (;;) { \
111 unsigned int reg; \
112 pin = entry->pin; \
113 if (pin == -1) \
114 break; \
115 reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \
116 reg ACTION; \
117 io_apic_modify(entry->apic, reg); \
118 if (!entry->next) \
119 break; \
120 entry = irq_2_pin + entry->next; \
121 } \
122 FINAL; \
123}
124 152
125#define DO_ACTION(name,R,ACTION, FINAL) \ 153#define DO_ACTION(name,R,ACTION, FINAL) \
126 \ 154 \
@@ -767,6 +795,7 @@ static void __init setup_IO_APIC_irqs(void)
767 spin_lock_irqsave(&ioapic_lock, flags); 795 spin_lock_irqsave(&ioapic_lock, flags);
768 io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); 796 io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
769 io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); 797 io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
798 set_native_irq_info(irq, TARGET_CPUS);
770 spin_unlock_irqrestore(&ioapic_lock, flags); 799 spin_unlock_irqrestore(&ioapic_lock, flags);
771 } 800 }
772 } 801 }
@@ -1314,6 +1343,7 @@ static unsigned int startup_edge_ioapic_irq(unsigned int irq)
1314 */ 1343 */
1315static void ack_edge_ioapic_irq(unsigned int irq) 1344static void ack_edge_ioapic_irq(unsigned int irq)
1316{ 1345{
1346 move_irq(irq);
1317 if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED)) 1347 if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
1318 == (IRQ_PENDING | IRQ_DISABLED)) 1348 == (IRQ_PENDING | IRQ_DISABLED))
1319 mask_IO_APIC_irq(irq); 1349 mask_IO_APIC_irq(irq);
@@ -1343,26 +1373,10 @@ static unsigned int startup_level_ioapic_irq (unsigned int irq)
1343 1373
1344static void end_level_ioapic_irq (unsigned int irq) 1374static void end_level_ioapic_irq (unsigned int irq)
1345{ 1375{
1376 move_irq(irq);
1346 ack_APIC_irq(); 1377 ack_APIC_irq();
1347} 1378}
1348 1379
1349static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
1350{
1351 unsigned long flags;
1352 unsigned int dest;
1353
1354 dest = cpu_mask_to_apicid(mask);
1355
1356 /*
1357 * Only the high 8 bits are valid.
1358 */
1359 dest = SET_APIC_LOGICAL_ID(dest);
1360
1361 spin_lock_irqsave(&ioapic_lock, flags);
1362 __DO_ACTION(1, = dest, )
1363 spin_unlock_irqrestore(&ioapic_lock, flags);
1364}
1365
1366#ifdef CONFIG_PCI_MSI 1380#ifdef CONFIG_PCI_MSI
1367static unsigned int startup_edge_ioapic_vector(unsigned int vector) 1381static unsigned int startup_edge_ioapic_vector(unsigned int vector)
1368{ 1382{
@@ -1375,6 +1389,7 @@ static void ack_edge_ioapic_vector(unsigned int vector)
1375{ 1389{
1376 int irq = vector_to_irq(vector); 1390 int irq = vector_to_irq(vector);
1377 1391
1392 move_native_irq(vector);
1378 ack_edge_ioapic_irq(irq); 1393 ack_edge_ioapic_irq(irq);
1379} 1394}
1380 1395
@@ -1389,6 +1404,7 @@ static void end_level_ioapic_vector (unsigned int vector)
1389{ 1404{
1390 int irq = vector_to_irq(vector); 1405 int irq = vector_to_irq(vector);
1391 1406
1407 move_native_irq(vector);
1392 end_level_ioapic_irq(irq); 1408 end_level_ioapic_irq(irq);
1393} 1409}
1394 1410
@@ -1406,14 +1422,17 @@ static void unmask_IO_APIC_vector (unsigned int vector)
1406 unmask_IO_APIC_irq(irq); 1422 unmask_IO_APIC_irq(irq);
1407} 1423}
1408 1424
1425#ifdef CONFIG_SMP
1409static void set_ioapic_affinity_vector (unsigned int vector, 1426static void set_ioapic_affinity_vector (unsigned int vector,
1410 cpumask_t cpu_mask) 1427 cpumask_t cpu_mask)
1411{ 1428{
1412 int irq = vector_to_irq(vector); 1429 int irq = vector_to_irq(vector);
1413 1430
1431 set_native_irq_info(vector, cpu_mask);
1414 set_ioapic_affinity_irq(irq, cpu_mask); 1432 set_ioapic_affinity_irq(irq, cpu_mask);
1415} 1433}
1416#endif 1434#endif // CONFIG_SMP
1435#endif // CONFIG_PCI_MSI
1417 1436
1418/* 1437/*
1419 * Level and edge triggered IO-APIC interrupts need different handling, 1438 * Level and edge triggered IO-APIC interrupts need different handling,
@@ -1432,7 +1451,9 @@ static struct hw_interrupt_type ioapic_edge_type = {
1432 .disable = disable_edge_ioapic, 1451 .disable = disable_edge_ioapic,
1433 .ack = ack_edge_ioapic, 1452 .ack = ack_edge_ioapic,
1434 .end = end_edge_ioapic, 1453 .end = end_edge_ioapic,
1454#ifdef CONFIG_SMP
1435 .set_affinity = set_ioapic_affinity, 1455 .set_affinity = set_ioapic_affinity,
1456#endif
1436}; 1457};
1437 1458
1438static struct hw_interrupt_type ioapic_level_type = { 1459static struct hw_interrupt_type ioapic_level_type = {
@@ -1443,7 +1464,9 @@ static struct hw_interrupt_type ioapic_level_type = {
1443 .disable = disable_level_ioapic, 1464 .disable = disable_level_ioapic,
1444 .ack = mask_and_ack_level_ioapic, 1465 .ack = mask_and_ack_level_ioapic,
1445 .end = end_level_ioapic, 1466 .end = end_level_ioapic,
1467#ifdef CONFIG_SMP
1446 .set_affinity = set_ioapic_affinity, 1468 .set_affinity = set_ioapic_affinity,
1469#endif
1447}; 1470};
1448 1471
1449static inline void init_IO_APIC_traps(void) 1472static inline void init_IO_APIC_traps(void)
@@ -1918,6 +1941,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
1918 spin_lock_irqsave(&ioapic_lock, flags); 1941 spin_lock_irqsave(&ioapic_lock, flags);
1919 io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); 1942 io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
1920 io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); 1943 io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
1944 set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
1921 spin_unlock_irqrestore(&ioapic_lock, flags); 1945 spin_unlock_irqrestore(&ioapic_lock, flags);
1922 1946
1923 return 0; 1947 return 0;
@@ -1931,6 +1955,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
1931 * we need to reprogram the ioredtbls to cater for the cpus which have come online 1955 * we need to reprogram the ioredtbls to cater for the cpus which have come online
1932 * so mask in all cases should simply be TARGET_CPUS 1956 * so mask in all cases should simply be TARGET_CPUS
1933 */ 1957 */
1958#ifdef CONFIG_SMP
1934void __init setup_ioapic_dest(void) 1959void __init setup_ioapic_dest(void)
1935{ 1960{
1936 int pin, ioapic, irq, irq_entry; 1961 int pin, ioapic, irq, irq_entry;
@@ -1949,3 +1974,4 @@ void __init setup_ioapic_dest(void)
1949 1974
1950 } 1975 }
1951} 1976}
1977#endif