Skip to content

Commit 2d5c80b

Browse files
committed
Merge branch 'pm-cpuidle'
* 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
2 parents 5b56420 + 0a39894 commit 2d5c80b

File tree

9 files changed

+210
-111
lines changed

9 files changed

+210
-111
lines changed

drivers/acpi/processor_idle.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -655,25 +655,27 @@ static int acpi_idle_enter(struct cpuidle_device *dev,
655655
return index;
656656
}
657657

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

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

666666
if (unlikely(!pr))
667-
return;
667+
return 0;
668668

669669
if (pr->flags.bm_check) {
670670
acpi_idle_enter_bm(pr, cx, false);
671-
return;
671+
return 0;
672672
} else {
673673
ACPI_FLUSH_CPU_CACHE();
674674
}
675675
}
676676
acpi_idle_do_entry(cx);
677+
678+
return 0;
677679
}
678680

679681
static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,

drivers/cpuidle/Kconfig.arm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ config ARM_PSCI_CPUIDLE
2323
It provides an idle driver that is capable of detecting and
2424
managing idle states through the PSCI firmware interface.
2525

26+
config ARM_PSCI_CPUIDLE_DOMAIN
27+
bool "PSCI CPU idle Domain"
28+
depends on ARM_PSCI_CPUIDLE
29+
depends on PM_GENERIC_DOMAINS_OF
30+
default y
31+
help
32+
Select this to enable the PSCI based CPUidle driver to use PM domains,
33+
which is needed to support the hierarchical DT based layout of the
34+
idle states.
35+
2636
config ARM_BIG_LITTLE_CPUIDLE
2737
bool "Support for ARM big.LITTLE processors"
2838
depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS || COMPILE_TEST

drivers/cpuidle/Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o
2121
obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o
2222
obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o
2323
obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o
24-
obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle_psci.o
25-
cpuidle_psci-y := cpuidle-psci.o
26-
cpuidle_psci-$(CONFIG_PM_GENERIC_DOMAINS_OF) += cpuidle-psci-domain.o
24+
obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle-psci.o
25+
obj-$(CONFIG_ARM_PSCI_CPUIDLE_DOMAIN) += cpuidle-psci-domain.o
2726
obj-$(CONFIG_ARM_TEGRA_CPUIDLE) += cpuidle-tegra.o
2827
obj-$(CONFIG_ARM_QCOM_SPM_CPUIDLE) += cpuidle-qcom-spm.o
2928

drivers/cpuidle/cpuidle-psci-domain.c

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/cpu.h>
1313
#include <linux/device.h>
1414
#include <linux/kernel.h>
15+
#include <linux/platform_device.h>
1516
#include <linux/pm_domain.h>
1617
#include <linux/pm_runtime.h>
1718
#include <linux/psci.h>
@@ -26,7 +27,7 @@ struct psci_pd_provider {
2627
};
2728

2829
static LIST_HEAD(psci_pd_providers);
29-
static bool osi_mode_enabled __initdata;
30+
static bool psci_pd_allow_domain_state;
3031

3132
static int psci_pd_power_off(struct generic_pm_domain *pd)
3233
{
@@ -36,15 +37,18 @@ static int psci_pd_power_off(struct generic_pm_domain *pd)
3637
if (!state->data)
3738
return 0;
3839

40+
if (!psci_pd_allow_domain_state)
41+
return -EBUSY;
42+
3943
/* OSI mode is enabled, set the corresponding domain state. */
4044
pd_state = state->data;
4145
psci_set_domain_state(*pd_state);
4246

4347
return 0;
4448
}
4549

