Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc244dda authored by John Stultz's avatar John Stultz
Browse files

timekeeping: Move TAI managment into timekeeping core from ntp



Currently NTP manages the TAI offset. Since there's plans for a
CLOCK_TAI clockid, push the TAI management into the timekeeping
core.

CC: Thomas Gleixner <tglx@linutronix.de>
CC: Eric Dumazet <eric.dumazet@gmail.com>
CC: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
parent e445cf1c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -181,6 +181,8 @@ extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
extern int timekeeping_valid_for_hres(void);
extern u64 timekeeping_max_deferment(void);
extern int timekeeping_inject_offset(struct timespec *ts);
extern s32 timekeeping_get_tai_offset(void);
extern void timekeeping_set_tai_offset(s32 tai_offset);

struct tms;
extern void do_sys_times(struct tms *);
+3 −0
Original line number Diff line number Diff line
@@ -62,6 +62,9 @@ struct timekeeper {
	ktime_t			offs_boot;
	/* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
	struct timespec		raw_time;
	/* The current UTC to TAI offset in seconds */
	s32			tai_offset;

	/* Seqlock for all timekeeper values */
	seqlock_t		lock;
};
+10 −8
Original line number Diff line number Diff line
@@ -53,9 +53,6 @@ static int time_state = TIME_OK;
/* clock status bits:							*/
static int			time_status = STA_UNSYNC;

/* TAI offset (secs):							*/
static long			time_tai;

/* time adjustment (nsecs):						*/
static s64			time_offset;

@@ -415,7 +412,6 @@ int second_overflow(unsigned long secs)
		else if (secs % 86400 == 0) {
			leap = -1;
			time_state = TIME_OOP;
			time_tai++;
			printk(KERN_NOTICE
				"Clock: inserting leap second 23:59:60 UTC\n");
		}
@@ -425,7 +421,6 @@ int second_overflow(unsigned long secs)
			time_state = TIME_OK;
		else if ((secs + 1) % 86400 == 0) {
			leap = 1;
			time_tai--;
			time_state = TIME_WAIT;
			printk(KERN_NOTICE
				"Clock: deleting leap second 23:59:59 UTC\n");
@@ -579,7 +574,9 @@ static inline void process_adj_status(struct timex *txc, struct timespec *ts)
 * Called with ntp_lock held, so we can access and modify
 * all the global NTP state:
 */
static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts)
static inline void process_adjtimex_modes(struct timex *txc,
						struct timespec *ts,
						s32 *time_tai)
{
	if (txc->modes & ADJ_STATUS)
		process_adj_status(txc, ts);
@@ -613,7 +610,7 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
	}

	if (txc->modes & ADJ_TAI && txc->constant > 0)
		time_tai = txc->constant;
		*time_tai = txc->constant;

	if (txc->modes & ADJ_OFFSET)
		ntp_update_offset(txc->offset);
@@ -632,6 +629,7 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
int do_adjtimex(struct timex *txc)
{
	struct timespec ts;
	u32 time_tai, orig_tai;
	int result;

	/* Validate the data before disabling interrupts */
@@ -671,6 +669,7 @@ int do_adjtimex(struct timex *txc)
	}

	getnstimeofday(&ts);
	orig_tai = time_tai = timekeeping_get_tai_offset();

	raw_spin_lock_irq(&ntp_lock);

@@ -687,7 +686,7 @@ int do_adjtimex(struct timex *txc)

		/* If there are input parameters, then process them: */
		if (txc->modes)
			process_adjtimex_modes(txc, &ts);
			process_adjtimex_modes(txc, &ts, &time_tai);

		txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
				  NTP_SCALE_SHIFT);
@@ -716,6 +715,9 @@ int do_adjtimex(struct timex *txc)

	raw_spin_unlock_irq(&ntp_lock);

	if (time_tai != orig_tai)
		timekeeping_set_tai_offset(time_tai);

	txc->time.tv_sec = ts.tv_sec;
	txc->time.tv_usec = ts.tv_nsec;
	if (!(time_status & STA_NANO))
+44 −0
Original line number Diff line number Diff line
@@ -513,6 +513,48 @@ int timekeeping_inject_offset(struct timespec *ts)
}
EXPORT_SYMBOL(timekeeping_inject_offset);


/**
 * timekeeping_get_tai_offset - Returns current TAI offset from UTC
 *
 */
s32 timekeeping_get_tai_offset(void)
{
	struct timekeeper *tk = &timekeeper;
	unsigned int seq;
	s32 ret;

	do {
		seq = read_seqbegin(&tk->lock);
		ret = tk->tai_offset;
	} while (read_seqretry(&tk->lock, seq));

	return ret;
}

/**
 * __timekeeping_set_tai_offset - Lock free worker function
 *
 */
void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset)
{
	tk->tai_offset = tai_offset;
}

/**
 * timekeeping_set_tai_offset - Sets the current TAI offset from UTC
 *
 */
void timekeeping_set_tai_offset(s32 tai_offset)
{
	struct timekeeper *tk = &timekeeper;
	unsigned long flags;

	write_seqlock_irqsave(&tk->lock, flags);
	__timekeeping_set_tai_offset(tk, tai_offset);
	write_sequnlock_irqrestore(&tk->lock, flags);
}

/**
 * change_clocksource - Swaps clocksources if a new one is available
 *
@@ -1143,6 +1185,8 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)
			tk_set_wall_to_mono(tk,
				timespec_sub(tk->wall_to_monotonic, ts));

			__timekeeping_set_tai_offset(tk, tk->tai_offset - leap);

			clock_was_set_delayed();
		}
	}