Skip to content

Commit

Permalink
Merge branch 'pm-cpuidle'
Browse files Browse the repository at this point in the history
* pm-cpuidle:
  cpuidle: ACPI: fix 'return' with no value build warning
  intel_idle: Customize IceLake server support
  cpuidle: change enter_s2idle() prototype
  cpuidle: psci: Prevent domain idlestates until consumers are ready
  cpuidle: psci: Convert PM domain to platform driver
  cpuidle: psci: Fix error path via converting to a platform driver
  cpuidle: psci: Fail cpuidle registration if set OSI mode failed
  cpuidle: psci: Split into two separate build objects
  intel_idle: Eliminate redundant static variable
  • Loading branch information
Rafael J. Wysocki committed Aug 3, 2020
2 parents 5b56420 + 0a39894 commit 2d5c80b
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 111 deletions.
10 changes: 6 additions & 4 deletions drivers/acpi/processor_idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -655,25 +655,27 @@ static int acpi_idle_enter(struct cpuidle_device *dev,
return index;
}

static void acpi_idle_enter_s2idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
static int acpi_idle_enter_s2idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);

if (cx->type == ACPI_STATE_C3) {
struct acpi_processor *pr = __this_cpu_read(processors);

if (unlikely(!pr))
return;
return 0;

if (pr->flags.bm_check) {
acpi_idle_enter_bm(pr, cx, false);
return;
return 0;
} else {
ACPI_FLUSH_CPU_CACHE();
}
}
acpi_idle_do_entry(cx);

return 0;
}

static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
Expand Down
10 changes: 10 additions & 0 deletions drivers/cpuidle/Kconfig.arm
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ config ARM_PSCI_CPUIDLE
It provides an idle driver that is capable of detecting and
managing idle states through the PSCI firmware interface.

config ARM_PSCI_CPUIDLE_DOMAIN
bool "PSCI CPU idle Domain"
depends on ARM_PSCI_CPUIDLE
depends on PM_GENERIC_DOMAINS_OF
default y
help
Select this to enable the PSCI based CPUidle driver to use PM domains,
which is needed to support the hierarchical DT based layout of the
idle states.

config ARM_BIG_LITTLE_CPUIDLE
bool "Support for ARM big.LITTLE processors"
depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS || COMPILE_TEST
Expand Down
5 changes: 2 additions & 3 deletions drivers/cpuidle/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o
obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o
obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o
obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o
obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle_psci.o
cpuidle_psci-y := cpuidle-psci.o
cpuidle_psci-$(CONFIG_PM_GENERIC_DOMAINS_OF) += cpuidle-psci-domain.o
obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle-psci.o
obj-$(CONFIG_ARM_PSCI_CPUIDLE_DOMAIN) += cpuidle-psci-domain.o
obj-$(CONFIG_ARM_TEGRA_CPUIDLE) += cpuidle-tegra.o
obj-$(CONFIG_ARM_QCOM_SPM_CPUIDLE) += cpuidle-qcom-spm.o

Expand Down
74 changes: 51 additions & 23 deletions drivers/cpuidle/cpuidle-psci-domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/cpu.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/psci.h>
Expand All @@ -26,7 +27,7 @@ struct psci_pd_provider {
};

static LIST_HEAD(psci_pd_providers);
static bool osi_mode_enabled __initdata;
static bool psci_pd_allow_domain_state;

static int psci_pd_power_off(struct generic_pm_domain *pd)
{
Expand All @@ -36,15 +37,18 @@ static int psci_pd_power_off(struct generic_pm_domain *pd)
if (!state->data)
return 0;

if (!psci_pd_allow_domain_state)
return -EBUSY;

/* OSI mode is enabled, set the corresponding domain state. */
pd_state = state->data;
psci_set_domain_state(*pd_state);

return 0;
}

