Commit 9917de73 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull power management fixes from Rafael Wysocki:
 "Fix a recent regression in the timer events oriented (TEO) cpuidle
  governor causing it to misbehave when idle state 0 is disabled and
  rename two local variables for improved clarity on top of that"

* tag 'pm-5.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpuidle: teo: Rename two local variables in teo_select()
  cpuidle: teo: Fix alternative idle state lookup
parents 5d609689 4adae7dd
Loading
Loading
Loading
Loading
+31 −17
Original line number Diff line number Diff line
@@ -382,8 +382,8 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
	alt_intercepts = 2 * idx_intercept_sum > cpu_data->total - idx_hit_sum;
	alt_recent = idx_recent_sum > NR_RECENT / 2;
	if (alt_recent || alt_intercepts) {
		s64 last_enabled_span_ns = duration_ns;
		int last_enabled_idx = idx;
		s64 first_suitable_span_ns = duration_ns;
		int first_suitable_idx = idx;

		/*
		 * Look for the deepest idle state whose target residency had
@@ -397,37 +397,51 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
		intercept_sum = 0;
		recent_sum = 0;

		for (i = idx - 1; i >= idx0; i--) {
		for (i = idx - 1; i >= 0; i--) {
			struct teo_bin *bin = &cpu_data->state_bins[i];
			s64 span_ns;

			intercept_sum += bin->intercepts;
			recent_sum += bin->recent;

			if (dev->states_usage[i].disable)
				continue;

			span_ns = teo_middle_of_bin(i, drv);
			if (!teo_time_ok(span_ns)) {
				/*
				 * The current state is too shallow, so select
				 * the first enabled deeper state.
				 */
				duration_ns = last_enabled_span_ns;
				idx = last_enabled_idx;
				break;
			}

			if ((!alt_recent || 2 * recent_sum > idx_recent_sum) &&
			    (!alt_intercepts ||
			     2 * intercept_sum > idx_intercept_sum)) {
				if (teo_time_ok(span_ns) &&
				    !dev->states_usage[i].disable) {
					idx = i;
					duration_ns = span_ns;
				} else {
					/*
					 * The current state is too shallow or
					 * disabled, so take the first enabled
					 * deeper state with suitable time span.
					 */
					idx = first_suitable_idx;
					duration_ns = first_suitable_span_ns;
				}
				break;
			}

			if (dev->states_usage[i].disable)
				continue;

			if (!teo_time_ok(span_ns)) {
				/*
				 * The current state is too shallow, but if an
				 * alternative candidate state has been found,
				 * it may still turn out to be a better choice.
				 */
				if (first_suitable_idx != idx)
					continue;

				break;
			}

			last_enabled_span_ns = span_ns;
			last_enabled_idx = i;
			first_suitable_span_ns = span_ns;
			first_suitable_idx = i;
		}
	}