diff options
Diffstat (limited to 'kernel/time/ntp.c')
| -rw-r--r-- | kernel/time/ntp.c | 48 | 
1 files changed, 30 insertions, 18 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 24174b4d669..072bb066bb7 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -15,6 +15,7 @@  #include <linux/time.h>  #include <linux/mm.h>  #include <linux/module.h> +#include <linux/rtc.h>  #include "tick-internal.h" @@ -22,7 +23,7 @@   * NTP timekeeping variables:   */ -DEFINE_SPINLOCK(ntp_lock); +DEFINE_RAW_SPINLOCK(ntp_lock);  /* USER_HZ period (usecs): */ @@ -347,7 +348,7 @@ void ntp_clear(void)  {  	unsigned long flags; -	spin_lock_irqsave(&ntp_lock, flags); +	raw_spin_lock_irqsave(&ntp_lock, flags);  	time_adjust	= 0;		/* stop active adjtime() */  	time_status	|= STA_UNSYNC; @@ -361,7 +362,7 @@ void ntp_clear(void)  	/* Clear PPS state variables */  	pps_clear(); -	spin_unlock_irqrestore(&ntp_lock, flags); +	raw_spin_unlock_irqrestore(&ntp_lock, flags);  } @@ -371,9 +372,9 @@ u64 ntp_tick_length(void)  	unsigned long flags;  	s64 ret; -	spin_lock_irqsave(&ntp_lock, flags); +	raw_spin_lock_irqsave(&ntp_lock, flags);  	ret = tick_length; -	spin_unlock_irqrestore(&ntp_lock, flags); +	raw_spin_unlock_irqrestore(&ntp_lock, flags);  	return ret;  } @@ -394,7 +395,7 @@ int second_overflow(unsigned long secs)  	int leap = 0;  	unsigned long flags; -	spin_lock_irqsave(&ntp_lock, flags); +	raw_spin_lock_irqsave(&ntp_lock, flags);  	/*  	 * Leap second processing. If in leap-insert state at the end of the @@ -478,13 +479,12 @@ int second_overflow(unsigned long secs)  	time_adjust = 0;  out: -	spin_unlock_irqrestore(&ntp_lock, flags); +	raw_spin_unlock_irqrestore(&ntp_lock, flags);  	return leap;  } -#ifdef CONFIG_GENERIC_CMOS_UPDATE - +#if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC)  static void sync_cmos_clock(struct work_struct *work);  static DECLARE_DELAYED_WORK(sync_cmos_work, sync_cmos_clock); @@ -510,14 +510,26 @@ static void sync_cmos_clock(struct work_struct *work)  	}  	getnstimeofday(&now); -	if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) -		fail = update_persistent_clock(now); +	if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) { +		struct timespec adjust = now; + +		fail = -ENODEV; +		if (persistent_clock_is_local) +			adjust.tv_sec -= (sys_tz.tz_minuteswest * 60); +#ifdef CONFIG_GENERIC_CMOS_UPDATE +		fail = update_persistent_clock(adjust); +#endif +#ifdef CONFIG_RTC_SYSTOHC +		if (fail == -ENODEV) +			fail = rtc_set_ntp_time(adjust); +#endif +	}  	next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2);  	if (next.tv_nsec <= 0)  		next.tv_nsec += NSEC_PER_SEC; -	if (!fail) +	if (!fail || fail == -ENODEV)  		next.tv_sec = 659;  	else  		next.tv_sec = 0; @@ -660,7 +672,7 @@ int do_adjtimex(struct timex *txc)  	getnstimeofday(&ts); -	spin_lock_irq(&ntp_lock); +	raw_spin_lock_irq(&ntp_lock);  	if (txc->modes & ADJ_ADJTIME) {  		long save_adjust = time_adjust; @@ -702,7 +714,7 @@ int do_adjtimex(struct timex *txc)  	/* fill PPS status fields */  	pps_fill_timex(txc); -	spin_unlock_irq(&ntp_lock); +	raw_spin_unlock_irq(&ntp_lock);  	txc->time.tv_sec = ts.tv_sec;  	txc->time.tv_usec = ts.tv_nsec; @@ -900,7 +912,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)  	pts_norm = pps_normalize_ts(*phase_ts); -	spin_lock_irqsave(&ntp_lock, flags); +	raw_spin_lock_irqsave(&ntp_lock, flags);  	/* clear the error bits, they will be set again if needed */  	time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR); @@ -913,7 +925,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)  	 * just start the frequency interval */  	if (unlikely(pps_fbase.tv_sec == 0)) {  		pps_fbase = *raw_ts; -		spin_unlock_irqrestore(&ntp_lock, flags); +		raw_spin_unlock_irqrestore(&ntp_lock, flags);  		return;  	} @@ -928,7 +940,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)  		time_status |= STA_PPSJITTER;  		/* restart the frequency calibration interval */  		pps_fbase = *raw_ts; -		spin_unlock_irqrestore(&ntp_lock, flags); +		raw_spin_unlock_irqrestore(&ntp_lock, flags);  		pr_err("hardpps: PPSJITTER: bad pulse\n");  		return;  	} @@ -945,7 +957,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)  	hardpps_update_phase(pts_norm.nsec); -	spin_unlock_irqrestore(&ntp_lock, flags); +	raw_spin_unlock_irqrestore(&ntp_lock, flags);  }  EXPORT_SYMBOL(hardpps);  |