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.c69
1 files changed, 36 insertions, 33 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 6578f40bd501..889eda2d7b17 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -33,6 +33,7 @@
33#include <linux/acpi.h> 33#include <linux/acpi.h>
34#include <linux/module.h> 34#include <linux/module.h>
35#include <linux/sysdev.h> 35#include <linux/sysdev.h>
36
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/smp.h> 38#include <asm/smp.h>
38#include <asm/desc.h> 39#include <asm/desc.h>
@@ -77,7 +78,7 @@ static struct irq_pin_list {
77 int apic, pin, next; 78 int apic, pin, next;
78} irq_2_pin[PIN_MAP_SIZE]; 79} irq_2_pin[PIN_MAP_SIZE];
79 80
80int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; 81int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
81#ifdef CONFIG_PCI_MSI 82#ifdef CONFIG_PCI_MSI
82#define vector_to_irq(vector) \ 83#define vector_to_irq(vector) \
83 (platform_legacy_irq(vector) ? vector : vector_irq[vector]) 84 (platform_legacy_irq(vector) ? vector : vector_irq[vector])
@@ -222,13 +223,21 @@ static void clear_IO_APIC (void)
222 clear_IO_APIC_pin(apic, pin); 223 clear_IO_APIC_pin(apic, pin);
223} 224}
224 225
226#ifdef CONFIG_SMP
225static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask) 227static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
226{ 228{
227 unsigned long flags; 229 unsigned long flags;
228 int pin; 230 int pin;
229 struct irq_pin_list *entry = irq_2_pin + irq; 231 struct irq_pin_list *entry = irq_2_pin + irq;
230 unsigned int apicid_value; 232 unsigned int apicid_value;
233 cpumask_t tmp;
231 234
235 cpus_and(tmp, cpumask, cpu_online_map);
236 if (cpus_empty(tmp))
237 tmp = TARGET_CPUS;
238
239 cpus_and(cpumask, tmp, CPU_MASK_ALL);
240
232 apicid_value = cpu_mask_to_apicid(cpumask); 241 apicid_value = cpu_mask_to_apicid(cpumask);
233 /* Prepare to do the io_apic_write */ 242 /* Prepare to do the io_apic_write */
234 apicid_value = apicid_value << 24; 243 apicid_value = apicid_value << 24;
@@ -242,6 +251,7 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
242 break; 251 break;
243 entry = irq_2_pin + entry->next; 252 entry = irq_2_pin + entry->next;
244 } 253 }
254 set_irq_info(irq, cpumask);
245 spin_unlock_irqrestore(&ioapic_lock, flags); 255 spin_unlock_irqrestore(&ioapic_lock, flags);
246} 256}
247 257
@@ -259,7 +269,6 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
259# define Dprintk(x...) 269# define Dprintk(x...)
260# endif 270# endif
261 271
262cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];
263 272
264#define IRQBALANCE_CHECK_ARCH -999 273#define IRQBALANCE_CHECK_ARCH -999
265static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH; 274static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
@@ -328,12 +337,7 @@ static inline void balance_irq(int cpu, int irq)
328 cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]); 337 cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]);
329 new_cpu = move(cpu, allowed_mask, now, 1); 338 new_cpu = move(cpu, allowed_mask, now, 1);
330 if (cpu != new_cpu) { 339 if (cpu != new_cpu) {
331 irq_desc_t *desc = irq_desc + irq; 340 set_pending_irq(irq, cpumask_of_cpu(new_cpu));
332 unsigned long flags;
333
334 spin_lock_irqsave(&desc->lock, flags);
335 pending_irq_balance_cpumask[irq] = cpumask_of_cpu(new_cpu);
336 spin_unlock_irqrestore(&desc->lock, flags);
337 } 341 }
338} 342}
339 343
@@ -528,16 +532,12 @@ tryanotherirq:
528 cpus_and(tmp, target_cpu_mask, allowed_mask); 532 cpus_and(tmp, target_cpu_mask, allowed_mask);
529 533
530 if (!cpus_empty(tmp)) { 534 if (!cpus_empty(tmp)) {
531 irq_desc_t *desc = irq_desc + selected_irq;
532 unsigned long flags;
533 535
534 Dprintk("irq = %d moved to cpu = %d\n", 536 Dprintk("irq = %d moved to cpu = %d\n",
535 selected_irq, min_loaded); 537 selected_irq, min_loaded);
536 /* mark for change destination */ 538 /* mark for change destination */
537 spin_lock_irqsave(&desc->lock, flags); 539 set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded));
538 pending_irq_balance_cpumask[selected_irq] = 540
539 cpumask_of_cpu(min_loaded);
540 spin_unlock_irqrestore(&desc->lock, flags);
541 /* Since we made a change, come back sooner to 541 /* Since we made a change, come back sooner to
542 * check for more variation. 542 * check for more variation.
543 */ 543 */
@@ -568,7 +568,8 @@ static int balanced_irq(void *unused)
568 568
569 /* push everything to CPU 0 to give us a starting point. */ 569 /* push everything to CPU 0 to give us a starting point. */
570 for (i = 0 ; i < NR_IRQS ; i++) { 570 for (i = 0 ; i < NR_IRQS ; i++) {
571 pending_irq_balance_cpumask[i] = cpumask_of_cpu(0); 571 pending_irq_cpumask[i] = cpumask_of_cpu(0);
572 set_pending_irq(i, cpumask_of_cpu(0));
572 } 573 }
573 574
574 for ( ; ; ) { 575 for ( ; ; ) {
@@ -647,20 +648,9 @@ int __init irqbalance_disable(char *str)
647 648
648__setup("noirqbalance", irqbalance_disable); 649__setup("noirqbalance", irqbalance_disable);
649 650
650static inline void move_irq(int irq)
651{
652 /* note - we hold the desc->lock */
653 if (unlikely(!cpus_empty(pending_irq_balance_cpumask[irq]))) {
654 set_ioapic_affinity_irq(irq, pending_irq_balance_cpumask[irq]);
655 cpus_clear(pending_irq_balance_cpumask[irq]);
656 }
657}
658
659late_initcall(balanced_irq_init); 651late_initcall(balanced_irq_init);
660
661#else /* !CONFIG_IRQBALANCE */
662static inline void move_irq(int irq) { }
663#endif /* CONFIG_IRQBALANCE */ 652#endif /* CONFIG_IRQBALANCE */
653#endif /* CONFIG_SMP */
664 654
665#ifndef CONFIG_SMP 655#ifndef CONFIG_SMP
666void fastcall send_IPI_self(int vector) 656void fastcall send_IPI_self(int vector)
@@ -820,6 +810,7 @@ EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
820 * we need to reprogram the ioredtbls to cater for the cpus which have come online 810 * we need to reprogram the ioredtbls to cater for the cpus which have come online
821 * so mask in all cases should simply be TARGET_CPUS 811 * so mask in all cases should simply be TARGET_CPUS
822 */ 812 */
813#ifdef CONFIG_SMP
823void __init setup_ioapic_dest(void) 814void __init setup_ioapic_dest(void)
824{ 815{
825 int pin, ioapic, irq, irq_entry; 816 int pin, ioapic, irq, irq_entry;
@@ -838,6 +829,7 @@ void __init setup_ioapic_dest(void)
838 829
839 } 830 }
840} 831}
832#endif
841 833
842/* 834/*
843 * EISA Edge/Level control register, ELCR 835 * EISA Edge/Level control register, ELCR
@@ -1127,7 +1119,7 @@ static inline int IO_APIC_irq_trigger(int irq)
1127} 1119}
1128 1120
1129/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ 1121/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
1130u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; 1122u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
1131 1123
1132int assign_irq_vector(int irq) 1124int assign_irq_vector(int irq)
1133{ 1125{
@@ -1249,6 +1241,7 @@ static void __init setup_IO_APIC_irqs(void)
1249 spin_lock_irqsave(&ioapic_lock, flags); 1241 spin_lock_irqsave(&ioapic_lock, flags);
1250 io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); 1242 io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
1251 io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); 1243 io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
1244 set_native_irq_info(irq, TARGET_CPUS);
1252 spin_unlock_irqrestore(&ioapic_lock, flags); 1245 spin_unlock_irqrestore(&ioapic_lock, flags);
1253 } 1246 }
1254 } 1247 }
@@ -1944,6 +1937,7 @@ static void ack_edge_ioapic_vector(unsigned int vector)
1944{ 1937{
1945 int irq = vector_to_irq(vector); 1938 int irq = vector_to_irq(vector);
1946 1939
1940 move_irq(vector);
1947 ack_edge_ioapic_irq(irq); 1941 ack_edge_ioapic_irq(irq);
1948} 1942}
1949 1943
@@ -1958,6 +1952,7 @@ static void end_level_ioapic_vector (unsigned int vector)
1958{ 1952{
1959 int irq = vector_to_irq(vector); 1953 int irq = vector_to_irq(vector);
1960 1954
1955 move_irq(vector);
1961 end_level_ioapic_irq(irq); 1956 end_level_ioapic_irq(irq);
1962} 1957}
1963 1958
@@ -1975,14 +1970,17 @@ static void unmask_IO_APIC_vector (unsigned int vector)
1975 unmask_IO_APIC_irq(irq); 1970 unmask_IO_APIC_irq(irq);
1976} 1971}
1977 1972
1973#ifdef CONFIG_SMP
1978static void set_ioapic_affinity_vector (unsigned int vector, 1974static void set_ioapic_affinity_vector (unsigned int vector,
1979 cpumask_t cpu_mask) 1975 cpumask_t cpu_mask)
1980{ 1976{
1981 int irq = vector_to_irq(vector); 1977 int irq = vector_to_irq(vector);
1982 1978
1979 set_native_irq_info(vector, cpu_mask);
1983 set_ioapic_affinity_irq(irq, cpu_mask); 1980 set_ioapic_affinity_irq(irq, cpu_mask);
1984} 1981}
1985#endif 1982#endif
1983#endif
1986 1984
1987/* 1985/*
1988 * Level and edge triggered IO-APIC interrupts need different handling, 1986 * Level and edge triggered IO-APIC interrupts need different handling,
@@ -1992,7 +1990,7 @@ static void set_ioapic_affinity_vector (unsigned int vector,
1992 * edge-triggered handler, without risking IRQ storms and other ugly 1990 * edge-triggered handler, without risking IRQ storms and other ugly
1993 * races. 1991 * races.
1994 */ 1992 */
1995static struct hw_interrupt_type ioapic_edge_type = { 1993static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
1996 .typename = "IO-APIC-edge", 1994 .typename = "IO-APIC-edge",
1997 .startup = startup_edge_ioapic, 1995 .startup = startup_edge_ioapic,
1998 .shutdown = shutdown_edge_ioapic, 1996 .shutdown = shutdown_edge_ioapic,
@@ -2000,10 +1998,12 @@ static struct hw_interrupt_type ioapic_edge_type = {
2000 .disable = disable_edge_ioapic, 1998 .disable = disable_edge_ioapic,
2001 .ack = ack_edge_ioapic, 1999 .ack = ack_edge_ioapic,
2002 .end = end_edge_ioapic, 2000 .end = end_edge_ioapic,
2001#ifdef CONFIG_SMP
2003 .set_affinity = set_ioapic_affinity, 2002 .set_affinity = set_ioapic_affinity,
2003#endif
2004}; 2004};
2005 2005
2006static struct hw_interrupt_type ioapic_level_type = { 2006static struct hw_interrupt_type ioapic_level_type __read_mostly = {
2007 .typename = "IO-APIC-level", 2007 .typename = "IO-APIC-level",
2008 .startup = startup_level_ioapic, 2008 .startup = startup_level_ioapic,
2009 .shutdown = shutdown_level_ioapic, 2009 .shutdown = shutdown_level_ioapic,
@@ -2011,7 +2011,9 @@ static struct hw_interrupt_type ioapic_level_type = {
2011 .disable = disable_level_ioapic, 2011 .disable = disable_level_ioapic,
2012 .ack = mask_and_ack_level_ioapic, 2012 .ack = mask_and_ack_level_ioapic,
2013 .end = end_level_ioapic, 2013 .end = end_level_ioapic,
2014#ifdef CONFIG_SMP
2014 .set_affinity = set_ioapic_affinity, 2015 .set_affinity = set_ioapic_affinity,
2016#endif
2015}; 2017};
2016 2018
2017static inline void init_IO_APIC_traps(void) 2019static inline void init_IO_APIC_traps(void)
@@ -2074,7 +2076,7 @@ static void ack_lapic_irq (unsigned int irq)
2074 2076
2075static void end_lapic_irq (unsigned int i) { /* nothing */ } 2077static void end_lapic_irq (unsigned int i) { /* nothing */ }
2076 2078
2077static struct hw_interrupt_type lapic_irq_type = { 2079static struct hw_interrupt_type lapic_irq_type __read_mostly = {
2078 .typename = "local-APIC-edge", 2080 .typename = "local-APIC-edge",
2079 .startup = NULL, /* startup_irq() not used for IRQ0 */ 2081 .startup = NULL, /* startup_irq() not used for IRQ0 */
2080 .shutdown = NULL, /* shutdown_irq() not used for IRQ0 */ 2082 .shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
@@ -2421,7 +2423,7 @@ device_initcall(ioapic_init_sysfs);
2421 ACPI-based IOAPIC Configuration 2423 ACPI-based IOAPIC Configuration
2422 -------------------------------------------------------------------------- */ 2424 -------------------------------------------------------------------------- */
2423 2425
2424#ifdef CONFIG_ACPI_BOOT 2426#ifdef CONFIG_ACPI
2425 2427
2426int __init io_apic_get_unique_id (int ioapic, int apic_id) 2428int __init io_apic_get_unique_id (int ioapic, int apic_id)
2427{ 2429{
@@ -2569,9 +2571,10 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
2569 spin_lock_irqsave(&ioapic_lock, flags); 2571 spin_lock_irqsave(&ioapic_lock, flags);
2570 io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); 2572 io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
2571 io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); 2573 io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
2574 set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
2572 spin_unlock_irqrestore(&ioapic_lock, flags); 2575 spin_unlock_irqrestore(&ioapic_lock, flags);
2573 2576
2574 return 0; 2577 return 0;
2575} 2578}
2576 2579
2577#endif /*CONFIG_ACPI_BOOT*/ 2580#endif /* CONFIG_ACPI */