diff options
Diffstat (limited to 'arch/powerpc/mm/numa.c')
| -rw-r--r-- | arch/powerpc/mm/numa.c | 78 | 
1 files changed, 57 insertions, 21 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index eaa7633515b7..80d110635d24 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -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)  |