提交 a157508c 编写于 作者: L Linus Torvalds

Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer core updates from Thomas Gleixner:
 "The time(r) departement provides:

   - more infrastructure work on the year 2038 issue

   - a few fixes in the Armada SoC timers

   - the usual pile of fixlets and improvements"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  clocksource: armada-370-xp: Use the reference clock on A375 SoC
  watchdog: orion: Use the reference clock on Armada 375 SoC
  clocksource: armada-370-xp: Add missing clock enable
  time: Fix sign bug in NTP mult overflow warning
  time: Remove timekeeping_inject_sleeptime()
  rtc: Update suspend/resume timing to use 64bit time
  rtc/lib: Provide y2038 safe rtc_tm_to_time()/rtc_time_to_tm() replacement
  time: Fixup comments to reflect usage of timespec64
  time: Expose get_monotonic_coarse64() for in-kernel uses
  time: Expose getrawmonotonic64 for in-kernel uses
  time: Provide y2038 safe mktime() replacement
  time: Provide y2038 safe timekeeping_inject_sleeptime() replacement
  time: Provide y2038 safe do_settimeofday() replacement
  time: Complete NTP adjustment threshold judging conditions
  time: Avoid possible NTP adjustment mult overflow.
  time: Rename udelay_test.c to test_udelay.c
  clocksource: sirf: Remove hard-coded clock rate
