Re: [tip:timers/core] time: Add timekeeping_inject_sleeptime

From: Arve Hjønnevåg
Date: Fri Apr 29 2011 - 21:12:12 EST


2011/4/29 Thomas Gleixner <tglx@xxxxxxxxxxxxx>:
> On Fri, 29 Apr 2011, Arve Hjønnevåg wrote:
>> On Fri, Apr 29, 2011 at 10:31 AM, tip-bot for John Stultz
>> <john.stultz@xxxxxxxxxx> wrote:
>> > -       set_normalized_timespec(&time,
>> > -                               newtime + delta.tv_sec,
>> > -                               (NSEC_PER_SEC >> 1) + delta.tv_nsec);
>> > -       do_settimeofday(&time);
>> > +       /* subtract kernel time between rtc_suspend to rtc_resume */
>> > +       time = timespec_sub(time, timespec_sub(newts, oldts));
>>
>> The delta you got from the rtc can be almost a second to long or
>> short. Do you do anything to prevent these errors from accumulating?
>
> By using the the magic crystal ball to avoid it or what do you have in
> mind ?
>

This is how we worked around the problem with the old code:

diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 09b4437..e55828a 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -42,25 +42,32 @@ static void rtc_device_release(struct device *dev)
*/

static struct timespec delta;
+static struct timespec delta_delta;
static time_t oldtime;

static int rtc_suspend(struct device *dev, pm_message_t mesg)
{
struct rtc_device *rtc = to_rtc_device(dev);
struct rtc_time tm;
- struct timespec ts = current_kernel_time();
+ struct timespec ts;
+ struct timespec new_delta;

if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
return 0;

+ getnstimeofday(&ts);
rtc_read_time(rtc, &tm);
rtc_tm_to_time(&tm, &oldtime);

/* RTC precision is 1 second; adjust delta for avg 1/2 sec err */
- set_normalized_timespec(&delta,
+ set_normalized_timespec(&new_delta,
ts.tv_sec - oldtime,
ts.tv_nsec - (NSEC_PER_SEC >> 1));

+ /* prevent 1/2 sec errors from accumulating */
+ delta_delta = timespec_sub(new_delta, delta);
+ if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2)
+ delta = new_delta;
return 0;
}

@@ -80,6 +87,8 @@ static int rtc_resume(struct device *dev)
return 0;
}
rtc_tm_to_time(&tm, &newtime);
+ if (delta_delta.tv_sec < -1)
+ newtime++;
if (newtime <= oldtime) {
if (newtime < oldtime)
pr_debug("%s: time travel!\n", dev_name(&rtc->dev));



--
Arve Hjønnevåg
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/