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
Miroslav Lichvar 2013-04-08 15:44:10 +02:00 committed by Richard Cochran
parent 7b162c4821
commit 4929d50a3f
4 changed files with 26 additions and 0 deletions

View File

@ -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;

View File

@ -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");
}

View File

@ -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

View File

@ -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;
} }