Merge git://git.infradead.org/~dwmw2/mtd-2.6.35
[pandora-kernel.git] / arch / powerpc / mm / numa.c
index eaa7633..80d1106 100644 (file)
@@ -33,16 +33,41 @@ static int numa_debug;
 #define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
 
 int numa_cpu_lookup_table[NR_CPUS];
-cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
+cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
 struct pglist_data *node_data[MAX_NUMNODES];
 
 EXPORT_SYMBOL(numa_cpu_lookup_table);
-EXPORT_SYMBOL(numa_cpumask_lookup_table);
+EXPORT_SYMBOL(node_to_cpumask_map);
 EXPORT_SYMBOL(node_data);
 
 static int min_common_depth;
 static int n_mem_addr_cells, n_mem_size_cells;
 
+/*
+ * Allocate node_to_cpumask_map based on number of available nodes
+ * Requires node_possible_map to be valid.
+ *
+ * Note: node_to_cpumask() is not valid until after this is done.
+ */
+static void __init setup_node_to_cpumask_map(void)
+{
+       unsigned int node, num = 0;
+
+       /* setup nr_node_ids if not done yet */
+       if (nr_node_ids == MAX_NUMNODES) {
+               for_each_node_mask(node, node_possible_map)
+                       num = node;
+               nr_node_ids = num + 1;
+       }
+
+       /* allocate the map */
+       for (node = 0; node < nr_node_ids; node++)
+               alloc_bootmem_cpumask_var(&node_to_cpumask_map[node]);
+
+       /* cpumask_of_node() will now work */
+       dbg("Node to cpumask map for %d nodes\n", nr_node_ids);
+}
+
 static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn,
                                                unsigned int *nid)
 {
@@ -138,8 +163,8 @@ static void __cpuinit map_cpu_to_node(int cpu, int node)
 
        dbg("adding cpu %d to node %d\n", cpu, node);
 
-       if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node])))
-               cpu_set(cpu, numa_cpumask_lookup_table[node]);
+       if (!(cpumask_test_cpu(cpu, node_to_cpumask_map[node])))
+               cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -149,8 +174,8 @@ static void unmap_cpu_from_node(unsigned long cpu)
 
        dbg("removing cpu %lu from node %d\n", cpu, node);
 
-       if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
-               cpu_clear(cpu, numa_cpumask_lookup_table[node]);
+       if (cpumask_test_cpu(cpu, node_to_cpumask_map[node])) {
+               cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
        } else {
                printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n",
                       cpu, node);
@@ -246,7 +271,8 @@ static int __init find_min_common_depth(void)
        const unsigned int *ref_points;
        struct device_node *rtas_root;
        unsigned int len;
-       struct device_node *options;
+       struct device_node *chosen;
+       const char *vec5;
 
        rtas_root = of_find_node_by_path("/rtas");
 
@@ -264,14 +290,17 @@ static int __init find_min_common_depth(void)
                        "ibm,associativity-reference-points", &len);
 
        /*
-        * For type 1 affinity information we want the first field
+        * For form 1 affinity information we want the first field
         */
-       options = of_find_node_by_path("/options");
-       if (options) {
-               const char *str;
-               str = of_get_property(options, "ibm,associativity-form", NULL);
-               if (str && !strcmp(str, "1"))
-                        index = 0;
+#define VEC5_AFFINITY_BYTE     5
+#define VEC5_AFFINITY          0x80
+       chosen = of_find_node_by_path("/chosen");
+       if (chosen) {
+               vec5 = of_get_property(chosen, "ibm,architecture-vec-5", NULL);
+               if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & VEC5_AFFINITY)) {
+                       dbg("Using form 1 affinity\n");
+                       index = 0;
+               }
        }
 
        if ((len >= 2 * sizeof(unsigned int)) && ref_points) {
@@ -750,8 +779,9 @@ void __init dump_numa_cpu_topology(void)
                 * If we used a CPU iterator here we would miss printing
                 * the holes in the cpumap.
                 */
-               for (cpu = 0; cpu < NR_CPUS; cpu++) {
-                       if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
+               for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
+                       if (cpumask_test_cpu(cpu,
+                                       node_to_cpumask_map[node])) {
                                if (count == 0)
                                        printk(" %u", cpu);
                                ++count;
@@ -763,7 +793,7 @@ void __init dump_numa_cpu_topology(void)
                }
 
                if (count > 1)
-                       printk("-%u", NR_CPUS - 1);
+                       printk("-%u", nr_cpu_ids - 1);
                printk("\n");
        }
 }
@@ -939,10 +969,6 @@ void __init do_init_bootmem(void)
        else
                dump_numa_memory_topology();
 
-       register_cpu_notifier(&ppc64_numa_nb);
-       cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE,
-                         (void *)(unsigned long)boot_cpuid);
-
        for_each_online_node(nid) {
                unsigned long start_pfn, end_pfn;
                void *bootmem_vaddr;
@@ -996,6 +1022,16 @@ void __init do_init_bootmem(void)
        }
 
        init_bootmem_done = 1;
+
+       /*
+        * Now bootmem is initialised we can create the node to cpumask
+        * lookup tables and setup the cpu callback to populate them.
+        */
+       setup_node_to_cpumask_map();
+
+       register_cpu_notifier(&ppc64_numa_nb);
+       cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE,
+                         (void *)(unsigned long)boot_cpuid);
 }
 
 void __init paging_init(void)