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

Commit 5ee36f52 authored by Mahesh Sivasubramanian's avatar Mahesh Sivasubramanian
Browse files

msm: pm: Prevent system sleeps when suspend is in progress



The MPM driver sends a XO vote for suspend during suspend prepare
callback. If the CPU were to execute a system low power mode after
suspend, the MPM driver votes against XO shutdown based on the list of
enabled interrupts. This vote is never removed and results in the XO
vote for shutdown overridden by the idle parameters.

Fix issue by ensuring that the system doesn't enter system low power
mode when the device is preparing for suspend. This would also prevent
RPM power collapse as RPM could turn off XO based on state of the
suspend votes sent as a part of suspend_prepare.

CRs-fixed: 551806
Change-Id: I9104f28898c995f69b8c0b9124651b915e15f690
Signed-off-by: default avatarMahesh Sivasubramanian <msivasub@codeaurora.org>
parent ede485fc
Loading
Loading
Loading
Loading
+26 −3
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ static struct msm_mpm_device_data msm_mpm_dev_data;

static struct clk *xo_clk;
static bool xo_enabled;
static bool msm_mpm_in_suspend;
static struct workqueue_struct *msm_mpm_wq;
static struct work_struct msm_mpm_work;
static struct completion wake_wq;
@@ -273,7 +274,8 @@ static int msm_mpm_enable_irq_exclusive(
		else
			__clear_bit(d->hwirq, irq_apps);

		if (!wakeset && (msm_mpm_initialized & MSM_MPM_DEVICE_PROBED))
		if ((msm_mpm_initialized & MSM_MPM_DEVICE_PROBED)
				&& !wakeset && !msm_mpm_in_suspend)
			complete(&wake_wq);
	}

@@ -582,17 +584,33 @@ static void msm_mpm_sys_low_power_modes(bool allow)

void msm_mpm_suspend_prepare(void)
{
	bool allow = msm_mpm_irqs_detectable(false) &&
	bool allow;
	unsigned long flags;

	spin_lock_irqsave(&msm_mpm_lock, flags);

	allow = msm_mpm_irqs_detectable(false) &&
		msm_mpm_gpio_irqs_detectable(false);
	msm_mpm_in_suspend = true;

	spin_unlock_irqrestore(&msm_mpm_lock, flags);
	msm_mpm_sys_low_power_modes(allow);
}
EXPORT_SYMBOL(msm_mpm_suspend_prepare);

void msm_mpm_suspend_wake(void)
{
	bool allow = msm_mpm_irqs_detectable(true) &&
	bool allow;
	unsigned long flags;

	spin_lock_irqsave(&msm_mpm_lock, flags);

	allow = msm_mpm_irqs_detectable(true) &&
		msm_mpm_gpio_irqs_detectable(true);

	spin_unlock_irqrestore(&msm_mpm_lock, flags);
	msm_mpm_sys_low_power_modes(allow);
	msm_mpm_in_suspend = false;
}
EXPORT_SYMBOL(msm_mpm_suspend_wake);

@@ -605,6 +623,11 @@ static void msm_mpm_work_fn(struct work_struct *work)
		spin_lock_irqsave(&msm_mpm_lock, flags);
		allow = msm_mpm_irqs_detectable(true) &&
				msm_mpm_gpio_irqs_detectable(true);
		if (msm_mpm_in_suspend) {
			spin_unlock_irqrestore(&msm_mpm_lock, flags);
			continue;
		}

		spin_unlock_irqrestore(&msm_mpm_lock, flags);
		msm_mpm_sys_low_power_modes(allow);
	}
+4 −1
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ static bool msm_pm_retention_calls_tz;
static bool msm_no_ramp_down_pc;
static struct msm_pm_sleep_status_data *msm_pm_slp_sts;
static bool msm_pm_pc_reset_timer;
static bool msm_pm_in_suspend;

DEFINE_PER_CPU(struct clk *, cpu_clks);
static struct clk *l2_clk;
@@ -822,7 +823,7 @@ static int msm_pm_idle_prepare(struct cpuidle_device *dev,

		switch (mode) {
		case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
			if (num_online_cpus() > 1)
			if (num_online_cpus() > 1 || msm_pm_in_suspend)
				allow = false;
			break;
		case MSM_PM_SLEEP_MODE_RETENTION:
@@ -1174,6 +1175,7 @@ void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops)
static int msm_suspend_prepare(void)
{
	suspend_time = msm_pm_timer_enter_suspend(&suspend_period);
	msm_pm_in_suspend = true;
	msm_mpm_suspend_prepare();
	return 0;
}
@@ -1191,6 +1193,7 @@ static void msm_suspend_wake(void)
					suspend_time);
		suspend_power_collapsed = false;
	}
	msm_pm_in_suspend = false;
}

static const struct platform_suspend_ops msm_pm_ops = {