Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70be7025 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "timekeeping: Cap adjustments so they don't exceed the maxadj value"

parents b49958c0 1b6457b8
Loading
Loading
Loading
Loading
+27 −4
Original line number Diff line number Diff line
@@ -1669,9 +1669,12 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
{
	s64 interval = tk->cycle_interval;
	s64 xinterval = tk->xtime_interval;
	u32 base = tk->tkr_mono.clock->mult;
	u32 max = tk->tkr_mono.clock->maxadj;
	u32 cur_adj = tk->tkr_mono.mult;
	s64 tick_error;
	bool negative;
	u32 adj;
	u32 adj_scale;

	/* Remove any current error adj from freq calculation */
	if (tk->ntp_err_mult)
@@ -1690,13 +1693,33 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
	/* preserve the direction of correction */
	negative = (tick_error < 0);

	/* Sort out the magnitude of the correction */
	/* If any adjustment would pass the max, just return */
	if (negative && (cur_adj - 1) <= (base - max))
		return;
	if (!negative && (cur_adj + 1) >= (base + max))
		return;
	/*
	 * Sort out the magnitude of the correction, but
	 * avoid making so large a correction that we go
	 * over the max adjustment.
	 */
	adj_scale = 0;
	tick_error = abs(tick_error);
	for (adj = 0; tick_error > interval; adj++)
	while (tick_error > interval) {
		u32 adj = 1 << (adj_scale + 1);

		/* Check if adjustment gets us within 1 unit from the max */
		if (negative && (cur_adj - adj) <= (base - max))
			break;
		if (!negative && (cur_adj + adj) >= (base + max))
			break;

		adj_scale++;
		tick_error >>= 1;
	}

	/* scale the corrections */
	timekeeping_apply_adjustment(tk, offset, negative, adj);
	timekeeping_apply_adjustment(tk, offset, negative, adj_scale);
}

/*