diff options
Diffstat (limited to 'drivers/acpi/pptt.c')
-rw-r--r-- | drivers/acpi/pptt.c | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index b72e6afaa8fb..1e7ac0bd0d3a 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c | |||
@@ -432,17 +432,40 @@ static void cache_setup_acpi_cpu(struct acpi_table_header *table, | |||
432 | } | 432 | } |
433 | } | 433 | } |
434 | 434 | ||
435 | static bool flag_identical(struct acpi_table_header *table_hdr, | ||
436 | struct acpi_pptt_processor *cpu) | ||
437 | { | ||
438 | struct acpi_pptt_processor *next; | ||
439 | |||
440 | /* heterogeneous machines must use PPTT revision > 1 */ | ||
441 | if (table_hdr->revision < 2) | ||
442 | return false; | ||
443 | |||
444 | /* Locate the last node in the tree with IDENTICAL set */ | ||
445 | if (cpu->flags & ACPI_PPTT_ACPI_IDENTICAL) { | ||
446 | next = fetch_pptt_node(table_hdr, cpu->parent); | ||
447 | if (!(next && next->flags & ACPI_PPTT_ACPI_IDENTICAL)) | ||
448 | return true; | ||
449 | } | ||
450 | |||
451 | return false; | ||
452 | } | ||
453 | |||
435 | /* Passing level values greater than this will result in search termination */ | 454 | /* Passing level values greater than this will result in search termination */ |
436 | #define PPTT_ABORT_PACKAGE 0xFF | 455 | #define PPTT_ABORT_PACKAGE 0xFF |
437 | 456 | ||
438 | static struct acpi_pptt_processor *acpi_find_processor_package_id(struct acpi_table_header *table_hdr, | 457 | static struct acpi_pptt_processor *acpi_find_processor_tag(struct acpi_table_header *table_hdr, |
439 | struct acpi_pptt_processor *cpu, | 458 | struct acpi_pptt_processor *cpu, |
440 | int level, int flag) | 459 | int level, int flag) |
441 | { | 460 | { |
442 | struct acpi_pptt_processor *prev_node; | 461 | struct acpi_pptt_processor *prev_node; |
443 | 462 | ||
444 | while (cpu && level) { | 463 | while (cpu && level) { |
445 | if (cpu->flags & flag) | 464 | /* special case the identical flag to find last identical */ |
465 | if (flag == ACPI_PPTT_ACPI_IDENTICAL) { | ||
466 | if (flag_identical(table_hdr, cpu)) | ||
467 | break; | ||
468 | } else if (cpu->flags & flag) | ||
446 | break; | 469 | break; |
447 | pr_debug("level %d\n", level); | 470 | pr_debug("level %d\n", level); |
448 | prev_node = fetch_pptt_node(table_hdr, cpu->parent); | 471 | prev_node = fetch_pptt_node(table_hdr, cpu->parent); |
@@ -480,8 +503,8 @@ static int topology_get_acpi_cpu_tag(struct acpi_table_header *table, | |||
480 | 503 | ||
481 | cpu_node = acpi_find_processor_node(table, acpi_cpu_id); | 504 | cpu_node = acpi_find_processor_node(table, acpi_cpu_id); |
482 | if (cpu_node) { | 505 | if (cpu_node) { |
483 | cpu_node = acpi_find_processor_package_id(table, cpu_node, | 506 | cpu_node = acpi_find_processor_tag(table, cpu_node, |
484 | level, flag); | 507 | level, flag); |
485 | /* | 508 | /* |
486 | * As per specification if the processor structure represents | 509 | * As per specification if the processor structure represents |
487 | * an actual processor, then ACPI processor ID must be valid. | 510 | * an actual processor, then ACPI processor ID must be valid. |
@@ -660,3 +683,29 @@ int find_acpi_cpu_topology_package(unsigned int cpu) | |||
660 | return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, | 683 | return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, |
661 | ACPI_PPTT_PHYSICAL_PACKAGE); | 684 | ACPI_PPTT_PHYSICAL_PACKAGE); |
662 | } | 685 | } |
686 | |||
687 | /** | ||
688 | * find_acpi_cpu_topology_hetero_id() - Get a core architecture tag | ||
689 | * @cpu: Kernel logical CPU number | ||
690 | * | ||
691 | * Determine a unique heterogeneous tag for the given CPU. CPUs with the same | ||
692 | * implementation should have matching tags. | ||
693 | * | ||
694 | * The returned tag can be used to group peers with identical implementation. | ||
695 | * | ||
696 | * The search terminates when a level is found with the identical implementation | ||
697 | * flag set or we reach a root node. | ||
698 | * | ||
699 | * Due to limitations in the PPTT data structure, there may be rare situations | ||
700 | * where two cores in a heterogeneous machine may be identical, but won't have | ||
701 | * the same tag. | ||
702 | * | ||
703 | * Return: -ENOENT if the PPTT doesn't exist, or the CPU cannot be found. | ||
704 | * Otherwise returns a value which represents a group of identical cores | ||
705 | * similar to this CPU. | ||
706 | */ | ||
707 | int find_acpi_cpu_topology_hetero_id(unsigned int cpu) | ||
708 | { | ||
709 | return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, | ||
710 | ACPI_PPTT_ACPI_IDENTICAL); | ||
711 | } | ||