Merge back cpuidle changes for v5.11.
This commit is contained in:
commit
0f6e2cb45b
@ -1363,41 +1363,60 @@ static void genpd_complete(struct device *dev)
|
||||
genpd_unlock(genpd);
|
||||
}
|
||||
|
||||
/**
|
||||
* genpd_syscore_switch - Switch power during system core suspend or resume.
|
||||
* @dev: Device that normally is marked as "always on" to switch power for.
|
||||
*
|
||||
* This routine may only be called during the system core (syscore) suspend or
|
||||
* resume phase for devices whose "always on" flags are set.
|
||||
*/
|
||||
static void genpd_syscore_switch(struct device *dev, bool suspend)
|
||||
static void genpd_switch_state(struct device *dev, bool suspend)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
bool use_lock;
|
||||
|
||||
genpd = dev_to_genpd_safe(dev);
|
||||
if (!genpd)
|
||||
return;
|
||||
|
||||
use_lock = genpd_is_irq_safe(genpd);
|
||||
|
||||
if (use_lock)
|
||||
genpd_lock(genpd);
|
||||
|
||||
if (suspend) {
|
||||
genpd->suspended_count++;
|
||||
genpd_sync_power_off(genpd, false, 0);
|
||||
genpd_sync_power_off(genpd, use_lock, 0);
|
||||
} else {
|
||||
genpd_sync_power_on(genpd, false, 0);
|
||||
genpd_sync_power_on(genpd, use_lock, 0);
|
||||
genpd->suspended_count--;
|
||||
}
|
||||
|
||||
if (use_lock)
|
||||
genpd_unlock(genpd);
|
||||
}
|
||||
|
||||
void pm_genpd_syscore_poweroff(struct device *dev)
|
||||
/**
|
||||
* dev_pm_genpd_suspend - Synchronously try to suspend the genpd for @dev
|
||||
* @dev: The device that is attached to the genpd, that can be suspended.
|
||||
*
|
||||
* This routine should typically be called for a device that needs to be
|
||||
* suspended during the syscore suspend phase. It may also be called during
|
||||
* suspend-to-idle to suspend a corresponding CPU device that is attached to a
|
||||
* genpd.
|
||||
*/
|
||||
void dev_pm_genpd_suspend(struct device *dev)
|
||||
{
|
||||
genpd_syscore_switch(dev, true);
|
||||
genpd_switch_state(dev, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweroff);
|
||||
EXPORT_SYMBOL_GPL(dev_pm_genpd_suspend);
|
||||
|
||||
void pm_genpd_syscore_poweron(struct device *dev)
|
||||
/**
|
||||
* dev_pm_genpd_resume - Synchronously try to resume the genpd for @dev
|
||||
* @dev: The device that is attached to the genpd, which needs to be resumed.
|
||||
*
|
||||
* This routine should typically be called for a device that needs to be resumed
|
||||
* during the syscore resume phase. It may also be called during suspend-to-idle
|
||||
* to resume a corresponding CPU device that is attached to a genpd.
|
||||
*/
|
||||
void dev_pm_genpd_resume(struct device *dev)
|
||||
{
|
||||
genpd_syscore_switch(dev, false);
|
||||
genpd_switch_state(dev, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweron);
|
||||
EXPORT_SYMBOL_GPL(dev_pm_genpd_resume);
|
||||
|
||||
#else /* !CONFIG_PM_SLEEP */
|
||||
|
||||
|
@ -658,7 +658,7 @@ static void sh_cmt_clocksource_suspend(struct clocksource *cs)
|
||||
return;
|
||||
|
||||
sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
|
||||
pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev);
|
||||
dev_pm_genpd_suspend(&ch->cmt->pdev->dev);
|
||||
}
|
||||
|
||||
static void sh_cmt_clocksource_resume(struct clocksource *cs)
|
||||
@ -668,7 +668,7 @@ static void sh_cmt_clocksource_resume(struct clocksource *cs)
|
||||
if (!ch->cs_enabled)
|
||||
return;
|
||||
|
||||
pm_genpd_syscore_poweron(&ch->cmt->pdev->dev);
|
||||
dev_pm_genpd_resume(&ch->cmt->pdev->dev);
|
||||
sh_cmt_start(ch, FLAG_CLOCKSOURCE);
|
||||
}
|
||||
|
||||
@ -760,7 +760,7 @@ static void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
|
||||
{
|
||||
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
||||
|
||||
pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev);
|
||||
dev_pm_genpd_suspend(&ch->cmt->pdev->dev);
|
||||
clk_unprepare(ch->cmt->clk);
|
||||
}
|
||||
|
||||
@ -769,7 +769,7 @@ static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
|
||||
struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
|
||||
|
||||
clk_prepare(ch->cmt->clk);
|
||||
pm_genpd_syscore_poweron(&ch->cmt->pdev->dev);
|
||||
dev_pm_genpd_resume(&ch->cmt->pdev->dev);
|
||||
}
|
||||
|
||||
static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
|
||||
|
@ -297,12 +297,12 @@ static int sh_mtu2_clock_event_set_periodic(struct clock_event_device *ced)
|
||||
|
||||
static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced)
|
||||
{
|
||||
pm_genpd_syscore_poweroff(&ced_to_sh_mtu2(ced)->mtu->pdev->dev);
|
||||
dev_pm_genpd_suspend(&ced_to_sh_mtu2(ced)->mtu->pdev->dev);
|
||||
}
|
||||
|
||||
static void sh_mtu2_clock_event_resume(struct clock_event_device *ced)
|
||||
{
|
||||
pm_genpd_syscore_poweron(&ced_to_sh_mtu2(ced)->mtu->pdev->dev);
|
||||
dev_pm_genpd_resume(&ced_to_sh_mtu2(ced)->mtu->pdev->dev);
|
||||
}
|
||||
|
||||
static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
|
||||
|
@ -292,7 +292,7 @@ static void sh_tmu_clocksource_suspend(struct clocksource *cs)
|
||||
|
||||
if (--ch->enable_count == 0) {
|
||||
__sh_tmu_disable(ch);
|
||||
pm_genpd_syscore_poweroff(&ch->tmu->pdev->dev);
|
||||
dev_pm_genpd_suspend(&ch->tmu->pdev->dev);
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +304,7 @@ static void sh_tmu_clocksource_resume(struct clocksource *cs)
|
||||
return;
|
||||
|
||||
if (ch->enable_count++ == 0) {
|
||||
pm_genpd_syscore_poweron(&ch->tmu->pdev->dev);
|
||||
dev_pm_genpd_resume(&ch->tmu->pdev->dev);
|
||||
__sh_tmu_enable(ch);
|
||||
}
|
||||
}
|
||||
@ -394,12 +394,12 @@ static int sh_tmu_clock_event_next(unsigned long delta,
|
||||
|
||||
static void sh_tmu_clock_event_suspend(struct clock_event_device *ced)
|
||||
{
|
||||
pm_genpd_syscore_poweroff(&ced_to_sh_tmu(ced)->tmu->pdev->dev);
|
||||
dev_pm_genpd_suspend(&ced_to_sh_tmu(ced)->tmu->pdev->dev);
|
||||
}
|
||||
|
||||
static void sh_tmu_clock_event_resume(struct clock_event_device *ced)
|
||||
{
|
||||
pm_genpd_syscore_poweron(&ced_to_sh_tmu(ced)->tmu->pdev->dev);
|
||||
dev_pm_genpd_resume(&ced_to_sh_tmu(ced)->tmu->pdev->dev);
|
||||
}
|
||||
|
||||
static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
|
||||
|
@ -327,6 +327,8 @@ struct device *psci_dt_attach_cpu(int cpu)
|
||||
if (cpu_online(cpu))
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
dev_pm_syscore_device(dev, true);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/psci.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
@ -52,8 +53,9 @@ static inline int psci_enter_state(int idx, u32 state)
|
||||
return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter, idx, state);
|
||||
}
|
||||
|
||||
static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int idx)
|
||||
static int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int idx,
|
||||
bool s2idle)
|
||||
{
|
||||
struct psci_cpuidle_data *data = this_cpu_ptr(&psci_cpuidle_data);
|
||||
u32 *states = data->psci_states;
|
||||
@ -66,7 +68,12 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
|
||||
return -1;
|
||||
|
||||
/* Do runtime PM to manage a hierarchical CPU toplogy. */
|
||||
RCU_NONIDLE(pm_runtime_put_sync_suspend(pd_dev));
|
||||
rcu_irq_enter_irqson();
|
||||
if (s2idle)
|
||||
dev_pm_genpd_suspend(pd_dev);
|
||||
else
|
||||
pm_runtime_put_sync_suspend(pd_dev);
|
||||
rcu_irq_exit_irqson();
|
||||
|
||||
state = psci_get_domain_state();
|
||||
if (!state)
|
||||
@ -74,7 +81,12 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
|
||||
|
||||
ret = psci_cpu_suspend_enter(state) ? -1 : idx;
|
||||
|
||||
RCU_NONIDLE(pm_runtime_get_sync(pd_dev));
|
||||
rcu_irq_enter_irqson();
|
||||
if (s2idle)
|
||||
dev_pm_genpd_resume(pd_dev);
|
||||
else
|
||||
pm_runtime_get_sync(pd_dev);
|
||||
rcu_irq_exit_irqson();
|
||||
|
||||
cpu_pm_exit();
|
||||
|
||||
@ -83,6 +95,19 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv, int idx)
|
||||
{
|
||||
return __psci_enter_domain_idle_state(dev, drv, idx, false);
|
||||
}
|
||||
|
||||
static int psci_enter_s2idle_domain_idle_state(struct cpuidle_device *dev,
|
||||
struct cpuidle_driver *drv,
|
||||
int idx)
|
||||
{
|
||||
return __psci_enter_domain_idle_state(dev, drv, idx, true);
|
||||
}
|
||||
|
||||
static int psci_idle_cpuhp_up(unsigned int cpu)
|
||||
{
|
||||
struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev);
|
||||
@ -170,6 +195,7 @@ static int psci_dt_cpu_init_topology(struct cpuidle_driver *drv,
|
||||
* deeper states.
|
||||
*/
|
||||
drv->states[state_count - 1].enter = psci_enter_domain_idle_state;
|
||||
drv->states[state_count - 1].enter_s2idle = psci_enter_s2idle_domain_idle_state;
|
||||
psci_cpuidle_use_cpuhp = true;
|
||||
|
||||
return 0;
|
||||
|
@ -280,11 +280,11 @@ static inline int dev_pm_genpd_remove_notifier(struct device *dev)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP
|
||||
void pm_genpd_syscore_poweroff(struct device *dev);
|
||||
void pm_genpd_syscore_poweron(struct device *dev);
|
||||
void dev_pm_genpd_suspend(struct device *dev);
|
||||
void dev_pm_genpd_resume(struct device *dev);
|
||||
#else
|
||||
static inline void pm_genpd_syscore_poweroff(struct device *dev) {}
|
||||
static inline void pm_genpd_syscore_poweron(struct device *dev) {}
|
||||
static inline void dev_pm_genpd_suspend(struct device *dev) {}
|
||||
static inline void dev_pm_genpd_resume(struct device *dev) {}
|
||||
#endif
|
||||
|
||||
/* OF PM domain providers */
|
||||
|
Loading…
Reference in New Issue
Block a user