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

Commit e033caa0 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 5f5a1660 9baf4a38
Loading
Loading
Loading
Loading
+27 −4
Original line number Original line Diff line number Diff line
@@ -1386,9 +1386,12 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
{
{
	s64 interval = tk->cycle_interval;
	s64 interval = tk->cycle_interval;
	s64 xinterval = tk->xtime_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;
	s64 tick_error;
	bool negative;
	bool negative;
	u32 adj;
	u32 adj_scale;


	/* Remove any current error adj from freq calculation */
	/* Remove any current error adj from freq calculation */
	if (tk->ntp_err_mult)
	if (tk->ntp_err_mult)
@@ -1407,13 +1410,33 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
	/* preserve the direction of correction */
	/* preserve the direction of correction */
	negative = (tick_error < 0);
	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 = abs64(tick_error);
	tick_error = abs64(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;
		tick_error >>= 1;
	}


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


/*
/*