diff options
author | David S. Miller <davem@davemloft.net> | 2009-05-27 00:46:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-16 07:56:16 -0400 |
commit | 9bab54143ca16592536c9d35f43cfac0a2a28ea8 (patch) | |
tree | 35f1f8a148bb4f9a11036b19ea77e87191773263 | |
parent | 8249778908783f329a8852285b083ce86437e089 (diff) |
sparc64: Refactor OBP cpu scanning code using an iterator.
With feedback from Sam Ravnborg.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/include/asm/prom.h | 1 | ||||
-rw-r--r-- | arch/sparc/kernel/prom_64.c | 233 |
2 files changed, 125 insertions, 109 deletions
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index 900d44714f8d..1b15212563cd 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h | |||
@@ -86,6 +86,7 @@ extern int of_node_to_nid(struct device_node *dp); | |||
86 | #endif | 86 | #endif |
87 | 87 | ||
88 | extern void prom_build_devicetree(void); | 88 | extern void prom_build_devicetree(void); |
89 | extern void of_populate_present_mask(void); | ||
89 | 90 | ||
90 | /* Dummy ref counting routines - to be implemented later */ | 91 | /* Dummy ref counting routines - to be implemented later */ |
91 | static inline struct device_node *of_node_get(struct device_node *node) | 92 | static inline struct device_node *of_node_get(struct device_node *node) |
diff --git a/arch/sparc/kernel/prom_64.c b/arch/sparc/kernel/prom_64.c index ca55c7012f77..4d92f488fae1 100644 --- a/arch/sparc/kernel/prom_64.c +++ b/arch/sparc/kernel/prom_64.c | |||
@@ -374,75 +374,26 @@ static const char *get_mid_prop(void) | |||
374 | return (tlb_type == spitfire ? "upa-portid" : "portid"); | 374 | return (tlb_type == spitfire ? "upa-portid" : "portid"); |
375 | } | 375 | } |
376 | 376 | ||
377 | struct device_node *of_find_node_by_cpuid(int cpuid) | 377 | static void *of_iterate_over_cpus(void *(*func)(struct device_node *, int, int), int arg) |
378 | { | ||
379 | struct device_node *dp; | ||
380 | const char *mid_prop = get_mid_prop(); | ||
381 | |||
382 | for_each_node_by_type(dp, "cpu") { | ||
383 | int id = of_getintprop_default(dp, mid_prop, -1); | ||
384 | const char *this_mid_prop = mid_prop; | ||
385 | |||
386 | if (id < 0) { | ||
387 | this_mid_prop = "cpuid"; | ||
388 | id = of_getintprop_default(dp, this_mid_prop, -1); | ||
389 | } | ||
390 | |||
391 | if (id < 0) { | ||
392 | prom_printf("OF: Serious problem, cpu lacks " | ||
393 | "%s property", this_mid_prop); | ||
394 | prom_halt(); | ||
395 | } | ||
396 | if (cpuid == id) | ||
397 | return dp; | ||
398 | } | ||
399 | return NULL; | ||
400 | } | ||
401 | |||
402 | void __init of_fill_in_cpu_data(void) | ||
403 | { | 378 | { |
404 | struct device_node *dp; | 379 | struct device_node *dp; |
405 | const char *mid_prop; | 380 | const char *mid_prop; |
406 | 381 | ||
407 | if (tlb_type == hypervisor) | ||
408 | return; | ||
409 | |||
410 | mid_prop = get_mid_prop(); | 382 | mid_prop = get_mid_prop(); |
411 | ncpus_probed = 0; | ||
412 | for_each_node_by_type(dp, "cpu") { | 383 | for_each_node_by_type(dp, "cpu") { |
413 | int cpuid = of_getintprop_default(dp, mid_prop, -1); | 384 | int cpuid = of_getintprop_default(dp, mid_prop, -1); |
414 | const char *this_mid_prop = mid_prop; | 385 | const char *this_mid_prop = mid_prop; |
415 | struct device_node *portid_parent; | 386 | void *ret; |
416 | int portid = -1; | ||
417 | 387 | ||
418 | portid_parent = NULL; | ||
419 | if (cpuid < 0) { | 388 | if (cpuid < 0) { |
420 | this_mid_prop = "cpuid"; | 389 | this_mid_prop = "cpuid"; |
421 | cpuid = of_getintprop_default(dp, this_mid_prop, -1); | 390 | cpuid = of_getintprop_default(dp, this_mid_prop, -1); |
422 | if (cpuid >= 0) { | ||
423 | int limit = 2; | ||
424 | |||
425 | portid_parent = dp; | ||
426 | while (limit--) { | ||
427 | portid_parent = portid_parent->parent; | ||
428 | if (!portid_parent) | ||
429 | break; | ||
430 | portid = of_getintprop_default(portid_parent, | ||
431 | "portid", -1); | ||
432 | if (portid >= 0) | ||
433 | break; | ||
434 | } | ||
435 | } | ||
436 | } | 391 | } |
437 | |||
438 | if (cpuid < 0) { | 392 | if (cpuid < 0) { |
439 | prom_printf("OF: Serious problem, cpu lacks " | 393 | prom_printf("OF: Serious problem, cpu lacks " |
440 | "%s property", this_mid_prop); | 394 | "%s property", this_mid_prop); |
441 | prom_halt(); | 395 | prom_halt(); |
442 | } | 396 | } |
443 | |||
444 | ncpus_probed++; | ||
445 | |||
446 | #ifdef CONFIG_SMP | 397 | #ifdef CONFIG_SMP |
447 | if (cpuid >= NR_CPUS) { | 398 | if (cpuid >= NR_CPUS) { |
448 | printk(KERN_WARNING "Ignoring CPU %d which is " | 399 | printk(KERN_WARNING "Ignoring CPU %d which is " |
@@ -450,79 +401,143 @@ void __init of_fill_in_cpu_data(void) | |||
450 | cpuid, NR_CPUS); | 401 | cpuid, NR_CPUS); |
451 | continue; | 402 | continue; |
452 | } | 403 | } |
453 | #else | ||
454 | /* On uniprocessor we only want the values for the | ||
455 | * real physical cpu the kernel booted onto, however | ||
456 | * cpu_data() only has one entry at index 0. | ||
457 | */ | ||
458 | if (cpuid != real_hard_smp_processor_id()) | ||
459 | continue; | ||
460 | cpuid = 0; | ||
461 | #endif | 404 | #endif |
405 | ret = func(dp, cpuid, arg); | ||
406 | if (ret) | ||
407 | return ret; | ||
408 | } | ||
409 | return NULL; | ||
410 | } | ||
462 | 411 | ||
463 | cpu_data(cpuid).clock_tick = | 412 | static void *check_cpu_node(struct device_node *dp, int cpuid, int id) |
464 | of_getintprop_default(dp, "clock-frequency", 0); | 413 | { |
465 | 414 | if (id == cpuid) | |
466 | if (portid_parent) { | 415 | return dp; |
467 | cpu_data(cpuid).dcache_size = | 416 | return NULL; |
468 | of_getintprop_default(dp, "l1-dcache-size", | 417 | } |
469 | 16 * 1024); | 418 | |
470 | cpu_data(cpuid).dcache_line_size = | 419 | struct device_node *of_find_node_by_cpuid(int cpuid) |
471 | of_getintprop_default(dp, "l1-dcache-line-size", | 420 | { |
472 | 32); | 421 | return of_iterate_over_cpus(check_cpu_node, cpuid); |
473 | cpu_data(cpuid).icache_size = | 422 | } |
474 | of_getintprop_default(dp, "l1-icache-size", | 423 | |
475 | 8 * 1024); | 424 | static void *record_one_cpu(struct device_node *dp, int cpuid, int arg) |
476 | cpu_data(cpuid).icache_line_size = | 425 | { |
477 | of_getintprop_default(dp, "l1-icache-line-size", | 426 | ncpus_probed++; |
478 | 32); | ||
479 | cpu_data(cpuid).ecache_size = | ||
480 | of_getintprop_default(dp, "l2-cache-size", 0); | ||
481 | cpu_data(cpuid).ecache_line_size = | ||
482 | of_getintprop_default(dp, "l2-cache-line-size", 0); | ||
483 | if (!cpu_data(cpuid).ecache_size || | ||
484 | !cpu_data(cpuid).ecache_line_size) { | ||
485 | cpu_data(cpuid).ecache_size = | ||
486 | of_getintprop_default(portid_parent, | ||
487 | "l2-cache-size", | ||
488 | (4 * 1024 * 1024)); | ||
489 | cpu_data(cpuid).ecache_line_size = | ||
490 | of_getintprop_default(portid_parent, | ||
491 | "l2-cache-line-size", 64); | ||
492 | } | ||
493 | |||
494 | cpu_data(cpuid).core_id = portid + 1; | ||
495 | cpu_data(cpuid).proc_id = portid; | ||
496 | #ifdef CONFIG_SMP | 427 | #ifdef CONFIG_SMP |
497 | sparc64_multi_core = 1; | 428 | set_cpu_present(cpuid, true); |
429 | set_cpu_possible(cpuid, true); | ||
498 | #endif | 430 | #endif |
499 | } else { | 431 | return NULL; |
500 | cpu_data(cpuid).dcache_size = | 432 | } |
501 | of_getintprop_default(dp, "dcache-size", 16 * 1024); | ||
502 | cpu_data(cpuid).dcache_line_size = | ||
503 | of_getintprop_default(dp, "dcache-line-size", 32); | ||
504 | 433 | ||
505 | cpu_data(cpuid).icache_size = | 434 | void __init of_populate_present_mask(void) |
506 | of_getintprop_default(dp, "icache-size", 16 * 1024); | 435 | { |
507 | cpu_data(cpuid).icache_line_size = | 436 | if (tlb_type == hypervisor) |
508 | of_getintprop_default(dp, "icache-line-size", 32); | 437 | return; |
438 | |||
439 | ncpus_probed = 0; | ||
440 | of_iterate_over_cpus(record_one_cpu, 0); | ||
441 | } | ||
509 | 442 | ||
443 | static void *fill_in_one_cpu(struct device_node *dp, int cpuid, int arg) | ||
444 | { | ||
445 | struct device_node *portid_parent = NULL; | ||
446 | int portid = -1; | ||
447 | |||
448 | if (of_find_property(dp, "cpuid", NULL)) { | ||
449 | int limit = 2; | ||
450 | |||
451 | portid_parent = dp; | ||
452 | while (limit--) { | ||
453 | portid_parent = portid_parent->parent; | ||
454 | if (!portid_parent) | ||
455 | break; | ||
456 | portid = of_getintprop_default(portid_parent, | ||
457 | "portid", -1); | ||
458 | if (portid >= 0) | ||
459 | break; | ||
460 | } | ||
461 | } | ||
462 | |||
463 | #ifndef CONFIG_SMP | ||
464 | /* On uniprocessor we only want the values for the | ||
465 | * real physical cpu the kernel booted onto, however | ||
466 | * cpu_data() only has one entry at index 0. | ||
467 | */ | ||
468 | if (cpuid != real_hard_smp_processor_id()) | ||
469 | return NULL; | ||
470 | cpuid = 0; | ||
471 | #endif | ||
472 | |||
473 | cpu_data(cpuid).clock_tick = | ||
474 | of_getintprop_default(dp, "clock-frequency", 0); | ||
475 | |||
476 | if (portid_parent) { | ||
477 | cpu_data(cpuid).dcache_size = | ||
478 | of_getintprop_default(dp, "l1-dcache-size", | ||
479 | 16 * 1024); | ||
480 | cpu_data(cpuid).dcache_line_size = | ||
481 | of_getintprop_default(dp, "l1-dcache-line-size", | ||
482 | 32); | ||
483 | cpu_data(cpuid).icache_size = | ||
484 | of_getintprop_default(dp, "l1-icache-size", | ||
485 | 8 * 1024); | ||
486 | cpu_data(cpuid).icache_line_size = | ||
487 | of_getintprop_default(dp, "l1-icache-line-size", | ||
488 | 32); | ||
489 | cpu_data(cpuid).ecache_size = | ||
490 | of_getintprop_default(dp, "l2-cache-size", 0); | ||
491 | cpu_data(cpuid).ecache_line_size = | ||
492 | of_getintprop_default(dp, "l2-cache-line-size", 0); | ||
493 | if (!cpu_data(cpuid).ecache_size || | ||
494 | !cpu_data(cpuid).ecache_line_size) { | ||
510 | cpu_data(cpuid).ecache_size = | 495 | cpu_data(cpuid).ecache_size = |
511 | of_getintprop_default(dp, "ecache-size", | 496 | of_getintprop_default(portid_parent, |
497 | "l2-cache-size", | ||
512 | (4 * 1024 * 1024)); | 498 | (4 * 1024 * 1024)); |
513 | cpu_data(cpuid).ecache_line_size = | 499 | cpu_data(cpuid).ecache_line_size = |
514 | of_getintprop_default(dp, "ecache-line-size", 64); | 500 | of_getintprop_default(portid_parent, |
515 | 501 | "l2-cache-line-size", 64); | |
516 | cpu_data(cpuid).core_id = 0; | ||
517 | cpu_data(cpuid).proc_id = -1; | ||
518 | } | 502 | } |
519 | 503 | ||
504 | cpu_data(cpuid).core_id = portid + 1; | ||
505 | cpu_data(cpuid).proc_id = portid; | ||
520 | #ifdef CONFIG_SMP | 506 | #ifdef CONFIG_SMP |
521 | set_cpu_present(cpuid, true); | 507 | sparc64_multi_core = 1; |
522 | set_cpu_possible(cpuid, true); | ||
523 | #endif | 508 | #endif |
509 | } else { | ||
510 | cpu_data(cpuid).dcache_size = | ||
511 | of_getintprop_default(dp, "dcache-size", 16 * 1024); | ||
512 | cpu_data(cpuid).dcache_line_size = | ||
513 | of_getintprop_default(dp, "dcache-line-size", 32); | ||
514 | |||
515 | cpu_data(cpuid).icache_size = | ||
516 | of_getintprop_default(dp, "icache-size", 16 * 1024); | ||
517 | cpu_data(cpuid).icache_line_size = | ||
518 | of_getintprop_default(dp, "icache-line-size", 32); | ||
519 | |||
520 | cpu_data(cpuid).ecache_size = | ||
521 | of_getintprop_default(dp, "ecache-size", | ||
522 | (4 * 1024 * 1024)); | ||
523 | cpu_data(cpuid).ecache_line_size = | ||
524 | of_getintprop_default(dp, "ecache-line-size", 64); | ||
525 | |||
526 | cpu_data(cpuid).core_id = 0; | ||
527 | cpu_data(cpuid).proc_id = -1; | ||
524 | } | 528 | } |
525 | 529 | ||
530 | return NULL; | ||
531 | } | ||
532 | |||
533 | void __init of_fill_in_cpu_data(void) | ||
534 | { | ||
535 | if (tlb_type == hypervisor) | ||
536 | return; | ||
537 | |||
538 | of_populate_present_mask(); | ||
539 | of_iterate_over_cpus(fill_in_one_cpu, 0); | ||
540 | |||
526 | smp_fill_in_sib_core_maps(); | 541 | smp_fill_in_sib_core_maps(); |
527 | } | 542 | } |
528 | 543 | ||