diff options
Diffstat (limited to 'arch/powerpc/mm')
| -rw-r--r-- | arch/powerpc/mm/numa.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 9da01dc8cfd9..262790910ff2 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
| @@ -295,6 +295,63 @@ static unsigned long __init numa_enforce_memory_limit(unsigned long start, | |||
| 295 | return lmb_end_of_DRAM() - start; | 295 | return lmb_end_of_DRAM() - start; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | /* | ||
| 299 | * Extract NUMA information from the ibm,dynamic-reconfiguration-memory | ||
| 300 | * node. This assumes n_mem_{addr,size}_cells have been set. | ||
| 301 | */ | ||
| 302 | static void __init parse_drconf_memory(struct device_node *memory) | ||
| 303 | { | ||
| 304 | const unsigned int *lm, *dm, *aa; | ||
| 305 | unsigned int ls, ld, la; | ||
| 306 | unsigned int n, aam, aalen; | ||
| 307 | unsigned long lmb_size, size; | ||
| 308 | int nid, default_nid = 0; | ||
| 309 | unsigned int start, ai, flags; | ||
| 310 | |||
| 311 | lm = get_property(memory, "ibm,lmb-size", &ls); | ||
| 312 | dm = get_property(memory, "ibm,dynamic-memory", &ld); | ||
| 313 | aa = get_property(memory, "ibm,associativity-lookup-arrays", &la); | ||
| 314 | if (!lm || !dm || !aa || | ||
| 315 | ls < sizeof(unsigned int) || ld < sizeof(unsigned int) || | ||
| 316 | la < 2 * sizeof(unsigned int)) | ||
| 317 | return; | ||
| 318 | |||
| 319 | lmb_size = read_n_cells(n_mem_size_cells, &lm); | ||
| 320 | n = *dm++; /* number of LMBs */ | ||
| 321 | aam = *aa++; /* number of associativity lists */ | ||
| 322 | aalen = *aa++; /* length of each associativity list */ | ||
| 323 | if (ld < (n * (n_mem_addr_cells + 4) + 1) * sizeof(unsigned int) || | ||
| 324 | la < (aam * aalen + 2) * sizeof(unsigned int)) | ||
| 325 | return; | ||
| 326 | |||
| 327 | for (; n != 0; --n) { | ||
| 328 | start = read_n_cells(n_mem_addr_cells, &dm); | ||
| 329 | ai = dm[2]; | ||
| 330 | flags = dm[3]; | ||
| 331 | dm += 4; | ||
| 332 | /* 0x80 == reserved, 0x8 = assigned to us */ | ||
| 333 | if ((flags & 0x80) || !(flags & 0x8)) | ||
| 334 | continue; | ||
| 335 | nid = default_nid; | ||
| 336 | /* flags & 0x40 means associativity index is invalid */ | ||
| 337 | if (min_common_depth > 0 && min_common_depth <= aalen && | ||
| 338 | (flags & 0x40) == 0 && ai < aam) { | ||
| 339 | /* this is like of_node_to_nid_single */ | ||
| 340 | nid = aa[ai * aalen + min_common_depth - 1]; | ||
| 341 | if (nid == 0xffff || nid >= MAX_NUMNODES) | ||
| 342 | nid = default_nid; | ||
| 343 | } | ||
| 344 | node_set_online(nid); | ||
| 345 | |||
| 346 | size = numa_enforce_memory_limit(start, lmb_size); | ||
| 347 | if (!size) | ||
| 348 | continue; | ||
| 349 | |||
| 350 | add_active_range(nid, start >> PAGE_SHIFT, | ||
| 351 | (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT)); | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 298 | static int __init parse_numa_properties(void) | 355 | static int __init parse_numa_properties(void) |
| 299 | { | 356 | { |
| 300 | struct device_node *cpu = NULL; | 357 | struct device_node *cpu = NULL; |
| @@ -385,6 +442,14 @@ new_range: | |||
| 385 | goto new_range; | 442 | goto new_range; |
| 386 | } | 443 | } |
| 387 | 444 | ||
| 445 | /* | ||
| 446 | * Now do the same thing for each LMB listed in the ibm,dynamic-memory | ||
| 447 | * property in the ibm,dynamic-reconfiguration-memory node. | ||
| 448 | */ | ||
| 449 | memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); | ||
| 450 | if (memory) | ||
| 451 | parse_drconf_memory(memory); | ||
| 452 | |||
| 388 | return 0; | 453 | return 0; |
| 389 | } | 454 | } |
| 390 | 455 | ||