46-
static int __init psci_pd_parse_state_nodes(struct genpd_power_state *states,
47-
int state_count)
50+
static int psci_pd_parse_state_nodes(struct genpd_power_state *states,
51+
int state_count)
4852
{
4953
int i, ret;
5054
u32 psci_state, *psci_state_buf;
@@ -73,7 +77,7 @@ static int __init psci_pd_parse_state_nodes(struct genpd_power_state *states,
7377
return ret;
7478
}
7579

76-
static int __init psci_pd_parse_states(struct device_node *np,
80+
static int psci_pd_parse_states(struct device_node *np,
7781
struct genpd_power_state **states, int *state_count)
7882
{
7983
int ret;
@@ -101,7 +105,7 @@ static void psci_pd_free_states(struct genpd_power_state *states,
101105
kfree(states);
102106
}
103107

104-
static int __init psci_pd_init(struct device_node *np)
108+
static int psci_pd_init(struct device_node *np)
105109
{
106110
struct generic_pm_domain *pd;
107111
struct psci_pd_provider *pd_provider;
@@ -168,7 +172,7 @@ static int __init psci_pd_init(struct device_node *np)
168172
return ret;
169173
}
170174

171-
static void __init psci_pd_remove(void)
175+
static void psci_pd_remove(void)
172176
{
173177
struct psci_pd_provider *pd_provider, *it;
174178
struct generic_pm_domain *genpd;
@@ -186,7 +190,7 @@ static void __init psci_pd_remove(void)
186190
}
187191
}
188192

189-
static int __init psci_pd_init_topology(struct device_node *np, bool add)
193+
static int psci_pd_init_topology(struct device_node *np, bool add)
190194
{
191195
struct device_node *node;
192196
struct of_phandle_args child, parent;
@@ -212,24 +216,33 @@ static int __init psci_pd_init_topology(struct device_node *np, bool add)
212216
return 0;
213217
}
214218

215-
static int __init psci_pd_add_topology(struct device_node *np)
219+
static int psci_pd_add_topology(struct device_node *np)
216220
{
217221
return psci_pd_init_topology(np, true);
218222
}
219223

220-
static void __init psci_pd_remove_topology(struct device_node *np)
224+
static void psci_pd_remove_topology(struct device_node *np)
221225
{
222226
psci_pd_init_topology(np, false);
223227
}
224228

225-
static const struct of_device_id psci_of_match[] __initconst = {
229+
static void psci_cpuidle_domain_sync_state(struct device *dev)
230+
{
231+
/*
232+
* All devices have now been attached/probed to the PM domain topology,
233+
* hence it's fine to allow domain states to be picked.
234+
*/
235+
psci_pd_allow_domain_state = true;
236+
}
237+
238+
static const struct of_device_id psci_of_match[] = {
226239
{ .compatible = "arm,psci-1.0" },
227240
{}
228241
};
229242

230-
static int __init psci_idle_init_domains(void)
243+
static int psci_cpuidle_domain_probe(struct platform_device *pdev)
231244
{
232-
struct device_node *np = of_find_matching_node(NULL, psci_of_match);
245+
struct device_node *np = pdev->dev.of_node;
233246
struct device_node *node;
234247
int ret = 0, pd_count = 0;
235248

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

239252
/* Currently limit the hierarchical topology to be used in OSI mode. */
240253
if (!psci_has_osi_support())
241-
goto out;
254+
return 0;
242255

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

258271
/* Bail out if not using the hierarchical CPU topology. */
259272
if (!pd_count)
260-
goto out;
273+
return 0;
261274

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

275-
osi_mode_enabled = true;
276-
of_node_put(np);
277288
pr_info("Initialized CPU PM domain topology\n");
278-
return pd_count;
289+
return 0;
279290

280291
put_node:
281292
of_node_put(node);
282293
remove_pd:
283294
if (pd_count)
284295
psci_pd_remove();
285296
pr_err("failed to create CPU PM domains ret=%d\n", ret);
286-
out:
287-
of_node_put(np);
288297
return ret;
289298
}
299+
300+
static struct platform_driver psci_cpuidle_domain_driver = {
301+
.probe = psci_cpuidle_domain_probe,
302+
.driver = {
303+
.name = "psci-cpuidle-domain",
304+
.of_match_table = psci_of_match,
305+
.sync_state = psci_cpuidle_domain_sync_state,
306+
},
307+
};
308+
309+
static int __init psci_idle_init_domains(void)
310+
{
311+
return platform_driver_register(&psci_cpuidle_domain_driver);
312+
}
290313
subsys_initcall(psci_idle_init_domains);
291314

292-
struct device __init *psci_dt_attach_cpu(int cpu)
315+
struct device *psci_dt_attach_cpu(int cpu)
293316
{
294317
struct device *dev;
295318

296-
if (!osi_mode_enabled)
297-
return NULL;
298-
299319
dev = dev_pm_domain_attach_by_name(get_cpu_device(cpu), "psci");
300320
if (IS_ERR_OR_NULL(dev))
301321
return dev;
@@ -306,3 +326,11 @@ struct device __init *psci_dt_attach_cpu(int cpu)
306326

307327
return dev;
308328
}
329+
330+
void psci_dt_detach_cpu(struct device *dev)
331+
{
332+
if (IS_ERR_OR_NULL(dev))
333+
return;
334+
335+
dev_pm_domain_detach(dev, false);
336+
}

0 commit comments

Comments
 (0)