diff options
| author | David S. Miller <davem@davemloft.net> | 2012-07-19 11:17:30 -0700 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-07-19 11:17:30 -0700 | 
| commit | abaa72d7fd9a20a67b62e6afa0e746e27851dc33 (patch) | |
| tree | ebe4134fcc93a6e205e6004b3e652d7a62281651 /kernel/time/timekeeping.c | |
| parent | 67da22d23fa6f3324e03bcd0580b914b2e4afbf3 (diff) | |
| parent | 3e4b9459fb0e149c6b74c9e89399a8fc39a92b44 (diff) | |
| download | olio-linux-3.10-abaa72d7fd9a20a67b62e6afa0e746e27851dc33.tar.xz olio-linux-3.10-abaa72d7fd9a20a67b62e6afa0e746e27851dc33.zip  | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
	drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
Diffstat (limited to 'kernel/time/timekeeping.c')
| -rw-r--r-- | kernel/time/timekeeping.c | 64 | 
1 files changed, 62 insertions, 2 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 6f46a00a1e8..3447cfaf11e 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -70,6 +70,12 @@ struct timekeeper {  	/* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */  	struct timespec raw_time; +	/* Offset clock monotonic -> clock realtime */ +	ktime_t offs_real; + +	/* Offset clock monotonic -> clock boottime */ +	ktime_t offs_boot; +  	/* Seqlock for all timekeeper values */  	seqlock_t lock;  }; @@ -172,6 +178,14 @@ static inline s64 timekeeping_get_ns_raw(void)  	return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);  } +static void update_rt_offset(void) +{ +	struct timespec tmp, *wtm = &timekeeper.wall_to_monotonic; + +	set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec); +	timekeeper.offs_real = timespec_to_ktime(tmp); +} +  /* must hold write on timekeeper.lock */  static void timekeeping_update(bool clearntp)  { @@ -179,6 +193,7 @@ static void timekeeping_update(bool clearntp)  		timekeeper.ntp_error = 0;  		ntp_clear();  	} +	update_rt_offset();  	update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic,  			 timekeeper.clock, timekeeper.mult);  } @@ -604,6 +619,7 @@ void __init timekeeping_init(void)  	}  	set_normalized_timespec(&timekeeper.wall_to_monotonic,  				-boot.tv_sec, -boot.tv_nsec); +	update_rt_offset();  	timekeeper.total_sleep_time.tv_sec = 0;  	timekeeper.total_sleep_time.tv_nsec = 0;  	write_sequnlock_irqrestore(&timekeeper.lock, flags); @@ -612,6 +628,12 @@ void __init timekeeping_init(void)  /* time in seconds when suspend began */  static struct timespec timekeeping_suspend_time; +static void update_sleep_time(struct timespec t) +{ +	timekeeper.total_sleep_time = t; +	timekeeper.offs_boot = timespec_to_ktime(t); +} +  /**   * __timekeeping_inject_sleeptime - Internal function to add sleep interval   * @delta: pointer to a timespec delta value @@ -630,8 +652,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta)  	timekeeper.xtime = timespec_add(timekeeper.xtime, *delta);  	timekeeper.wall_to_monotonic =  			timespec_sub(timekeeper.wall_to_monotonic, *delta); -	timekeeper.total_sleep_time = timespec_add( -					timekeeper.total_sleep_time, *delta); +	update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta));  } @@ -696,6 +717,7 @@ static void timekeeping_resume(void)  	timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);  	timekeeper.ntp_error = 0;  	timekeeping_suspended = 0; +	timekeeping_update(false);  	write_sequnlock_irqrestore(&timekeeper.lock, flags);  	touch_softlockup_watchdog(); @@ -963,6 +985,8 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)  		leap = second_overflow(timekeeper.xtime.tv_sec);  		timekeeper.xtime.tv_sec += leap;  		timekeeper.wall_to_monotonic.tv_sec -= leap; +		if (leap) +			clock_was_set_delayed();  	}  	/* Accumulate raw time */ @@ -1079,6 +1103,8 @@ static void update_wall_time(void)  		leap = second_overflow(timekeeper.xtime.tv_sec);  		timekeeper.xtime.tv_sec += leap;  		timekeeper.wall_to_monotonic.tv_sec -= leap; +		if (leap) +			clock_was_set_delayed();  	}  	timekeeping_update(false); @@ -1246,6 +1272,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,  	} while (read_seqretry(&timekeeper.lock, seq));  } +#ifdef CONFIG_HIGH_RES_TIMERS +/** + * ktime_get_update_offsets - hrtimer helper + * @offs_real:	pointer to storage for monotonic -> realtime offset + * @offs_boot:	pointer to storage for monotonic -> boottime offset + * + * Returns current monotonic time and updates the offsets + * Called from hrtimer_interupt() or retrigger_next_event() + */ +ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) +{ +	ktime_t now; +	unsigned int seq; +	u64 secs, nsecs; + +	do { +		seq = read_seqbegin(&timekeeper.lock); + +		secs = timekeeper.xtime.tv_sec; +		nsecs = timekeeper.xtime.tv_nsec; +		nsecs += timekeeping_get_ns(); +		/* If arch requires, add in gettimeoffset() */ +		nsecs += arch_gettimeoffset(); + +		*offs_real = timekeeper.offs_real; +		*offs_boot = timekeeper.offs_boot; +	} while (read_seqretry(&timekeeper.lock, seq)); + +	now = ktime_add_ns(ktime_set(secs, 0), nsecs); +	now = ktime_sub(now, *offs_real); +	return now; +} +#endif +  /**   * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format   */  |