aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/timekeeping.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r--kernel/time/timekeeping.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index d563c1960302..34b4cedfa80d 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -305,8 +305,7 @@ static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
305 305
306 delta = timekeeping_get_delta(tkr); 306 delta = timekeeping_get_delta(tkr);
307 307
308 nsec = delta * tkr->mult + tkr->xtime_nsec; 308 nsec = (delta * tkr->mult + tkr->xtime_nsec) >> tkr->shift;
309 nsec >>= tkr->shift;
310 309
311 /* If arch requires, add in get_arch_timeoffset() */ 310 /* If arch requires, add in get_arch_timeoffset() */
312 return nsec + arch_gettimeoffset(); 311 return nsec + arch_gettimeoffset();
@@ -846,6 +845,19 @@ time64_t ktime_get_real_seconds(void)
846} 845}
847EXPORT_SYMBOL_GPL(ktime_get_real_seconds); 846EXPORT_SYMBOL_GPL(ktime_get_real_seconds);
848 847
848/**
849 * __ktime_get_real_seconds - The same as ktime_get_real_seconds
850 * but without the sequence counter protect. This internal function
851 * is called just when timekeeping lock is already held.
852 */
853time64_t __ktime_get_real_seconds(void)
854{
855 struct timekeeper *tk = &tk_core.timekeeper;
856
857 return tk->xtime_sec;
858}
859
860
849#ifdef CONFIG_NTP_PPS 861#ifdef CONFIG_NTP_PPS
850 862
851/** 863/**
@@ -959,7 +971,7 @@ int timekeeping_inject_offset(struct timespec *ts)
959 struct timespec64 ts64, tmp; 971 struct timespec64 ts64, tmp;
960 int ret = 0; 972 int ret = 0;
961 973
962 if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) 974 if (!timespec_inject_offset_valid(ts))
963 return -EINVAL; 975 return -EINVAL;
964 976
965 ts64 = timespec_to_timespec64(*ts); 977 ts64 = timespec_to_timespec64(*ts);
@@ -1592,9 +1604,12 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
1592{ 1604{
1593 s64 interval = tk->cycle_interval; 1605 s64 interval = tk->cycle_interval;
1594 s64 xinterval = tk->xtime_interval; 1606 s64 xinterval = tk->xtime_interval;
1607 u32 base = tk->tkr_mono.clock->mult;
1608 u32 max = tk->tkr_mono.clock->maxadj;
1609 u32 cur_adj = tk->tkr_mono.mult;
1595 s64 tick_error; 1610 s64 tick_error;
1596 bool negative; 1611 bool negative;
1597 u32 adj; 1612 u32 adj_scale;
1598 1613
1599 /* Remove any current error adj from freq calculation */ 1614 /* Remove any current error adj from freq calculation */
1600 if (tk->ntp_err_mult) 1615 if (tk->ntp_err_mult)
@@ -1613,13 +1628,33 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
1613 /* preserve the direction of correction */ 1628 /* preserve the direction of correction */
1614 negative = (tick_error < 0); 1629 negative = (tick_error < 0);
1615 1630
1616 /* Sort out the magnitude of the correction */ 1631 /* If any adjustment would pass the max, just return */
1632 if (negative && (cur_adj - 1) <= (base - max))
1633 return;
1634 if (!negative && (cur_adj + 1) >= (base + max))
1635 return;
1636 /*
1637 * Sort out the magnitude of the correction, but
1638 * avoid making so large a correction that we go
1639 * over the max adjustment.
1640 */
1641 adj_scale = 0;
1617 tick_error = abs(tick_error); 1642 tick_error = abs(tick_error);
1618 for (adj = 0; tick_error > interval; adj++) 1643 while (tick_error > interval) {
1644 u32 adj = 1 << (adj_scale + 1);
1645
1646 /* Check if adjustment gets us within 1 unit from the max */
1647 if (negative && (cur_adj - adj) <= (base - max))
1648 break;
1649 if (!negative && (cur_adj + adj) >= (base + max))
1650 break;
1651
1652 adj_scale++;
1619 tick_error >>= 1; 1653 tick_error >>= 1;
1654 }
1620 1655
1621 /* scale the corrections */ 1656 /* scale the corrections */
1622 timekeeping_apply_adjustment(tk, offset, negative, adj); 1657 timekeeping_apply_adjustment(tk, offset, negative, adj_scale);
1623} 1658}
1624 1659
1625/* 1660/*