summaryrefslogtreecommitdiffstats
path: root/common/clock.c
diff options
context:
space:
mode:
authorAndrey Smirnov <andrew.smirnov@gmail.com>2018-06-27 21:54:28 -0700
committerSascha Hauer <s.hauer@pengutronix.de>2018-07-02 06:36:53 +0200
commite9d5e7a983b43e1bd4789098d4279c25f8ff7078 (patch)
tree4180008c610725a7be162bcf41764508259ba9b3 /common/clock.c
parent0ca998a69bb3f889141aad1872ff0fb53979605a (diff)
downloadbarebox-e9d5e7a983b43e1bd4789098d4279c25f8ff7078.tar.gz
common: clock: Sample time before poller_call()
Change is_timeout() to sample current time before invoking poller infrascructure to avoid occasional false timeout conditions. Consider the following timeout loop (can be found in wait_on_timeout): while (!(condition)) { if (is_timeout(...)) { return -ETIMEDOUT; } } ... in the original logic of is_timeout() it was possible to end up in the following situation: 1. Immediate check of of "condition" yeilds false (not enough time for it to become true has passed yet) 2. is_timeout is called which, in turn, calls poller_call() 3. All registerd pollers take more than specified timeout time to execute. 4. Sometime during poller_call() "contition" becomes true 5. As a result of #3 is_timeout() returns "true" 6. Code bails out with -ETIMEDOUT early even though timeout condition didn't really occur. One concrete example of this problem was discovered on ZII RDU1 board (poller_call() is long due to a serdev) when doing large data transfers over SPI to attached DataFlash chip. This commit changes is_timeout() to sample the value of time before calling poller_call(). This way first call to is_timeout() will almost always return false thus checking the condition at least twice before declaring a timeout. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'common/clock.c')
-rw-r--r--common/clock.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/common/clock.c b/common/clock.c
index f98176d..904bee0 100644
--- a/common/clock.c
+++ b/common/clock.c
@@ -181,10 +181,12 @@ EXPORT_SYMBOL(is_timeout_non_interruptible);
int is_timeout(uint64_t start_ns, uint64_t time_offset_ns)
{
+ int ret = is_timeout_non_interruptible(start_ns, time_offset_ns);
+
if (time_offset_ns >= 100 * USECOND)
poller_call();
- return is_timeout_non_interruptible(start_ns, time_offset_ns);
+ return ret;
}
EXPORT_SYMBOL(is_timeout);