diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index 05af9a3..97464e9 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -103,6 +103,10 @@ struct timekeeper {
 	 * shifted nano seconds. */
 	s64			ntp_error;
 	u32			ntp_error_shift;
+
+	/* Mult adjustment being applied to correct freq error */
+	u32			ntp_freq_mult;
+	/* Mult adjustment being applied to correct ntp_error */
 	u32			ntp_err_mult;
 };
 
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 91db941..315bcb8 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -179,6 +179,7 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
 	 * to counteract clock drifting.
 	 */
 	tk->tkr.mult = clock->mult;
+	tk->ntp_freq_mult = clock->mult;
 	tk->ntp_err_mult = 0;
 }
 
@@ -1352,20 +1353,20 @@ device_initcall(timekeeping_init_ops);
  */
 static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
 							 s64 offset,
-							 bool negative,
-							 int adj_scale)
+							 int adj)
 {
 	s64 interval = tk->cycle_interval;
-	s32 mult_adj = 1;
 
-	if (negative) {
-		mult_adj = -mult_adj;
+	if (!adj)
+		return;
+
+	if (unlikely(abs(adj) > 1)) {
+		interval *= adj;
+		offset  *= adj;
+	} else if (adj < 0) {
 		interval = -interval;
 		offset  = -offset;
 	}
-	mult_adj <<= adj_scale;
-	interval <<= adj_scale;
-	offset <<= adj_scale;
 
 	/*
 	 * So the following can be confusing.
@@ -1373,7 +1374,7 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
 	 * To keep things simple, lets assume mult_adj == 1 for now.
 	 *
 	 * When mult_adj != 1, remember that the interval and offset values
-	 * have been appropriately scaled so the math is the same.
+	 * have been appropriately multiplied so the math is the same.
 	 *
 	 * The basic idea here is that we're increasing the multiplier
 	 * by one, this causes the xtime_interval to be incremented by
@@ -1416,13 +1417,7 @@ 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->tkr.mult += adj;
 	tk->xtime_interval += interval;
 	tk->tkr.xtime_nsec -= offset;
 	tk->ntp_error -= (interval - offset) << tk->ntp_error_shift;
@@ -1435,36 +1430,13 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
 static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
 							s64 offset)
 {
-	s64 interval = tk->cycle_interval;
-	s64 xinterval = tk->xtime_interval;
-	s64 tick_error;
-	bool negative;
-	u32 adj;
-
-	/* Remove any current error adj from freq calculation */
-	if (tk->ntp_err_mult)
-		xinterval -= tk->cycle_interval;
-
-	tk->ntp_tick = ntp_tick_length();
+	s64 tick_ns;
 
-	/* Calculate current error per tick */
-	tick_error = ntp_tick_length() >> tk->ntp_error_shift;
-	tick_error -= (xinterval + tk->xtime_remainder);
-
-	/* Don't worry about correcting it if its small */
-	if (likely((tick_error >= 0) && (tick_error <= interval)))
+	if (likely(tk->ntp_tick == ntp_tick_length()))
 		return;
-
-	/* preserve the direction of correction */
-	negative = (tick_error < 0);
-
-	/* Sort out the magnitude of the correction */
-	tick_error = abs(tick_error);
-	for (adj = 0; tick_error > interval; adj++)
-		tick_error >>= 1;
-
-	/* scale the corrections */
-	timekeeping_apply_adjustment(tk, offset, negative, adj);
+	tk->ntp_tick = ntp_tick_length();
+	tick_ns = (tk->ntp_tick >> tk->ntp_error_shift) - tk->xtime_remainder;
+	tk->ntp_freq_mult = div64_u64(tick_ns, tk->cycle_interval);
 }
 
 /*
@@ -1473,18 +1445,19 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
  */
 static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
 {
+	u32 new_mult;
+
 	/* Correct for the current frequency error */
 	timekeeping_freqadjust(tk, offset);
 
 	/* Next make a small adjustment to fix any cumulative error */
-	if (!tk->ntp_err_mult && (tk->ntp_error > 0)) {
+	if (tk->ntp_error > 0)
 		tk->ntp_err_mult = 1;
-		timekeeping_apply_adjustment(tk, offset, 0, 0);
-	} else if (tk->ntp_err_mult && (tk->ntp_error <= 0)) {
-		/* Undo any existing error adjustment */
-		timekeeping_apply_adjustment(tk, offset, 1, 0);
+	else
 		tk->ntp_err_mult = 0;
-	}
+
+	new_mult = tk->ntp_freq_mult + tk->ntp_err_mult;
+	timekeeping_apply_adjustment(tk, offset, new_mult - tk->mult);
 
 	if (unlikely(tk->tkr.clock->maxadj &&
 		(abs(tk->tkr.mult - tk->tkr.clock->mult)
