aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Linton <jeremy.linton@arm.com>2019-06-26 17:37:15 -0400
committerWill Deacon <will@kernel.org>2019-06-27 11:52:13 -0400
commited2b664fcc8073c09394393756df3fc86977bbac (patch)
tree89872e71ab6996f9938599031b475924361b7eeb
parentae9924667a7ee91d49c91ebbc076451ca6b6293a (diff)
ACPI/PPTT: Modify node flag detection to find last IDENTICAL
The ACPI specification implies that the IDENTICAL flag should be set on all non leaf nodes where the children are identical. This means that we need to be searching for the last node with the identical flag set rather than the first one. Since this flag is also dependent on the table revision, we need to add a bit of extra code to verify the table revision, and the next node's state in the traversal. Since we want to avoid function pointers here, lets just special case the IDENTICAL flag. Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Hanjun Guo <hanjun.guo@linaro.org> Reviewed-by: Sudeep Holla <sudeep.holla@arm.com> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com> Signed-off-by: Will Deacon <will@kernel.org>
-rw-r--r--drivers/acpi/pptt.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index b72e6afaa8fb..05344413f199 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
435static 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
438static struct acpi_pptt_processor *acpi_find_processor_package_id(struct acpi_table_header *table_hdr, 457static 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.