x86/x2apic/cluster: Use all the members of one cluster specified in the smp_affinity...
[linux-2.6-block.git] / arch / x86 / kernel / apic / x2apic_cluster.c
index ff35cff0e1a7e6f4f16b628504c821c5e544bacf..90d999c7f2eac0640043bdf7a082eee3fbdb3fb1 100644 (file)
@@ -98,34 +98,47 @@ static void x2apic_send_IPI_all(int vector)
 
 static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask)
 {
-       /*
-        * We're using fixed IRQ delivery, can only return one logical APIC ID.
-        * May as well be the first.
-        */
        int cpu = cpumask_first(cpumask);
+       u32 dest = 0;
+       int i;
 
-       if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_logical_apicid, cpu);
-       else
+       if (cpu > nr_cpu_ids)
                return BAD_APICID;
+
+       for_each_cpu_and(i, cpumask, per_cpu(cpus_in_cluster, cpu))
+               dest |= per_cpu(x86_cpu_to_logical_apicid, i);
+
+       return dest;
 }
 
 static unsigned int
 x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
                              const struct cpumask *andmask)
 {
-       int cpu;
+       u32 dest = 0;
+       u16 cluster;
+       int i;
 
-       /*
-        * We're using fixed IRQ delivery, can only return one logical APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       break;
+       for_each_cpu_and(i, cpumask, andmask) {
+               if (!cpumask_test_cpu(i, cpu_online_mask))
+                       continue;
+               dest = per_cpu(x86_cpu_to_logical_apicid, i);
+               cluster = x2apic_cluster(i);
+               break;
        }
 
-       return per_cpu(x86_cpu_to_logical_apicid, cpu);
+       if (!dest)
+               return BAD_APICID;
+
+       for_each_cpu_and(i, cpumask, andmask) {
+               if (!cpumask_test_cpu(i, cpu_online_mask))
+                       continue;
+               if (cluster != x2apic_cluster(i))
+                       continue;
+               dest |= per_cpu(x86_cpu_to_logical_apicid, i);
+       }
+
+       return dest;
 }
 
 static void init_x2apic_ldr(void)
@@ -208,6 +221,15 @@ static int x2apic_cluster_probe(void)
                return 0;
 }
 
+/*
+ * Each x2apic cluster is an allocation domain.
+ */
+static void cluster_vector_allocation_domain(int cpu, struct cpumask *retmask)
+{
+       cpumask_clear(retmask);
+       cpumask_copy(retmask, per_cpu(cpus_in_cluster, cpu));
+}
+
 static struct apic apic_x2apic_cluster = {
 
        .name                           = "cluster x2apic",
@@ -225,7 +247,7 @@ static struct apic apic_x2apic_cluster = {
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = x2apic_vector_allocation_domain,
+       .vector_allocation_domain       = cluster_vector_allocation_domain,
        .init_apic_ldr                  = init_x2apic_ldr,
 
        .ioapic_phys_id_map             = NULL,