static int __init psci_pd_parse_state_nodes(struct genpd_power_state *states,
int state_count)
static int psci_pd_parse_state_nodes(struct genpd_power_state *states,
int state_count)
{
int i, ret;
u32 psci_state, *psci_state_buf;
Expand Down Expand Up @@ -73,7 +77,7 @@ static int __init psci_pd_parse_state_nodes(struct genpd_power_state *states,
return ret;
}

static int __init psci_pd_parse_states(struct device_node *np,
static int psci_pd_parse_states(struct device_node *np,
struct genpd_power_state **states, int *state_count)
{
int ret;
Expand Down Expand Up @@ -101,7 +105,7 @@ static void psci_pd_free_states(struct genpd_power_state *states,
kfree(states);
}

static int __init psci_pd_init(struct device_node *np)
static int psci_pd_init(struct device_node *np)
{
struct generic_pm_domain *pd;
struct psci_pd_provider *pd_provider;
Expand Down Expand Up @@ -168,7 +172,7 @@ static int __init psci_pd_init(struct device_node *np)
return ret;
}

static void __init psci_pd_remove(void)
static void psci_pd_remove(void)
{
struct psci_pd_provider *pd_provider, *it;
struct generic_pm_domain *genpd;
Expand All @@ -186,7 +190,7 @@ static void __init psci_pd_remove(void)
}
}

static int __init psci_pd_init_topology(struct device_node *np, bool add)
static int psci_pd_init_topology(struct device_node *np, bool add)
{
struct device_node *node;
struct of_phandle_args child, parent;
Expand All @@ -212,24 +216,33 @@ static int __init psci_pd_init_topology(struct device_node *np, bool add)
return 0;
}

static int __init psci_pd_add_topology(struct device_node *np)
static int psci_pd_add_topology(struct device_node *np)
{
return psci_pd_init_topology(np, true);
}

static void __init psci_pd_remove_topology(struct device_node *np)
static void psci_pd_remove_topology(struct device_node *np)
{
psci_pd_init_topology(np, false);
}

static const struct of_device_id psci_of_match[] __initconst = {
static void psci_cpuidle_domain_sync_state(struct device *dev)
{
/*
* All devices have now been attached/probed to the PM domain topology,
* hence it's fine to allow domain states to be picked.
*/
psci_pd_allow_domain_state = true;
}

static const struct of_device_id psci_of_match[] = {
{ .compatible = "arm,psci-1.0" },
{}
};

static int __init psci_idle_init_domains(void)
static int psci_cpuidle_domain_probe(struct platform_device *pdev)
{
struct device_node *np = of_find_matching_node(NULL, psci_of_match);
struct device_node *np = pdev->dev.of_node;
struct device_node *node;
int ret = 0, pd_count = 0;

Expand All @@ -238,7 +251,7 @@ static int __init psci_idle_init_domains(void)

/* Currently limit the hierarchical topology to be used in OSI mode. */
if (!psci_has_osi_support())
goto out;
return 0;

/*
* Parse child nodes for the "#power-domain-cells" property and
Expand All @@ -257,7 +270,7 @@ static int __init psci_idle_init_domains(void)

/* Bail out if not using the hierarchical CPU topology. */
if (!pd_count)
goto out;
return 0;

/* Link genpd masters/subdomains to model the CPU topology. */
ret = psci_pd_add_topology(np);
Expand All @@ -272,30 +285,37 @@ static int __init psci_idle_init_domains(void)
goto remove_pd;
}

osi_mode_enabled = true;
of_node_put(np);
pr_info("Initialized CPU PM domain topology\n");
return pd_count;
return 0;

put_node:
of_node_put(node);
remove_pd:
if (pd_count)
psci_pd_remove();
pr_err("failed to create CPU PM domains ret=%d\n", ret);
out:
of_node_put(np);
return ret;
}

static struct platform_driver psci_cpuidle_domain_driver = {
.probe = psci_cpuidle_domain_probe,
.driver = {
.name = "psci-cpuidle-domain",
.of_match_table = psci_of_match,
.sync_state = psci_cpuidle_domain_sync_state,
},
};

static int __init psci_idle_init_domains(void)
{
return platform_driver_register(&psci_cpuidle_domain_driver);
}
subsys_initcall(psci_idle_init_domains);

struct device __init *psci_dt_attach_cpu(int cpu)
struct device *psci_dt_attach_cpu(int cpu)
{
struct device *dev;

if (!osi_mode_enabled)
return NULL;

dev = dev_pm_domain_attach_by_name(get_cpu_device(cpu), "psci");
if (IS_ERR_OR_NULL(dev))
return dev;
Expand All @@ -306,3 +326,11 @@ struct device __init *psci_dt_attach_cpu(int cpu)

return dev;
}

void psci_dt_detach_cpu(struct device *dev)
{
if (IS_ERR_OR_NULL(dev))
return;

dev_pm_domain_detach(dev, false);
}
Loading

0 comments on commit 2d5c80b

Please sign in to comment.