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

Commit 9bb4b8c5 authored by Mahesh Sivasubramanian's avatar Mahesh Sivasubramanian
Browse files

drivers: cpuidle: lpm-levels: Update ordering for broadcast timer



The idle driver on a core switches to using broadcast timer after a
Core's low power mode is determined. During cluster mode prediction,
the driver sets a timer to wake the cluster up to avoid penalities of
choosing a shallower low power mode for longer duration of time. In
order to reprogram the broadcast timer, the driver forcibly disable and
enable broadcast timer from within the idle thread. This causes
stability issues with local timers not getting enabled on CPUs that
could have woken up for a rude interrupt.

Fix by moving the switch to broadcast to after CPU/cluster prediction
within the idle driver.

Change-Id: I84c7129fcd8fd9ea61d78658d88c69253db45359
Signed-off-by: default avatarMahesh Sivasubramanian <msivasub@codeaurora.org>
parent 814e5c69
Loading
Loading
Loading
Loading
+9 −10
Original line number Diff line number Diff line
@@ -1027,9 +1027,7 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx,
	if (predicted && (idx < (cluster->nlevels - 1))) {
		struct power_params *pwr_params = &cluster->levels[idx].pwr;

		tick_broadcast_exit();
		clusttimer_start(cluster, pwr_params->max_residency + tmr_add);
		tick_broadcast_enter();
	}

	return 0;
@@ -1082,10 +1080,8 @@ static void cluster_prepare(struct lpm_cluster *cluster,
			struct power_params *pwr_params =
						&cluster->levels[0].pwr;

			tick_broadcast_exit();
			clusttimer_start(cluster,
					pwr_params->max_residency + tmr_add);
			tick_broadcast_enter();
		}
	}

@@ -1192,9 +1188,6 @@ static inline void cpu_prepare(struct lpm_cpu *cpu, int cpu_index,
	 * next wakeup within a cluster, in which case, CPU switches over to
	 * use broadcast timer.
	 */
	if (from_idle && cpu_level->use_bc_timer)
		tick_broadcast_enter();

	if (from_idle && ((cpu_level->mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE)
		|| (cpu_level->mode ==
			MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)
@@ -1214,9 +1207,6 @@ static inline void cpu_unprepare(struct lpm_cpu *cpu, int cpu_index,
	struct lpm_cpu_level *cpu_level = &cpu->levels[cpu_index];
	bool jtag_save_restore = cpu->levels[cpu_index].jtag_save_restore;

	if (from_idle && cpu_level->use_bc_timer)
		tick_broadcast_exit();

	if (from_idle && ((cpu_level->mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE)
		|| (cpu_level->mode ==
			MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)
@@ -1268,6 +1258,11 @@ static bool psci_enter_sleep(struct lpm_cpu *cpu, int idx, bool from_idle)
	/*
	 * idx = 0 is the default LPM state
	 */
	if (from_idle && cpu->levels[idx].use_bc_timer) {
		if (tick_broadcast_enter())
			return false;
	}

	if (!idx) {
		stop_critical_timings();
		wfi();
@@ -1286,6 +1281,10 @@ static bool psci_enter_sleep(struct lpm_cpu *cpu, int idx, bool from_idle)
	start_critical_timings();
	update_debug_pc_event(CPU_EXIT, state_id,
			success, 0xdeaffeed, true);

	if (from_idle && cpu->levels[idx].use_bc_timer)
		tick_broadcast_exit();

	return success;
}