52c17bff3c
This adds kernel support for the Pistachio SoC and the Marduk (Ci40) board which uses it. Much of the code for Pistachio has been upstreamed however some patches are still required to boot from the Marduk board: * spi bug fixes * dma bug fixes * pistachio internal clock tree bug fixes * spi-nand implementation * dts based mtd device naming scheme * dts backports and bug fixes Signed-off-by: Abhijit Mahajani <Abhijit.Mahajani@imgtec.com> Signed-off-by: Francois Berder <francois.berder@imgtec.com> Signed-off-by: Ian Pozella <Ian.Pozella@imgtec.com>
71 lines
2.3 KiB
Diff
71 lines
2.3 KiB
Diff
From b46f8c74afdd30cd52bfdcc2231470a0bab04416 Mon Sep 17 00:00:00 2001
|
|
From: James Hogan <james.hogan@imgtec.com>
|
|
Date: Fri, 22 Apr 2016 18:22:45 +0100
|
|
Subject: clockevents: Retry programming min delta up to 10 times
|
|
|
|
Under virtualisation it is possible to get unexpected latency during a
|
|
clockevent device's set_next_event() callback which can make it return
|
|
-ETIME even for a delta based on min_delta_ns.
|
|
|
|
The clockevents_program_min_delta() implementation for
|
|
CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=n doesn't handle retries when this
|
|
happens, nor does clockevents_program_event() or its callers when force
|
|
is true (for example hrtimer_reprogram()). This can result in hangs
|
|
until the clock event device does a full period.
|
|
|
|
It isn't appropriate to use MIN_ADJUST in this case as occasional
|
|
hypervisor induced high latency will cause min_delta_ns to quickly
|
|
increase to the maximum.
|
|
Instead, borrow the retry pattern from the MIN_ADJUST case, but without
|
|
making adjustments. We retry up to 10 times before giving up.
|
|
|
|
(picked https://patchwork.kernel.org/patch/8909491/)
|
|
|
|
Signed-off-by: James Hogan <james.hogan@imgtec.com>
|
|
---
|
|
kernel/time/clockevents.c | 26 +++++++++++++++++++-------
|
|
1 file changed, 19 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
|
|
index 2c5bc77..ddd7e82 100644
|
|
--- a/kernel/time/clockevents.c
|
|
+++ b/kernel/time/clockevents.c
|
|
@@ -281,16 +281,28 @@ static int clockevents_program_min_delta(struct clock_event_device *dev)
|
|
{
|
|
unsigned long long clc;
|
|
int64_t delta;
|
|
+ int i;
|
|
|
|
- delta = dev->min_delta_ns;
|
|
- dev->next_event = ktime_add_ns(ktime_get(), delta);
|
|
+ for (i = 0;;) {
|
|
+ delta = dev->min_delta_ns;
|
|
+ dev->next_event = ktime_add_ns(ktime_get(), delta);
|
|
|
|
- if (clockevent_state_shutdown(dev))
|
|
- return 0;
|
|
+ if (clockevent_state_shutdown(dev))
|
|
+ return 0;
|
|
|
|
- dev->retries++;
|
|
- clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
|
|
- return dev->set_next_event((unsigned long) clc, dev);
|
|
+ dev->retries++;
|
|
+ clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
|
|
+ if (dev->set_next_event((unsigned long) clc, dev) == 0)
|
|
+ return 0;
|
|
+
|
|
+ if (++i > 9) {
|
|
+ /*
|
|
+ * We tried 10 times to program the device with the
|
|
+ * given min_delta_ns. Get out of here.
|
|
+ */
|
|
+ return -ETIME;
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
#endif /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */
|
|
--
|
|
2.7.4
|
|
|