diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2017-02-21 09:37:30 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2017-04-07 06:22:10 -0400 |
commit | 5a38bcac1f2f0bd0d24700690e36a277ffd0396d (patch) | |
tree | 3e7d1f3b3acf85b176276612940b76111104fdbd /drivers/clocksource/arm_arch_timer.c | |
parent | fa8d815fac96e7c9247783d5a1f8fa4685b3c543 (diff) |
arm64: arch_timer: Allow erratum matching with ACPI OEM information
Just as we're able to identify a broken platform using some DT
information, let's enable a way to spot the offenders with ACPI.
The difference is that we can only match on some OEM info instead
of implementation-specific properties. So in order to avoid the
insane multiplication of errata structures, we allow an array
of OEM descriptions to be attached to an erratum structure.
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: dann frazier <dann.frazier@canonical.com>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 8459d19a84f5..887f6d00a71d 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -190,6 +190,12 @@ static struct cyclecounter cyclecounter __ro_after_init = { | |||
190 | .mask = CLOCKSOURCE_MASK(56), | 190 | .mask = CLOCKSOURCE_MASK(56), |
191 | }; | 191 | }; |
192 | 192 | ||
193 | struct ate_acpi_oem_info { | ||
194 | char oem_id[ACPI_OEM_ID_SIZE + 1]; | ||
195 | char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; | ||
196 | u32 oem_revision; | ||
197 | }; | ||
198 | |||
193 | #ifdef CONFIG_FSL_ERRATUM_A008585 | 199 | #ifdef CONFIG_FSL_ERRATUM_A008585 |
194 | /* | 200 | /* |
195 | * The number of retries is an arbitrary value well beyond the highest number | 201 | * The number of retries is an arbitrary value well beyond the highest number |
@@ -371,6 +377,28 @@ bool arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workarou | |||
371 | return this_cpu_has_cap((uintptr_t)wa->id); | 377 | return this_cpu_has_cap((uintptr_t)wa->id); |
372 | } | 378 | } |
373 | 379 | ||
380 | |||
381 | static | ||
382 | bool arch_timer_check_acpi_oem_erratum(const struct arch_timer_erratum_workaround *wa, | ||
383 | const void *arg) | ||
384 | { | ||
385 | static const struct ate_acpi_oem_info empty_oem_info = {}; | ||
386 | const struct ate_acpi_oem_info *info = wa->id; | ||
387 | const struct acpi_table_header *table = arg; | ||
388 | |||
389 | /* Iterate over the ACPI OEM info array, looking for a match */ | ||
390 | while (memcmp(info, &empty_oem_info, sizeof(*info))) { | ||
391 | if (!memcmp(info->oem_id, table->oem_id, ACPI_OEM_ID_SIZE) && | ||
392 | !memcmp(info->oem_table_id, table->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) && | ||
393 | info->oem_revision == table->oem_revision) | ||
394 | return true; | ||
395 | |||
396 | info++; | ||
397 | } | ||
398 | |||
399 | return false; | ||
400 | } | ||
401 | |||
374 | static const struct arch_timer_erratum_workaround * | 402 | static const struct arch_timer_erratum_workaround * |
375 | arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, | 403 | arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, |
376 | ate_match_fn_t match_fn, | 404 | ate_match_fn_t match_fn, |
@@ -431,6 +459,9 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t | |||
431 | match_fn = arch_timer_check_local_cap_erratum; | 459 | match_fn = arch_timer_check_local_cap_erratum; |
432 | local = true; | 460 | local = true; |
433 | break; | 461 | break; |
462 | case ate_match_acpi_oem_info: | ||
463 | match_fn = arch_timer_check_acpi_oem_erratum; | ||
464 | break; | ||
434 | default: | 465 | default: |
435 | WARN_ON(1); | 466 | WARN_ON(1); |
436 | return; | 467 | return; |
@@ -1277,6 +1308,9 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) | |||
1277 | /* Always-on capability */ | 1308 | /* Always-on capability */ |
1278 | arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); | 1309 | arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); |
1279 | 1310 | ||
1311 | /* Check for globally applicable workarounds */ | ||
1312 | arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table); | ||
1313 | |||
1280 | arch_timer_init(); | 1314 | arch_timer_init(); |
1281 | return 0; | 1315 | return 0; |
1282 | } | 1316 | } |