......@@ -2,8 +2,10 @@ Marvell Armada 370 and Armada XP Timers
---------------------------------------
Required properties:
- compatible: Should be either "marvell,armada-370-timer" or
"marvell,armada-xp-timer" as appropriate.
- compatible: Should be one of the following
"marvell,armada-370-timer",
"marvell,armada-375-timer",
"marvell,armada-xp-timer".
- interrupts: Should contain the list of Global Timer interrupts and
then local timer interrupts
- reg: Should contain location and length for timers register. First
......@@ -13,7 +15,8 @@ Required properties:
Clocks required for compatible = "marvell,armada-370-timer":
- clocks : Must contain a single entry describing the clock input
Clocks required for compatible = "marvell,armada-xp-timer":
Clocks required for compatibles = "marvell,armada-xp-timer",
"marvell,armada-375-timer":
- clocks : Must contain an entry for each entry in clock-names.
- clock-names : Must include the following entries:
"nbclk" (L2/coherency fabric clock),
......
......@@ -17,6 +17,18 @@ For "marvell,armada-375-wdt" and "marvell,armada-380-wdt":
- reg : A third entry is mandatory and should contain the
shared mask/unmask RSTOUT address.
Clocks required for compatibles = "marvell,orion-wdt",
"marvell,armada-370-wdt":
- clocks : Must contain a single entry describing the clock input
Clocks required for compatibles = "marvell,armada-xp-wdt"
"marvell,armada-375-wdt"
"marvell,armada-380-wdt":
- clocks : Must contain an entry for each entry in clock-names.
- clock-names : Must include the following entries:
"nbclk" (L2/coherency fabric clock),
"fixed" (Reference 25 MHz fixed-clock).
Optional properties:
- interrupts : Contains the IRQ for watchdog expiration
......@@ -30,4 +42,5 @@ Example:
interrupts = <3>;
timeout-sec = <10>;
status = "okay";
clocks = <&gate_clk 7>;
};
......@@ -318,6 +318,7 @@ static void __init armada_xp_timer_init(struct device_node *np)
/* The 25Mhz fixed clock is mandatory, and must always be available */
BUG_ON(IS_ERR(clk));
clk_prepare_enable(clk);
timer_clk = clk_get_rate(clk);
armada_370_xp_timer_common_init(np);
......@@ -325,11 +326,40 @@ static void __init armada_xp_timer_init(struct device_node *np)
CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
armada_xp_timer_init);
static void __init armada_375_timer_init(struct device_node *np)
{
struct clk *clk;
clk = of_clk_get_by_name(np, "fixed");
if (!IS_ERR(clk)) {
clk_prepare_enable(clk);
timer_clk = clk_get_rate(clk);
} else {
/*
* This fallback is required in order to retain proper
* devicetree backwards compatibility.
*/
clk = of_clk_get(np, 0);
/* Must have at least a clock */
BUG_ON(IS_ERR(clk));
clk_prepare_enable(clk);
timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
timer25Mhz = false;
}
armada_370_xp_timer_common_init(np);
}
CLOCKSOURCE_OF_DECLARE(armada_375, "marvell,armada-375-timer",
armada_375_timer_init);
static void __init armada_370_timer_init(struct device_node *np)
{
struct clk *clk = of_clk_get(np, 0);
BUG_ON(IS_ERR(clk));
clk_prepare_enable(clk);
timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
timer25Mhz = false;
......
......@@ -20,8 +20,6 @@
#include <linux/of_address.h>
#include <linux/sched_clock.h>
#define MARCO_CLOCK_FREQ 1000000
#define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000
#define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004
#define SIRFSOC_TIMER_MATCH_0 0x0018
......@@ -40,6 +38,8 @@
#define SIRFSOC_TIMER_REG_CNT 6
static unsigned long marco_timer_rate;
static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
SIRFSOC_TIMER_WATCHDOG_EN,
SIRFSOC_TIMER_32COUNTER_0_CTRL,
......@@ -195,7 +195,7 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce)
ce->rating = 200;
ce->set_mode = sirfsoc_timer_set_mode;
ce->set_next_event = sirfsoc_timer_set_next_event;
clockevents_calc_mult_shift(ce, MARCO_CLOCK_FREQ, 60);
clockevents_calc_mult_shift(ce, marco_timer_rate, 60);
ce->max_delta_ns = clockevent_delta2ns(-2, ce);
ce->min_delta_ns = clockevent_delta2ns(2, ce);
ce->cpumask = cpumask_of(cpu);
......@@ -257,7 +257,6 @@ static void __init sirfsoc_clockevent_init(void)
/* initialize the kernel jiffy timer source */
static void __init sirfsoc_marco_timer_init(struct device_node *np)
{
unsigned long rate;
u32 timer_div;
struct clk *clk;
......@@ -266,16 +265,12 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np)
BUG_ON(clk_prepare_enable(clk));
rate = clk_get_rate(clk);
BUG_ON(rate < MARCO_CLOCK_FREQ);
BUG_ON(rate % MARCO_CLOCK_FREQ);
marco_timer_rate = clk_get_rate(clk);
/* Initialize the timer dividers */
timer_div = rate / MARCO_CLOCK_FREQ - 1;
writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
/* timer dividers: 0, not divided */
writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
/* Initialize timer counters to 0 */
writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
......@@ -288,7 +283,7 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np)
/* Clear all interrupts */
writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, MARCO_CLOCK_FREQ));
BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, marco_timer_rate));
sirfsoc_clockevent_init();
}
......
......@@ -45,14 +45,14 @@ int rtc_hctosys_ret = -ENODEV;
* system's wall clock; restore it on resume().
*/
static struct timespec old_rtc, old_system, old_delta;
static struct timespec64 old_rtc, old_system, old_delta;
static int rtc_suspend(struct device *dev)
{
struct rtc_device *rtc = to_rtc_device(dev);
struct rtc_time tm;
struct timespec delta, delta_delta;
struct timespec64 delta, delta_delta;
int err;
if (has_persistent_clock())
......@@ -68,8 +68,8 @@ static int rtc_suspend(struct device *dev)
return 0;
}
getnstimeofday(&old_system);
rtc_tm_to_time(&tm, &old_rtc.tv_sec);
getnstimeofday64(&old_system);
old_rtc.tv_sec = rtc_tm_to_time64(&tm);
/*
......@@ -78,8 +78,8 @@ static int rtc_suspend(struct device *dev)
* try to compensate so the difference in system time
* and rtc time stays close to constant.
*/
delta = timespec_sub(old_system, old_rtc);
delta_delta = timespec_sub(delta, old_delta);
delta = timespec64_sub(old_system, old_rtc);
delta_delta = timespec64_sub(delta, old_delta);
if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) {
/*
* if delta_delta is too large, assume time correction
......@@ -88,7 +88,7 @@ static int rtc_suspend(struct device *dev)
old_delta = delta;
} else {
/* Otherwise try to adjust old_system to compensate */
old_system = timespec_sub(old_system, delta_delta);
old_system = timespec64_sub(old_system, delta_delta);
}
return 0;
......@@ -98,8 +98,8 @@ static int rtc_resume(struct device *dev)
{
struct rtc_device *rtc = to_rtc_device(dev);
struct rtc_time tm;
struct timespec new_system, new_rtc;
struct timespec sleep_time;
struct timespec64 new_system, new_rtc;
struct timespec64 sleep_time;
int err;
if (has_persistent_clock())
......@@ -110,7 +110,7 @@ static int rtc_resume(struct device *dev)
return 0;
/* snapshot the current rtc and system time at resume */
getnstimeofday(&new_system);
getnstimeofday64(&new_system);
err = rtc_read_time(rtc, &tm);
if (err < 0) {
pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev));
......@@ -121,7 +121,7 @@ static int rtc_resume(struct device *dev)
pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev));
return 0;
}
rtc_tm_to_time(&tm, &new_rtc.tv_sec);
new_rtc.tv_sec = rtc_tm_to_time64(&tm);
new_rtc.tv_nsec = 0;
if (new_rtc.tv_sec < old_rtc.tv_sec) {
......@@ -130,7 +130,7 @@ static int rtc_resume(struct device *dev)
}
/* calculate the RTC time delta (sleep time)*/
sleep_time = timespec_sub(new_rtc, old_rtc);
sleep_time = timespec64_sub(new_rtc, old_rtc);
/*
* Since these RTC suspend/resume handlers are not called
......@@ -139,11 +139,11 @@ static int rtc_resume(struct device *dev)
* so subtract kernel run-time between rtc_suspend to rtc_resume
* to keep things accurate.
*/
sleep_time = timespec_sub(sleep_time,
timespec_sub(new_system, old_system));
sleep_time = timespec64_sub(sleep_time,
timespec64_sub(new_system, old_system));
if (sleep_time.tv_sec >= 0)
timekeeping_inject_sleeptime(&sleep_time);
timekeeping_inject_sleeptime64(&sleep_time);
rtc_hctosys_ret = 0;
return 0;
}
......
......@@ -45,16 +45,20 @@ int rtc_year_days(unsigned int day, unsigned int month, unsigned int year)
}
EXPORT_SYMBOL(rtc_year_days);
/*
* rtc_time_to_tm64 - Converts time64_t to rtc_time.
* Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
*/
void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
void rtc_time64_to_tm(time64_t time, struct rtc_time *tm)
{
unsigned int month, year;
unsigned long secs;
int days;
days = time / 86400;
time -= (unsigned int) days * 86400;
/* time must be positive */
days = div_s64(time, 86400);
secs = time - (unsigned int) days * 86400;
/* day of the week, 1970-01-01 was a Thursday */
tm->tm_wday = (days + 4) % 7;
......@@ -81,14 +85,14 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
tm->tm_mon = month;
tm->tm_mday = days + 1;
tm->tm_hour = time / 3600;
time -= tm->tm_hour * 3600;
tm->tm_min = time / 60;
tm->tm_sec = time - tm->tm_min * 60;
tm->tm_hour = secs / 3600;
secs -= tm->tm_hour * 3600;
tm->tm_min = secs / 60;
tm->tm_sec = secs - tm->tm_min * 60;
tm->tm_isdst = 0;
}
EXPORT_SYMBOL(rtc_time_to_tm);
EXPORT_SYMBOL(rtc_time64_to_tm);
/*
* Does the rtc_time represent a valid date/time?
......@@ -109,24 +113,22 @@ int rtc_valid_tm(struct rtc_time *tm)
EXPORT_SYMBOL(rtc_valid_tm);
/*
* rtc_tm_to_time64 - Converts rtc_time to time64_t.
* Convert Gregorian date to seconds since 01-01-1970 00:00:00.
*/
int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
time64_t rtc_tm_to_time64(struct rtc_time *tm)
{
*time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
return mktime64(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
return 0;
}
EXPORT_SYMBOL(rtc_tm_to_time);
EXPORT_SYMBOL(rtc_tm_to_time64);
/*
* Convert rtc_time to ktime
*/
ktime_t rtc_tm_to_ktime(struct rtc_time tm)
{
time_t time;
rtc_tm_to_time(&tm, &time);
return ktime_set(time, 0);
return ktime_set(rtc_tm_to_time64(&tm), 0);
}
EXPORT_SYMBOL_GPL(rtc_tm_to_ktime);
......@@ -135,14 +137,14 @@ EXPORT_SYMBOL_GPL(rtc_tm_to_ktime);
*/
struct rtc_time rtc_ktime_to_tm(ktime_t kt)
{
struct timespec ts;
struct timespec64 ts;
struct rtc_time ret;
ts = ktime_to_timespec(kt);
ts = ktime_to_timespec64(kt);
/* Round up any ns */
if (ts.tv_nsec)
ts.tv_sec++;
rtc_time_to_tm(ts.tv_sec, &ret);
rtc_time64_to_tm(ts.tv_sec, &ret);
return ret;
}
EXPORT_SYMBOL_GPL(rtc_ktime_to_tm);
......
......@@ -114,6 +114,46 @@ static int armada370_wdt_clock_init(struct platform_device *pdev,
return 0;
}
static int armada375_wdt_clock_init(struct platform_device *pdev,
struct orion_watchdog *dev)
{
int ret;
dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed");
if (!IS_ERR(dev->clk)) {
ret = clk_prepare_enable(dev->clk);
if (ret) {
clk_put(dev->clk);
return ret;
}
atomic_io_modify(dev->reg + TIMER_CTRL,
WDT_AXP_FIXED_ENABLE_BIT,
WDT_AXP_FIXED_ENABLE_BIT);
dev->clk_rate = clk_get_rate(dev->clk);
return 0;
}
/* Mandatory fallback for proper devicetree backward compatibility */
dev->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk))
return PTR_ERR(dev->clk);
ret = clk_prepare_enable(dev->clk);
if (ret) {
clk_put(dev->clk);
return ret;
}
atomic_io_modify(dev->reg + TIMER_CTRL,
WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT),
WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT));
dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO;
return 0;
}
static int armadaxp_wdt_clock_init(struct platform_device *pdev,
struct orion_watchdog *dev)
{
......@@ -394,7 +434,7 @@ static const struct orion_watchdog_data armada375_data = {
.rstout_mask_bit = BIT(10),
.wdt_enable_bit = BIT(8),
.wdt_counter_offset = 0x34,
.clock_init = armada370_wdt_clock_init,
.clock_init = armada375_wdt_clock_init,
.enabled = armada375_enabled,
.start = armada375_start,
.stop = armada375_stop,
......
......@@ -19,11 +19,28 @@
extern int rtc_month_days(unsigned int month, unsigned int year);
extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year);
extern int rtc_valid_tm(struct rtc_time *tm);
extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
extern time64_t rtc_tm_to_time64(struct rtc_time *tm);
extern void rtc_time64_to_tm(time64_t time, struct rtc_time *tm);
ktime_t rtc_tm_to_ktime(struct rtc_time tm);
struct rtc_time rtc_ktime_to_tm(ktime_t kt);
/**
* Deprecated. Use rtc_time64_to_tm().
*/
static inline void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
{
rtc_time64_to_tm(time, tm);
}
/**
* Deprecated. Use rtc_tm_to_time64().
*/
static inline int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
{
*time = rtc_tm_to_time64(tm);
return 0;
}
#include <linux/device.h>
#include <linux/seq_file.h>
......
......@@ -39,9 +39,20 @@ static inline int timeval_compare(const struct timeval *lhs, const struct timeva
return lhs->tv_usec - rhs->tv_usec;
}
extern unsigned long mktime(const unsigned int year, const unsigned int mon,
const unsigned int day, const unsigned int hour,
const unsigned int min, const unsigned int sec);
extern time64_t mktime64(const unsigned int year, const unsigned int mon,
const unsigned int day, const unsigned int hour,
const unsigned int min, const unsigned int sec);
/**
* Deprecated. Use mktime64().
*/
static inline unsigned long mktime(const unsigned int year,
const unsigned int mon, const unsigned int day,
const unsigned int hour, const unsigned int min,
const unsigned int sec)
{
return mktime64(year, mon, day, hour, min, sec);
}
extern void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec);
......
......@@ -10,7 +10,7 @@ extern int timekeeping_suspended;
* Get and set timeofday
*/
extern void do_gettimeofday(struct timeval *tv);
extern int do_settimeofday(const struct timespec *tv);
extern int do_settimeofday64(const struct timespec64 *ts);
extern int do_sys_settimeofday(const struct timespec *tv,
const struct timezone *tz);
......@@ -25,14 +25,22 @@ struct timespec __current_kernel_time(void);
/*
* timespec based interfaces
*/
struct timespec get_monotonic_coarse(void);
extern void getrawmonotonic(struct timespec *ts);
struct timespec64 get_monotonic_coarse64(void);
extern void getrawmonotonic64(struct timespec64 *ts);
extern void ktime_get_ts64(struct timespec64 *ts);
extern int __getnstimeofday64(struct timespec64 *tv);
extern void getnstimeofday64(struct timespec64 *tv);
#if BITS_PER_LONG == 64
/**
* Deprecated. Use do_settimeofday64().
*/
static inline int do_settimeofday(const struct timespec *ts)
{
return do_settimeofday64(ts);
}
static inline int __getnstimeofday(struct timespec *ts)
{
return __getnstimeofday64(ts);
......@@ -53,7 +61,27 @@ static inline void ktime_get_real_ts(struct timespec *ts)
getnstimeofday64(ts);
}
static inline void getrawmonotonic(struct timespec *ts)
{
getrawmonotonic64(ts);
}
static inline struct timespec get_monotonic_coarse(void)
{
return get_monotonic_coarse64();
}
#else
/**
* Deprecated. Use do_settimeofday64().
*/
static inline int do_settimeofday(const struct timespec *ts)
{
struct timespec64 ts64;
ts64 = timespec_to_timespec64(*ts);
return do_settimeofday64(&ts64);
}
static inline int __getnstimeofday(struct timespec *ts)
{
struct timespec64 ts64;
......@@ -86,6 +114,19 @@ static inline void ktime_get_real_ts(struct timespec *ts)
getnstimeofday64(&ts64);
*ts = timespec64_to_timespec(ts64);
}
static inline void getrawmonotonic(struct timespec *ts)
{
struct timespec64 ts64;
getrawmonotonic64(&ts64);
*ts = timespec64_to_timespec(ts64);
}
static inline struct timespec get_monotonic_coarse(void)
{
return timespec64_to_timespec(get_monotonic_coarse64());
}
#endif
extern void getboottime(struct timespec *ts);
......@@ -182,7 +223,7 @@ static inline void timekeeping_clocktai(struct timespec *ts)
/*
* RTC specific
*/
extern void timekeeping_inject_sleeptime(struct timespec *delta);
extern void timekeeping_inject_sleeptime64(struct timespec64 *delta);
/*
* PPS accessor
......
......@@ -13,7 +13,7 @@ obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o
obj-$(CONFIG_TICK_ONESHOT) += tick-sched.o
obj-$(CONFIG_TIMER_STATS) += timer_stats.o
obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o
obj-$(CONFIG_TEST_UDELAY) += udelay_test.o
obj-$(CONFIG_TEST_UDELAY) += test_udelay.o
$(obj)/time.o: $(obj)/timeconst.h
......
......@@ -304,7 +304,9 @@ struct timespec timespec_trunc(struct timespec t, unsigned gran)
}
EXPORT_SYMBOL(timespec_trunc);
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
/*
* mktime64 - Converts date to seconds.
* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
* => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
*
......@@ -314,15 +316,10 @@ EXPORT_SYMBOL(timespec_trunc);
* -year/100+year/400 terms, and add 10.]
*
* This algorithm was first published by Gauss (I think).
*
* WARNING: this function will overflow on 2106-02-07 06:28:16 on
* machines where long is 32-bit! (However, as time_t is signed, we
* will already get problems at other places on 2038-01-19 03:14:08)
*/
unsigned long
mktime(const unsigned int year0, const unsigned int mon0,
const unsigned int day, const unsigned int hour,
const unsigned int min, const unsigned int sec)
time64_t mktime64(const unsigned int year0, const unsigned int mon0,
const unsigned int day, const unsigned int hour,
const unsigned int min, const unsigned int sec)
{
unsigned int mon = mon0, year = year0;
......@@ -332,15 +329,14 @@ mktime(const unsigned int year0, const unsigned int mon0,
year -= 1;
}
return ((((unsigned long)
return ((((time64_t)
(year/4 - year/100 + year/400 + 367*mon/12 + day) +
year*365 - 719499
)*24 + hour /* now have hours */
)*60 + min /* now have minutes */
)*60 + sec; /* finally seconds */
}
EXPORT_SYMBOL(mktime);
EXPORT_SYMBOL(mktime64);
/**
* set_normalized_timespec - set timespec sec and nsec parts and normalize
......
......@@ -519,9 +519,9 @@ EXPORT_SYMBOL(__getnstimeofday64);
/**
* getnstimeofday64 - Returns the time of day in a timespec64.
* @ts: pointer to the timespec to be set
* @ts: pointer to the timespec64 to be set
*
* Returns the time of day in a timespec (WARN if suspended).
* Returns the time of day in a timespec64 (WARN if suspended).
*/
void getnstimeofday64(struct timespec64 *ts)
{
......@@ -623,7 +623,7 @@ EXPORT_SYMBOL_GPL(ktime_get_raw);
*
* The function calculates the monotonic clock from the realtime
* clock and the wall_to_monotonic offset and stores the result
* in normalized timespec format in the variable pointed to by @ts.
* in normalized timespec64 format in the variable pointed to by @ts.
*/
void ktime_get_ts64(struct timespec64 *ts)
{
......@@ -703,18 +703,18 @@ void do_gettimeofday(struct timeval *tv)
EXPORT_SYMBOL(do_gettimeofday);
/**
* do_settimeofday - Sets the time of day
* @tv: pointer to the timespec variable containing the new time
* do_settimeofday64 - Sets the time of day.
* @ts: pointer to the timespec64 variable containing the new time
*
* Sets the time of day to the new time and update NTP and notify hrtimers
*/
int do_settimeofday(const struct timespec *tv)
int do_settimeofday64(const struct timespec64 *ts)
{
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 ts_delta, xt, tmp;
struct timespec64 ts_delta, xt;
unsigned long flags;
if (!timespec_valid_strict(tv))
if (!timespec64_valid_strict(ts))
return -EINVAL;
raw_spin_lock_irqsave(&timekeeper_lock, flags);
......@@ -723,13 +723,12 @@ int do_settimeofday(const struct timespec *tv)
timekeeping_forward_now(tk);
xt = tk_xtime(tk);
ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;
ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec;
ts_delta.tv_sec = ts->tv_sec - xt.tv_sec;
ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec;
tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta));
tmp = timespec_to_timespec64(*tv);
tk_set_xtime(tk, &tmp);
tk_set_xtime(tk, ts);
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
......@@ -741,7 +740,7 @@ int do_settimeofday(const struct timespec *tv)
return 0;
}
EXPORT_SYMBOL(do_settimeofday);
EXPORT_SYMBOL(do_settimeofday64);
/**
* timekeeping_inject_offset - Adds or subtracts from the current time.
......@@ -895,12 +894,12 @@ int timekeeping_notify(struct clocksource *clock)
}
/**
* getrawmonotonic - Returns the raw monotonic time in a timespec
* @ts: pointer to the timespec to be set
* getrawmonotonic64 - Returns the raw monotonic time in a timespec
* @ts: pointer to the timespec64 to be set
*
* Returns the raw monotonic time (completely un-modified by ntp)
*/
void getrawmonotonic(struct timespec *ts)
void getrawmonotonic64(struct timespec64 *ts)
{
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 ts64;
......@@ -915,9 +914,10 @@ void getrawmonotonic(struct timespec *ts)
} while (read_seqcount_retry(&tk_core.seq, seq));
timespec64_add_ns(&ts64, nsecs);
*ts = timespec64_to_timespec(ts64);
*ts = ts64;
}
EXPORT_SYMBOL(getrawmonotonic);
EXPORT_SYMBOL(getrawmonotonic64);
/**
* timekeeping_valid_for_hres - Check if timekeeping is suitable for hres
......@@ -1068,8 +1068,8 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
}
/**
* timekeeping_inject_sleeptime - Adds suspend interval to timeekeeping values
* @delta: pointer to a timespec delta value
* timekeeping_inject_sleeptime64 - Adds suspend interval to timeekeeping values
* @delta: pointer to a timespec64 delta value
*
* This hook is for architectures that cannot support read_persistent_clock
* because their RTC/persistent clock is only accessible when irqs are enabled.
......@@ -1077,10 +1077,9 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
* This function should only be called by rtc_resume(), and allows
* a suspend offset to be injected into the timekeeping values.
*/
void timekeeping_inject_sleeptime(struct timespec *delta)
void timekeeping_inject_sleeptime64(struct timespec64 *delta)
{
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 tmp;
unsigned long flags;
/*
......@@ -1095,8 +1094,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta)
timekeeping_forward_now(tk);
tmp = timespec_to_timespec64(*delta);
__timekeeping_inject_sleeptime(tk, &tmp);
__timekeeping_inject_sleeptime(tk, delta);
timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
......@@ -1332,6 +1330,12 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
*
* XXX - TODO: Doc ntp_error calculation.
*/
if ((mult_adj > 0) && (tk->tkr.mult + mult_adj < mult_adj)) {
/* NTP adjustment caused clocksource mult overflow */
WARN_ON_ONCE(1);
return;
}
tk->tkr.mult += mult_adj;
tk->xtime_interval += interval;
tk->tkr.xtime_nsec -= offset;
......@@ -1397,7 +1401,8 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
}
if (unlikely(tk->tkr.clock->maxadj &&
(tk->tkr.mult > tk->tkr.clock->mult + tk->tkr.clock->maxadj))) {
(abs(tk->tkr.mult - tk->tkr.clock->mult)
> tk->tkr.clock->maxadj))) {
printk_once(KERN_WARNING
"Adjusting %s more than 11%% (%ld vs %ld)\n",
tk->tkr.clock->name, (long)tk->tkr.mult,
......@@ -1646,7 +1651,7 @@ struct timespec current_kernel_time(void)
}
EXPORT_SYMBOL(current_kernel_time);
struct timespec get_monotonic_coarse(void)
struct timespec64 get_monotonic_coarse64(void)
{
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 now, mono;
......@@ -1662,7 +1667,7 @@ struct timespec get_monotonic_coarse(void)
set_normalized_timespec64(&now, now.tv_sec + mono.tv_sec,
now.tv_nsec + mono.tv_nsec);
return timespec64_to_timespec(now);
return now;
}
/*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册