X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fia64%2Fkernel%2Fiosapic.c;h=51548a8c57e0404d2b507a3b231bcd1585199660;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=f032ea1b35eee0ab012cc81d07bfc2ba823eb25a;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index f032ea1b3..51548a8c5 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -104,7 +104,7 @@ static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */ static struct iosapic_intr_info { - char *addr; /* base address of IOSAPIC */ + char __iomem *addr; /* base address of IOSAPIC */ u32 low32; /* current value of low word of Redirection table entry */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */ @@ -114,9 +114,12 @@ static struct iosapic_intr_info { } iosapic_intr_info[IA64_NUM_VECTORS]; static struct iosapic { - char *addr; /* base address of IOSAPIC */ + char __iomem *addr; /* base address of IOSAPIC */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ unsigned short num_rte; /* number of RTE in this IOSAPIC */ +#ifdef CONFIG_NUMA + unsigned short node; /* numa node association via pxm */ +#endif } iosapic_lists[NR_IOSAPICS]; static int num_iosapic; @@ -176,7 +179,7 @@ set_rte (unsigned int vector, unsigned int dest, int mask) { unsigned long pol, trigger, dmode, flags; u32 low32, high32; - char *addr; + char __iomem *addr; int rte_index; char redir; @@ -234,7 +237,7 @@ static void mask_irq (unsigned int irq) { unsigned long flags; - char *addr; + char __iomem *addr; u32 low32; int rte_index; ia64_vector vec = irq_to_vector(irq); @@ -258,7 +261,7 @@ static void unmask_irq (unsigned int irq) { unsigned long flags; - char *addr; + char __iomem *addr; u32 low32; int rte_index; ia64_vector vec = irq_to_vector(irq); @@ -284,7 +287,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) unsigned long flags; u32 high32, low32; int dest, rte_index; - char *addr; + char __iomem *addr; int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; ia64_vector vec; @@ -409,7 +412,7 @@ struct hw_interrupt_type irq_type_iosapic_edge = { }; unsigned int -iosapic_version (char *addr) +iosapic_version (char __iomem *addr) { /* * IOSAPIC Version Register return 32 bit structure like: @@ -454,7 +457,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, int rte_index; int index; unsigned long gsi_base; - char *iosapic_address; + void __iomem *iosapic_address; index = find_iosapic(gsi); if (index < 0) { @@ -488,7 +491,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, } static unsigned int -get_target_cpu (void) +get_target_cpu (unsigned int gsi, int vector) { #ifdef CONFIG_SMP static int cpu = -1; @@ -507,6 +510,34 @@ get_target_cpu (void) if (!cpu_online(smp_processor_id())) return hard_smp_processor_id(); +#ifdef CONFIG_NUMA + { + int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0; + cpumask_t cpu_mask; + + iosapic_index = find_iosapic(gsi); + if (iosapic_index < 0 || + iosapic_lists[iosapic_index].node == MAX_NUMNODES) + goto skip_numa_setup; + + cpu_mask = node_to_cpumask(iosapic_lists[iosapic_index].node); + + num_cpus = cpus_weight(cpu_mask); + + if (!num_cpus) + goto skip_numa_setup; + + /* Use vector assigment to distribute across cpus in node */ + cpu_index = vector % num_cpus; + + for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) + numa_cpu = next_cpu(numa_cpu, cpu_mask); + + if (numa_cpu != NR_CPUS) + return cpu_physical_id(numa_cpu); + } +skip_numa_setup: +#endif /* * Otherwise, round-robin interrupt vectors across all the * processors. (It'd be nice if we could be smarter in the @@ -550,7 +581,7 @@ iosapic_register_intr (unsigned int gsi, } vector = assign_irq_vector(AUTO_ASSIGN); - dest = get_target_cpu(); + dest = get_target_cpu(gsi, vector); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); } @@ -665,7 +696,7 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) { int num_rte; unsigned int isa_irq, ver; - char *addr; + char __iomem *addr; addr = ioremap(phys_addr, 0); ver = iosapic_version(addr); @@ -680,6 +711,9 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) iosapic_lists[num_iosapic].addr = addr; iosapic_lists[num_iosapic].gsi_base = gsi_base; iosapic_lists[num_iosapic].num_rte = num_rte; +#ifdef CONFIG_NUMA + iosapic_lists[num_iosapic].node = MAX_NUMNODES; +#endif num_iosapic++; if ((gsi_base == 0) && pcat_compat) { @@ -692,3 +726,20 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); } } + +#ifdef CONFIG_NUMA +void __init +map_iosapic_to_node(unsigned int gsi_base, int node) +{ + int index; + + index = find_iosapic(gsi_base); + if (index < 0) { + printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", + __FUNCTION__, gsi_base); + return; + } + iosapic_lists[index].node = node; + return; +} +#endif