[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20111207161222.762773568@clark.kroah.org>
Date: Wed, 07 Dec 2011 08:12:39 -0800
From: Greg KH <gregkh@...e.de>
To: <linux-kernel@...r.kernel.org>, <stable@...r.kernel.org>
Cc: <torvalds@...ux-foundation.org>, <akpm@...ux-foundation.org>,
<alan@...rguk.ukuu.org.uk>,
Arve Hjønnevåg <arve@...roid.com>,
John Stultz <john.stultz@...aro.org>
Subject: [097/104] rtc: Fix some bugs that allowed accumulating time drift in suspend/resume
3.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= <arve@...roid.com>
commit 6a8943d9ec2567572fca25cf69ad45844d0141a3 upstream.
The current code checks if abs(delta_delta.tv_sec) is greater or
equal to two before it discards the old delta value, but this can
trigger at close to -1 seconds since -1.000000001 seconds is stored
as tv_sec -2 and tv_nsec 999999999 in a normalized timespec.
rtc_resume had an early return check if the rtc value had not changed
since rtc_suspend. This effectivly stops time for the duration of the
short sleep. Check if sleep_time is positive after all the adjustments
have been applied instead since this allows the old_system adjustment
in rtc_suspend to have an effect even for short sleep cycles.
Signed-off-by: Arve Hjønnevåg <arve@...roid.com>
Signed-off-by: John Stultz <john.stultz@...aro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@...e.de>
---
drivers/rtc/class.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -66,7 +66,7 @@ static int rtc_suspend(struct device *de
*/
delta = timespec_sub(old_system, old_rtc);
delta_delta = timespec_sub(delta, old_delta);
- if (abs(delta_delta.tv_sec) >= 2) {
+ if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) {
/*
* if delta_delta is too large, assume time correction
* has occured and set old_delta to the current delta.
@@ -100,9 +100,8 @@ static int rtc_resume(struct device *dev
rtc_tm_to_time(&tm, &new_rtc.tv_sec);
new_rtc.tv_nsec = 0;
- if (new_rtc.tv_sec <= old_rtc.tv_sec) {
- if (new_rtc.tv_sec < old_rtc.tv_sec)
- pr_debug("%s: time travel!\n", dev_name(&rtc->dev));
+ if (new_rtc.tv_sec < old_rtc.tv_sec) {
+ pr_debug("%s: time travel!\n", dev_name(&rtc->dev));
return 0;
}
@@ -119,7 +118,8 @@ static int rtc_resume(struct device *dev
sleep_time = timespec_sub(sleep_time,
timespec_sub(new_system, old_system));
- timekeeping_inject_sleeptime(&sleep_time);
+ if (sleep_time.tv_sec >= 0)
+ timekeeping_inject_sleeptime(&sleep_time);
return 0;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists