Let kernel synchronize RTC to system clock.
Reset the STA_UNSYNC flag and maxerror value with every frequency update to let the kernel synchronize the RTC to the system clock (11 minute mode). Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>master
parent
7b162c4821
commit
4929d50a3f
2
clock.c
2
clock.c
|
@ -1070,6 +1070,8 @@ enum servo_state clock_synchronize(struct clock *c,
|
||||||
break;
|
break;
|
||||||
case SERVO_LOCKED:
|
case SERVO_LOCKED:
|
||||||
clockadj_set_freq(c->clkid, -adj);
|
clockadj_set_freq(c->clkid, -adj);
|
||||||
|
if (c->clkid == CLOCK_REALTIME)
|
||||||
|
sysclk_set_sync();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
|
|
17
clockadj.c
17
clockadj.c
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
#define NS_PER_SEC 1000000000LL
|
#define NS_PER_SEC 1000000000LL
|
||||||
|
|
||||||
|
static int realtime_leap_bit;
|
||||||
|
|
||||||
void clockadj_set_freq(clockid_t clkid, double freq)
|
void clockadj_set_freq(clockid_t clkid, double freq)
|
||||||
{
|
{
|
||||||
struct timex tx;
|
struct timex tx;
|
||||||
|
@ -94,6 +96,7 @@ void sysclk_set_leap(int leap)
|
||||||
pr_err("failed to set the clock status: %m");
|
pr_err("failed to set the clock status: %m");
|
||||||
else if (m)
|
else if (m)
|
||||||
pr_notice(m);
|
pr_notice(m);
|
||||||
|
realtime_leap_bit = tx.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sysclk_max_freq(void)
|
int sysclk_max_freq(void)
|
||||||
|
@ -110,3 +113,17 @@ int sysclk_max_freq(void)
|
||||||
f = 500000;
|
f = 500000;
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sysclk_set_sync(void)
|
||||||
|
{
|
||||||
|
clockid_t clkid = CLOCK_REALTIME;
|
||||||
|
struct timex tx;
|
||||||
|
memset(&tx, 0, sizeof(tx));
|
||||||
|
/* Clear the STA_UNSYNC flag from the status and keep the maxerror
|
||||||
|
value (which is increased automatically by 500 ppm) below 16 seconds
|
||||||
|
to avoid getting the STA_UNSYNC flag back. */
|
||||||
|
tx.modes = ADJ_STATUS | ADJ_MAXERROR;
|
||||||
|
tx.status = realtime_leap_bit;
|
||||||
|
if (clock_adjtime(clkid, &tx) < 0)
|
||||||
|
pr_err("failed to set clock status and maximum error: %m");
|
||||||
|
}
|
||||||
|
|
|
@ -57,4 +57,9 @@ void sysclk_set_leap(int leap);
|
||||||
*/
|
*/
|
||||||
int sysclk_max_freq(void);
|
int sysclk_max_freq(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the system clock as synchronized to let the kernel synchronize
|
||||||
|
* the real-time clock (RTC) to it.
|
||||||
|
*/
|
||||||
|
void sysclk_set_sync(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -187,6 +187,8 @@ static void update_clock(struct clock *clock,
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
case SERVO_LOCKED:
|
case SERVO_LOCKED:
|
||||||
clockadj_set_freq(clock->clkid, -ppb);
|
clockadj_set_freq(clock->clkid, -ppb);
|
||||||
|
if (clock->clkid == CLOCK_REALTIME)
|
||||||
|
sysclk_set_sync();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue