aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/numa.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-01-09 13:03:44 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-09 13:03:44 -0500
commit6150c32589d1976ca8a5c987df951088c05a7542 (patch)
tree94073696576323ff966e365d8c47b8ecd8372f97 /arch/powerpc/mm/numa.c
parent44637a12f80b80157d9c1bc5b7d6ef09c9e05713 (diff)
parentbe42d5fa3772241b8ecebd443f1fb36247959c54 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
Diffstat (limited to 'arch/powerpc/mm/numa.c')
-rw-r--r--arch/powerpc/mm/numa.c139
1 files changed, 111 insertions, 28 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index ba7a3055a9fc..2863a912bcd0 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -37,6 +37,7 @@ EXPORT_SYMBOL(node_data);
37 37
38static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES]; 38static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
39static int min_common_depth; 39static int min_common_depth;
40static int n_mem_addr_cells, n_mem_size_cells;
40 41
41/* 42/*
42 * We need somewhere to store start/end/node for each region until we have 43 * We need somewhere to store start/end/node for each region until we have
@@ -254,32 +255,20 @@ static int __init find_min_common_depth(void)
254 return depth; 255 return depth;
255} 256}
256 257
257static int __init get_mem_addr_cells(void) 258static void __init get_n_mem_cells(int *n_addr_cells, int *n_size_cells)
258{ 259{
259 struct device_node *memory = NULL; 260 struct device_node *memory = NULL;
260 int rc;
261 261
262 memory = of_find_node_by_type(memory, "memory"); 262 memory = of_find_node_by_type(memory, "memory");
263 if (!memory) 263 if (!memory)
264 return 0; /* it won't matter */ 264 panic("numa.c: No memory nodes found!");
265 265
266 rc = prom_n_addr_cells(memory); 266 *n_addr_cells = prom_n_addr_cells(memory);
267 return rc; 267 *n_size_cells = prom_n_size_cells(memory);
268 of_node_put(memory);
268} 269}
269 270
270static int __init get_mem_size_cells(void) 271static unsigned long __devinit read_n_cells(int n, unsigned int **buf)
271{
272 struct device_node *memory = NULL;
273 int rc;
274
275 memory = of_find_node_by_type(memory, "memory");
276 if (!memory)
277 return 0; /* it won't matter */
278 rc = prom_n_size_cells(memory);
279 return rc;
280}
281
282static unsigned long __init read_n_cells(int n, unsigned int **buf)
283{ 272{
284 unsigned long result = 0; 273 unsigned long result = 0;
285 274
@@ -386,7 +375,6 @@ static int __init parse_numa_properties(void)
386{ 375{
387 struct device_node *cpu = NULL; 376 struct device_node *cpu = NULL;
388 struct device_node *memory = NULL; 377 struct device_node *memory = NULL;
389 int addr_cells, size_cells;
390 int max_domain; 378 int max_domain;
391 unsigned long i; 379 unsigned long i;
392 380
@@ -425,8 +413,7 @@ static int __init parse_numa_properties(void)
425 } 413 }
426 } 414 }
427 415
428 addr_cells = get_mem_addr_cells(); 416 get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
429 size_cells = get_mem_size_cells();
430 memory = NULL; 417 memory = NULL;
431 while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { 418 while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
432 unsigned long start; 419 unsigned long start;
@@ -436,15 +423,21 @@ static int __init parse_numa_properties(void)
436 unsigned int *memcell_buf; 423 unsigned int *memcell_buf;
437 unsigned int len; 424 unsigned int len;
438 425
439 memcell_buf = (unsigned int *)get_property(memory, "reg", &len); 426 memcell_buf = (unsigned int *)get_property(memory,
427 "linux,usable-memory", &len);
428 if (!memcell_buf || len <= 0)
429 memcell_buf =
430 (unsigned int *)get_property(memory, "reg",
431 &len);
440 if (!memcell_buf || len <= 0) 432 if (!memcell_buf || len <= 0)
441 continue; 433 continue;
442 434
443 ranges = memory->n_addrs; 435 /* ranges in cell */
436 ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells);
444new_range: 437new_range:
445 /* these are order-sensitive, and modify the buffer pointer */ 438 /* these are order-sensitive, and modify the buffer pointer */
446 start = read_n_cells(addr_cells, &memcell_buf); 439 start = read_n_cells(n_mem_addr_cells, &memcell_buf);
447 size = read_n_cells(size_cells, &memcell_buf); 440 size = read_n_cells(n_mem_size_cells, &memcell_buf);
448 441
449 numa_domain = of_node_numa_domain(memory); 442 numa_domain = of_node_numa_domain(memory);
450 443
@@ -497,7 +490,41 @@ static void __init setup_nonnuma(void)
497 node_set_online(0); 490 node_set_online(0);
498} 491}
499 492
500static void __init dump_numa_topology(void) 493void __init dump_numa_cpu_topology(void)
494{
495 unsigned int node;
496 unsigned int cpu, count;
497
498 if (min_common_depth == -1 || !numa_enabled)
499 return;
500
501 for_each_online_node(node) {
502 printk(KERN_INFO "Node %d CPUs:", node);
503
504 count = 0;
505 /*
506 * If we used a CPU iterator here we would miss printing
507 * the holes in the cpumap.
508 */
509 for (cpu = 0; cpu < NR_CPUS; cpu++) {
510 if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
511 if (count == 0)
512 printk(" %u", cpu);
513 ++count;
514 } else {
515 if (count > 1)
516 printk("-%u", cpu - 1);
517 count = 0;
518 }
519 }
520
521 if (count > 1)
522 printk("-%u", NR_CPUS - 1);
523 printk("\n");
524 }
525}
526
527static void __init dump_numa_memory_topology(void)
501{ 528{
502 unsigned int node; 529 unsigned int node;
503 unsigned int count; 530 unsigned int count;
@@ -529,7 +556,6 @@ static void __init dump_numa_topology(void)
529 printk("-0x%lx", i); 556 printk("-0x%lx", i);
530 printk("\n"); 557 printk("\n");
531 } 558 }
532 return;
533} 559}
534 560
535/* 561/*
@@ -591,7 +617,7 @@ void __init do_init_bootmem(void)
591 if (parse_numa_properties()) 617 if (parse_numa_properties())
592 setup_nonnuma(); 618 setup_nonnuma();
593 else 619 else
594 dump_numa_topology(); 620 dump_numa_memory_topology();
595 621
596 register_cpu_notifier(&ppc64_numa_nb); 622 register_cpu_notifier(&ppc64_numa_nb);
597 623
@@ -730,3 +756,60 @@ static int __init early_numa(char *p)
730 return 0; 756 return 0;
731} 757}
732early_param("numa", early_numa); 758early_param("numa", early_numa);
759
760#ifdef CONFIG_MEMORY_HOTPLUG
761/*
762 * Find the node associated with a hot added memory section. Section
763 * corresponds to a SPARSEMEM section, not an LMB. It is assumed that
764 * sections are fully contained within a single LMB.
765 */
766int hot_add_scn_to_nid(unsigned long scn_addr)
767{
768 struct device_node *memory = NULL;
769 nodemask_t nodes;
770 int numa_domain = 0;
771
772 if (!numa_enabled || (min_common_depth < 0))
773 return numa_domain;
774
775 while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
776 unsigned long start, size;
777 int ranges;
778 unsigned int *memcell_buf;
779 unsigned int len;
780
781 memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
782 if (!memcell_buf || len <= 0)
783 continue;
784
785 /* ranges in cell */
786 ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells);
787ha_new_range:
788 start = read_n_cells(n_mem_addr_cells, &memcell_buf);
789 size = read_n_cells(n_mem_size_cells, &memcell_buf);
790 numa_domain = of_node_numa_domain(memory);
791
792 /* Domains not present at boot default to 0 */
793 if (!node_online(numa_domain))
794 numa_domain = any_online_node(NODE_MASK_ALL);
795
796 if ((scn_addr >= start) && (scn_addr < (start + size))) {
797 of_node_put(memory);
798 goto got_numa_domain;
799 }
800
801 if (--ranges) /* process all ranges in cell */
802 goto ha_new_range;
803 }
804 BUG(); /* section address should be found above */
805
806 /* Temporary code to ensure that returned node is not empty */
807got_numa_domain:
808 nodes_setall(nodes);
809 while (NODE_DATA(numa_domain)->node_spanned_pages == 0) {
810 node_clear(numa_domain, nodes);
811 numa_domain = any_online_node(nodes);
812 }
813 return numa_domain;
814}
815#endif /* CONFIG_MEMORY_HOTPLUG */