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

Commit 3ed09c94 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Rafael J. Wysocki
Browse files

cpuidle: menu: allow state 0 to be disabled



The menu driver does not allow state0 to be disabled completely.
If it is disabled but other enabled states don't meet latency
requirements, it is still used.

Fix this by starting with the first enabled idle state. Fall back
to state 0 if no idle states are enabled (arguably this should be
-EINVAL if it is attempted, but this is the minimal fix).

Acked-by: default avatarGautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 654d08a4
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -286,6 +286,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
	struct device *device = get_cpu_device(dev->cpu);
	int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
	int i;
	int first_idx;
	int idx;
	unsigned int interactivity_req;
	unsigned int expected_interval;
	unsigned long nr_iowaiters, cpu_load;
@@ -335,11 +337,11 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
		if (data->next_timer_us > polling_threshold &&
		    latency_req > s->exit_latency && !s->disabled &&
		    !dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable)
			data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
			first_idx = CPUIDLE_DRIVER_STATE_START;
		else
			data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1;
			first_idx = CPUIDLE_DRIVER_STATE_START - 1;
	} else {
		data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
		first_idx = 0;
	}

	/*
@@ -359,20 +361,28 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
	 * Find the idle state with the lowest power while satisfying
	 * our constraints.
	 */
	for (i = data->last_state_idx + 1; i < drv->state_count; i++) {
	idx = -1;
	for (i = first_idx; i < drv->state_count; i++) {
		struct cpuidle_state *s = &drv->states[i];
		struct cpuidle_state_usage *su = &dev->states_usage[i];

		if (s->disabled || su->disable)
			continue;
		if (idx == -1)
			idx = i; /* first enabled state */
		if (s->target_residency > data->predicted_us)
			break;
		if (s->exit_latency > latency_req)
			break;

		data->last_state_idx = i;
		idx = i;
	}

	if (idx == -1)
		idx = 0; /* No states enabled. Must use 0. */

	data->last_state_idx = idx;

	return data->last_state_idx;
}