aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/arm_arch_timer.c
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2017-10-16 11:28:38 -0400
committerDaniel Lezcano <daniel.lezcano@linaro.org>2017-10-19 17:49:05 -0400
commit21492e1333a0d07af6968667f128e19088cf5ead (patch)
treee9c0acefa6bff885274b37ef0de7804821da01e6 /drivers/clocksource/arm_arch_timer.c
parent2d764649e4b18409a65befb2bdf1483dd56b992b (diff)
clocksource/drivers/arm_arch_timer: Validate CNTFRQ after enabling frame
The ACPI GTDT code validates the CNTFRQ field of each MMIO timer frame against the CNTFRQ system register of the current CPU, to ensure that they are equal, which is mandated by the architecture. However, reading the CNTFRQ field of a frame is not possible until the RFRQ bit in the frame's CNTACRn register is set, and doing so before that willl produce the following error: arch_timer: [Firmware Bug]: CNTFRQ mismatch: frame @ 0x00000000e0be0000: (0x00000000), CPU: (0x0ee6b280) arch_timer: Disabling MMIO timers due to CNTFRQ mismatch arch_timer: Failed to initialize memory-mapped timer. The reason is that the CNTFRQ field is RES0 if access is not enabled. So move the validation of CNTFRQ into the loop that iterates over the timers to find the best frame, but defer it until after we have selected the best frame, which should also have enabled the RFRQ bit. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r--drivers/clocksource/arm_arch_timer.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index fd4b7f684bd0..14e2419063e9 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1268,10 +1268,6 @@ arch_timer_mem_find_best_frame(struct arch_timer_mem *timer_mem)
1268 1268
1269 iounmap(cntctlbase); 1269 iounmap(cntctlbase);
1270 1270
1271 if (!best_frame)
1272 pr_err("Unable to find a suitable frame in timer @ %pa\n",
1273 &timer_mem->cntctlbase);
1274
1275 return best_frame; 1271 return best_frame;
1276} 1272}
1277 1273
@@ -1372,6 +1368,8 @@ static int __init arch_timer_mem_of_init(struct device_node *np)
1372 1368
1373 frame = arch_timer_mem_find_best_frame(timer_mem); 1369 frame = arch_timer_mem_find_best_frame(timer_mem);
1374 if (!frame) { 1370 if (!frame) {
1371 pr_err("Unable to find a suitable frame in timer @ %pa\n",
1372 &timer_mem->cntctlbase);
1375 ret = -EINVAL; 1373 ret = -EINVAL;
1376 goto out; 1374 goto out;
1377 } 1375 }
@@ -1420,7 +1418,7 @@ arch_timer_mem_verify_cntfrq(struct arch_timer_mem *timer_mem)
1420static int __init arch_timer_mem_acpi_init(int platform_timer_count) 1418static int __init arch_timer_mem_acpi_init(int platform_timer_count)
1421{ 1419{
1422 struct arch_timer_mem *timers, *timer; 1420 struct arch_timer_mem *timers, *timer;
1423 struct arch_timer_mem_frame *frame; 1421 struct arch_timer_mem_frame *frame, *best_frame = NULL;
1424 int timer_count, i, ret = 0; 1422 int timer_count, i, ret = 0;
1425 1423
1426 timers = kcalloc(platform_timer_count, sizeof(*timers), 1424 timers = kcalloc(platform_timer_count, sizeof(*timers),
@@ -1432,14 +1430,6 @@ static int __init arch_timer_mem_acpi_init(int platform_timer_count)
1432 if (ret || !timer_count) 1430 if (ret || !timer_count)
1433 goto out; 1431 goto out;
1434 1432
1435 for (i = 0; i < timer_count; i++) {
1436 ret = arch_timer_mem_verify_cntfrq(&timers[i]);
1437 if (ret) {
1438 pr_err("Disabling MMIO timers due to CNTFRQ mismatch\n");
1439 goto out;
1440 }
1441 }
1442
1443 /* 1433 /*
1444 * While unlikely, it's theoretically possible that none of the frames 1434 * While unlikely, it's theoretically possible that none of the frames
1445 * in a timer expose the combination of feature we want. 1435 * in a timer expose the combination of feature we want.
@@ -1448,12 +1438,26 @@ static int __init arch_timer_mem_acpi_init(int platform_timer_count)
1448 timer = &timers[i]; 1438 timer = &timers[i];
1449 1439
1450 frame = arch_timer_mem_find_best_frame(timer); 1440 frame = arch_timer_mem_find_best_frame(timer);
1451 if (frame) 1441 if (!best_frame)
1452 break; 1442 best_frame = frame;
1443
1444 ret = arch_timer_mem_verify_cntfrq(timer);
1445 if (ret) {
1446 pr_err("Disabling MMIO timers due to CNTFRQ mismatch\n");
1447 goto out;
1448 }
1449
1450 if (!best_frame) /* implies !frame */
1451 /*
1452 * Only complain about missing suitable frames if we
1453 * haven't already found one in a previous iteration.
1454 */
1455 pr_err("Unable to find a suitable frame in timer @ %pa\n",
1456 &timer->cntctlbase);
1453 } 1457 }
1454 1458
1455 if (frame) 1459 if (best_frame)
1456 ret = arch_timer_mem_frame_register(frame); 1460 ret = arch_timer_mem_frame_register(best_frame);
1457out: 1461out:
1458 kfree(timers); 1462 kfree(timers);
1459 return ret; 1463 return ret;