diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/time/timekeeping.c | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 3be559b6fd0a..b7db4916415b 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -1255,7 +1255,7 @@ void __init timekeeping_init(void) | |||
| 1255 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1255 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
| 1256 | } | 1256 | } |
| 1257 | 1257 | ||
| 1258 | /* time in seconds when suspend began */ | 1258 | /* time in seconds when suspend began for persistent clock */ |
| 1259 | static struct timespec64 timekeeping_suspend_time; | 1259 | static struct timespec64 timekeeping_suspend_time; |
| 1260 | 1260 | ||
| 1261 | /** | 1261 | /** |
| @@ -1428,24 +1428,26 @@ int timekeeping_suspend(void) | |||
| 1428 | timekeeping_forward_now(tk); | 1428 | timekeeping_forward_now(tk); |
| 1429 | timekeeping_suspended = 1; | 1429 | timekeeping_suspended = 1; |
| 1430 | 1430 | ||
| 1431 | /* | 1431 | if (has_persistent_clock()) { |
| 1432 | * To avoid drift caused by repeated suspend/resumes, | ||
| 1433 | * which each can add ~1 second drift error, | ||
| 1434 | * try to compensate so the difference in system time | ||
| 1435 | * and persistent_clock time stays close to constant. | ||
| 1436 | */ | ||
| 1437 | delta = timespec64_sub(tk_xtime(tk), timekeeping_suspend_time); | ||
| 1438 | delta_delta = timespec64_sub(delta, old_delta); | ||
| 1439 | if (abs(delta_delta.tv_sec) >= 2) { | ||
| 1440 | /* | 1432 | /* |
| 1441 | * if delta_delta is too large, assume time correction | 1433 | * To avoid drift caused by repeated suspend/resumes, |
| 1442 | * has occured and set old_delta to the current delta. | 1434 | * which each can add ~1 second drift error, |
| 1435 | * try to compensate so the difference in system time | ||
| 1436 | * and persistent_clock time stays close to constant. | ||
| 1443 | */ | 1437 | */ |
| 1444 | old_delta = delta; | 1438 | delta = timespec64_sub(tk_xtime(tk), timekeeping_suspend_time); |
| 1445 | } else { | 1439 | delta_delta = timespec64_sub(delta, old_delta); |
| 1446 | /* Otherwise try to adjust old_system to compensate */ | 1440 | if (abs(delta_delta.tv_sec) >= 2) { |
| 1447 | timekeeping_suspend_time = | 1441 | /* |
| 1448 | timespec64_add(timekeeping_suspend_time, delta_delta); | 1442 | * if delta_delta is too large, assume time correction |
| 1443 | * has occurred and set old_delta to the current delta. | ||
| 1444 | */ | ||
| 1445 | old_delta = delta; | ||
| 1446 | } else { | ||
| 1447 | /* Otherwise try to adjust old_system to compensate */ | ||
| 1448 | timekeeping_suspend_time = | ||
| 1449 | timespec64_add(timekeeping_suspend_time, delta_delta); | ||
| 1450 | } | ||
| 1449 | } | 1451 | } |
| 1450 | 1452 | ||
| 1451 | timekeeping_update(tk, TK_MIRROR); | 1453 | timekeeping_update(tk, TK_MIRROR); |
