diff options
author | Xunlei Pang <pang.xunlei@linaro.org> | 2015-04-01 23:34:38 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-04-03 02:18:34 -0400 |
commit | 0fa88cb4b82b5cf7429bc1cef9db006ca035754e (patch) | |
tree | b3800f619ee137e6914e56bf803968642bd389af /kernel | |
parent | 264bb3f79f2a465477cdcd2f0554e21aedc443a3 (diff) |
time, drivers/rtc: Don't bother with rtc_resume() for the nonstop clocksource
If a system does not provide a persistent_clock(), the time
will be updated on resume by rtc_resume(). With the addition
of the non-stop clocksources for suspend timing, those systems
set the time on resume in timekeeping_resume(), but may not
provide a valid persistent_clock().
This results in the rtc_resume() logic thinking no one has set
the time and it then will over-write the suspend time again,
which is not necessary and only increases clock error.
So, fix this for rtc_resume().
This patch also improves the name of persistent_clock_exist to
make it more grammatical.
Signed-off-by: Xunlei Pang <pang.xunlei@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1427945681-29972-19-git-send-email-john.stultz@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/time/timekeeping.c | 66 |
1 files changed, 49 insertions, 17 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index b7db4916415b..79b9bc6e7876 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -64,9 +64,6 @@ static struct tk_fast tk_fast_raw ____cacheline_aligned; | |||
64 | /* flag for if timekeeping is suspended */ | 64 | /* flag for if timekeeping is suspended */ |
65 | int __read_mostly timekeeping_suspended; | 65 | int __read_mostly timekeeping_suspended; |
66 | 66 | ||
67 | /* Flag for if there is a persistent clock on this platform */ | ||
68 | bool __read_mostly persistent_clock_exist = false; | ||
69 | |||
70 | static inline void tk_normalize_xtime(struct timekeeper *tk) | 67 | static inline void tk_normalize_xtime(struct timekeeper *tk) |
71 | { | 68 | { |
72 | while (tk->tkr_mono.xtime_nsec >= ((u64)NSEC_PER_SEC << tk->tkr_mono.shift)) { | 69 | while (tk->tkr_mono.xtime_nsec >= ((u64)NSEC_PER_SEC << tk->tkr_mono.shift)) { |
@@ -1204,6 +1201,12 @@ void __weak read_boot_clock64(struct timespec64 *ts64) | |||
1204 | *ts64 = timespec_to_timespec64(ts); | 1201 | *ts64 = timespec_to_timespec64(ts); |
1205 | } | 1202 | } |
1206 | 1203 | ||
1204 | /* Flag for if timekeeping_resume() has injected sleeptime */ | ||
1205 | static bool sleeptime_injected; | ||
1206 | |||
1207 | /* Flag for if there is a persistent clock on this platform */ | ||
1208 | static bool persistent_clock_exists; | ||
1209 | |||
1207 | /* | 1210 | /* |
1208 | * timekeeping_init - Initializes the clocksource and common timekeeping values | 1211 | * timekeeping_init - Initializes the clocksource and common timekeeping values |
1209 | */ | 1212 | */ |
@@ -1221,7 +1224,7 @@ void __init timekeeping_init(void) | |||
1221 | now.tv_sec = 0; | 1224 | now.tv_sec = 0; |
1222 | now.tv_nsec = 0; | 1225 | now.tv_nsec = 0; |
1223 | } else if (now.tv_sec || now.tv_nsec) | 1226 | } else if (now.tv_sec || now.tv_nsec) |
1224 | persistent_clock_exist = true; | 1227 | persistent_clock_exists = true; |
1225 | 1228 | ||
1226 | read_boot_clock64(&boot); | 1229 | read_boot_clock64(&boot); |
1227 | if (!timespec64_valid_strict(&boot)) { | 1230 | if (!timespec64_valid_strict(&boot)) { |
@@ -1282,11 +1285,47 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk, | |||
1282 | 1285 | ||
1283 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_RTC_HCTOSYS_DEVICE) | 1286 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_RTC_HCTOSYS_DEVICE) |
1284 | /** | 1287 | /** |
1288 | * We have three kinds of time sources to use for sleep time | ||
1289 | * injection, the preference order is: | ||
1290 | * 1) non-stop clocksource | ||
1291 | * 2) persistent clock (ie: RTC accessible when irqs are off) | ||
1292 | * 3) RTC | ||
1293 | * | ||
1294 | * 1) and 2) are used by timekeeping, 3) by RTC subsystem. | ||
1295 | * If system has neither 1) nor 2), 3) will be used finally. | ||
1296 | * | ||
1297 | * | ||
1298 | * If timekeeping has injected sleeptime via either 1) or 2), | ||
1299 | * 3) becomes needless, so in this case we don't need to call | ||
1300 | * rtc_resume(), and this is what timekeeping_rtc_skipresume() | ||
1301 | * means. | ||
1302 | */ | ||
1303 | bool timekeeping_rtc_skipresume(void) | ||
1304 | { | ||
1305 | return sleeptime_injected; | ||
1306 | } | ||
1307 | |||
1308 | /** | ||
1309 | * 1) can be determined whether to use or not only when doing | ||
1310 | * timekeeping_resume() which is invoked after rtc_suspend(), | ||
1311 | * so we can't skip rtc_suspend() surely if system has 1). | ||
1312 | * | ||
1313 | * But if system has 2), 2) will definitely be used, so in this | ||
1314 | * case we don't need to call rtc_suspend(), and this is what | ||
1315 | * timekeeping_rtc_skipsuspend() means. | ||
1316 | */ | ||
1317 | bool timekeeping_rtc_skipsuspend(void) | ||
1318 | { | ||
1319 | return persistent_clock_exists; | ||
1320 | } | ||
1321 | |||
1322 | /** | ||
1285 | * timekeeping_inject_sleeptime64 - Adds suspend interval to timeekeeping values | 1323 | * timekeeping_inject_sleeptime64 - Adds suspend interval to timeekeeping values |
1286 | * @delta: pointer to a timespec64 delta value | 1324 | * @delta: pointer to a timespec64 delta value |
1287 | * | 1325 | * |
1288 | * This hook is for architectures that cannot support read_persistent_clock64 | 1326 | * This hook is for architectures that cannot support read_persistent_clock64 |
1289 | * because their RTC/persistent clock is only accessible when irqs are enabled. | 1327 | * because their RTC/persistent clock is only accessible when irqs are enabled. |
1328 | * and also don't have an effective nonstop clocksource. | ||
1290 | * | 1329 | * |
1291 | * This function should only be called by rtc_resume(), and allows | 1330 | * This function should only be called by rtc_resume(), and allows |
1292 | * a suspend offset to be injected into the timekeeping values. | 1331 | * a suspend offset to be injected into the timekeeping values. |
@@ -1296,13 +1335,6 @@ void timekeeping_inject_sleeptime64(struct timespec64 *delta) | |||
1296 | struct timekeeper *tk = &tk_core.timekeeper; | 1335 | struct timekeeper *tk = &tk_core.timekeeper; |
1297 | unsigned long flags; | 1336 | unsigned long flags; |
1298 | 1337 | ||
1299 | /* | ||
1300 | * Make sure we don't set the clock twice, as timekeeping_resume() | ||
1301 | * already did it | ||
1302 | */ | ||
1303 | if (has_persistent_clock()) | ||
1304 | return; | ||
1305 | |||
1306 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 1338 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
1307 | write_seqcount_begin(&tk_core.seq); | 1339 | write_seqcount_begin(&tk_core.seq); |
1308 | 1340 | ||
@@ -1334,8 +1366,8 @@ void timekeeping_resume(void) | |||
1334 | unsigned long flags; | 1366 | unsigned long flags; |
1335 | struct timespec64 ts_new, ts_delta; | 1367 | struct timespec64 ts_new, ts_delta; |
1336 | cycle_t cycle_now, cycle_delta; | 1368 | cycle_t cycle_now, cycle_delta; |
1337 | bool suspendtime_found = false; | ||
1338 | 1369 | ||
1370 | sleeptime_injected = false; | ||
1339 | read_persistent_clock64(&ts_new); | 1371 | read_persistent_clock64(&ts_new); |
1340 | 1372 | ||
1341 | clockevents_resume(); | 1373 | clockevents_resume(); |
@@ -1381,13 +1413,13 @@ void timekeeping_resume(void) | |||
1381 | nsec += ((u64) cycle_delta * mult) >> shift; | 1413 | nsec += ((u64) cycle_delta * mult) >> shift; |
1382 | 1414 | ||
1383 | ts_delta = ns_to_timespec64(nsec); | 1415 | ts_delta = ns_to_timespec64(nsec); |
1384 | suspendtime_found = true; | 1416 | sleeptime_injected = true; |
1385 | } else if (timespec64_compare(&ts_new, &timekeeping_suspend_time) > 0) { | 1417 | } else if (timespec64_compare(&ts_new, &timekeeping_suspend_time) > 0) { |
1386 | ts_delta = timespec64_sub(ts_new, timekeeping_suspend_time); | 1418 | ts_delta = timespec64_sub(ts_new, timekeeping_suspend_time); |
1387 | suspendtime_found = true; | 1419 | sleeptime_injected = true; |
1388 | } | 1420 | } |
1389 | 1421 | ||
1390 | if (suspendtime_found) | 1422 | if (sleeptime_injected) |
1391 | __timekeeping_inject_sleeptime(tk, &ts_delta); | 1423 | __timekeeping_inject_sleeptime(tk, &ts_delta); |
1392 | 1424 | ||
1393 | /* Re-base the last cycle value */ | 1425 | /* Re-base the last cycle value */ |
@@ -1421,14 +1453,14 @@ int timekeeping_suspend(void) | |||
1421 | * value returned, update the persistent_clock_exists flag. | 1453 | * value returned, update the persistent_clock_exists flag. |
1422 | */ | 1454 | */ |
1423 | if (timekeeping_suspend_time.tv_sec || timekeeping_suspend_time.tv_nsec) | 1455 | if (timekeeping_suspend_time.tv_sec || timekeeping_suspend_time.tv_nsec) |
1424 | persistent_clock_exist = true; | 1456 | persistent_clock_exists = true; |
1425 | 1457 | ||
1426 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 1458 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
1427 | write_seqcount_begin(&tk_core.seq); | 1459 | write_seqcount_begin(&tk_core.seq); |
1428 | timekeeping_forward_now(tk); | 1460 | timekeeping_forward_now(tk); |
1429 | timekeeping_suspended = 1; | 1461 | timekeeping_suspended = 1; |
1430 | 1462 | ||
1431 | if (has_persistent_clock()) { | 1463 | if (persistent_clock_exists) { |
1432 | /* | 1464 | /* |
1433 | * To avoid drift caused by repeated suspend/resumes, | 1465 | * To avoid drift caused by repeated suspend/resumes, |
1434 | * which each can add ~1 second drift error, | 1466 | * which each can add ~1 second drift error, |