lkml.org 
[lkml]   [2011]   [Dec]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    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@android.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@android.com>
    Signed-off-by: John Stultz <john.stultz@linaro.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.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@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2011-12-07 17:37    [W:0.022 / U:0.864 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site