Skip to content

Commit 41f762a

Browse files
committed
Merge tag 'pm-5.10-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more power management updates from Rafael Wysocki: "First of all, the adaptive voltage scaling (AVS) drivers go to new platform-specific locations as planned (this part was reported to have merge conflicts against the new arm-soc updates in linux-next). In addition to that, there are some fixes (intel_idle, intel_pstate, RAPL, acpi_cpufreq), the addition of on/off notifiers and idle state accounting support to the generic power domains (genpd) code and some janitorial changes all over. Specifics: - Move the AVS drivers to new platform-specific locations and get rid of the drivers/power/avs directory (Ulf Hansson). - Add on/off notifiers and idle state accounting support to the generic power domains (genpd) framework (Ulf Hansson, Lina Iyer). - Ulf will maintain the PM domain part of cpuidle-psci (Ulf Hansson). - Make intel_idle disregard ACPI _CST if it cannot use the data returned by that method (Mel Gorman). - Modify intel_pstate to avoid leaving useless sysfs directory structure behind if it cannot be registered (Chen Yu). - Fix domain detection in the RAPL power capping driver and prevent it from failing to enumerate the Psys RAPL domain (Zhang Rui). - Allow acpi-cpufreq to use ACPI _PSD information with Family 19 and later AMD chips (Wei Huang). - Update the driver assumptions comment in intel_idle and fix a kerneldoc comment in the runtime PM framework (Alexander Monakov, Bean Huo). - Avoid unnecessary resets of the cached frequency in the schedutil cpufreq governor to reduce overhead (Wei Wang). - Clean up the cpufreq core a bit (Viresh Kumar). - Make assorted minor janitorial changes (Daniel Lezcano, Geert Uytterhoeven, Hubert Jasudowicz, Tom Rix). - Clean up and optimize the cpupower utility somewhat (Colin Ian King, Martin Kaistra)" * tag 'pm-5.10-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (23 commits) PM: sleep: remove unreachable break PM: AVS: Drop the avs directory and the corresponding Kconfig PM: AVS: qcom-cpr: Move the driver to the qcom specific drivers PM: runtime: Fix typo in pm_runtime_set_active() helper comment PM: domains: Fix build error for genpd notifiers powercap: Fix typo in Kconfig "Plance" -> "Plane" cpufreq: schedutil: restore cached freq when next_f is not changed acpi-cpufreq: Honor _PSD table setting on new AMD CPUs PM: AVS: smartreflex Move driver to soc specific drivers PM: AVS: rockchip-io: Move the driver to the rockchip specific drivers PM: domains: enable domain idle state accounting PM: domains: Add curly braces to delimit comment + statement block PM: domains: Add support for PM domain on/off notifiers for genpd powercap/intel_rapl: enumerate Psys RAPL domain together with package RAPL domain powercap/intel_rapl: Fix domain detection intel_idle: Ignore _CST if control cannot be taken from the platform cpuidle: Remove pointless stub intel_idle: mention assumption that WBINVD is not needed MAINTAINERS: Add section for cpuidle-psci PM domain cpufreq: intel_pstate: Delete intel_pstate sysfs if failed to register the driver ...
2 parents af99538 + 41c169d commit 41f762a

30 files changed

Lines changed: 281 additions & 164 deletions

File tree

MAINTAINERS

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4585,6 +4585,14 @@ L: linux-arm-kernel@lists.infradead.org
45854585
S: Supported
45864586
F: drivers/cpuidle/cpuidle-psci.c
45874587

4588+
CPUIDLE DRIVER - ARM PSCI PM DOMAIN
4589+
M: Ulf Hansson <ulf.hansson@linaro.org>
4590+
L: linux-pm@vger.kernel.org
4591+
L: linux-arm-kernel@lists.infradead.org
4592+
S: Supported
4593+
F: drivers/cpuidle/cpuidle-psci.h
4594+
F: drivers/cpuidle/cpuidle-psci-domain.c
4595+
45884596
CRAMFS FILESYSTEM
45894597
M: Nicolas Pitre <nico@fluxnic.net>
45904598
S: Maintained
@@ -5398,11 +5406,11 @@ F: include/linux/debugfs.h
53985406
F: include/linux/kobj*
53995407
F: lib/kobj*
54005408

5401-
DRIVERS FOR ADAPTIVE VOLTAGE SCALING (AVS)
5409+
DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
54025410
M: Nishanth Menon <nm@ti.com>
54035411
L: linux-pm@vger.kernel.org
54045412
S: Maintained
5405-
F: drivers/power/avs/
5413+
F: drivers/soc/ti/smartreflex.c
54065414
F: include/linux/power/smartreflex.h
54075415

54085416
DRM DRIVER FOR ALLWINNER DE2 AND DE3 ENGINE
@@ -14459,7 +14467,7 @@ L: linux-pm@vger.kernel.org
1445914467
L: linux-arm-msm@vger.kernel.org
1446014468
S: Maintained
1446114469
F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
14462-
F: drivers/power/avs/qcom-cpr.c
14470+
F: drivers/soc/qcom/cpr.c
1446314471

1446414472
QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
1446514473
M: Ilia Lin <ilia.lin@kernel.org>

arch/arm/plat-omap/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ config OMAP_DEBUG_LEDS
2323

2424
config POWER_AVS_OMAP
2525
bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2"
26-
depends on POWER_AVS && (ARCH_OMAP3 || ARCH_OMAP4) && PM
26+
depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
2727
select POWER_SUPPLY
2828
help
2929
Say Y to enable AVS(Adaptive Voltage Scaling)

drivers/base/power/domain.c

Lines changed: 153 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -415,26 +415,45 @@ static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
415415
s64 elapsed_ns;
416416
int ret;
417417

418+
/* Notify consumers that we are about to power on. */
419+
ret = raw_notifier_call_chain_robust(&genpd->power_notifiers,
420+
GENPD_NOTIFY_PRE_ON,
421+
GENPD_NOTIFY_OFF, NULL);
422+
ret = notifier_to_errno(ret);
423+
if (ret)
424+
return ret;
425+
418426
if (!genpd->power_on)
419-
return 0;
427+
goto out;
420428

421-
if (!timed)
422-
return genpd->power_on(genpd);
429+
if (!timed) {
430+
ret = genpd->power_on(genpd);
431+
if (ret)
432+
goto err;
433+
434+
goto out;
435+
}
423436

424437
time_start = ktime_get();
425438
ret = genpd->power_on(genpd);
426439
if (ret)
427-
return ret;
440+
goto err;
428441

429442
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
430443
if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns)
431-
return ret;
444+
goto out;
432445

433446
genpd->states[state_idx].power_on_latency_ns = elapsed_ns;
434447
genpd->max_off_time_changed = true;
435448
pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
436449
genpd->name, "on", elapsed_ns);
437450

451+
out:
452+
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
453+
return 0;
454+
err:
455+
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
456+
NULL);
438457
return ret;
439458
}
440459

@@ -445,27 +464,46 @@ static int _genpd_power_off(struct generic_pm_domain *genpd, bool timed)
445464
s64 elapsed_ns;
446465
int ret;
447466

467+
/* Notify consumers that we are about to power off. */
468+
ret = raw_notifier_call_chain_robust(&genpd->power_notifiers,
469+
GENPD_NOTIFY_PRE_OFF,
470+
GENPD_NOTIFY_ON, NULL);
471+
ret = notifier_to_errno(ret);
472+
if (ret)
473+
return ret;
474+
448475
if (!genpd->power_off)
449-
return 0;
476+
goto out;
477+
478+
if (!timed) {
479+
ret = genpd->power_off(genpd);
480+
if (ret)
481+
goto busy;
450482

451-
if (!timed)
452-
return genpd->power_off(genpd);
483+
goto out;
484+
}
453485

454486
time_start = ktime_get();
455487
ret = genpd->power_off(genpd);
456488
if (ret)
457-
return ret;
489+
goto busy;
458490

459491
elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
460492
if (elapsed_ns <= genpd->states[state_idx].power_off_latency_ns)
461-
return 0;
493+
goto out;
462494

463495
genpd->states[state_idx].power_off_latency_ns = elapsed_ns;
464496
genpd->max_off_time_changed = true;
465497
pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
466498
genpd->name, "off", elapsed_ns);
467499

500+
out:
501+
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
502+
NULL);
468503
return 0;
504+
busy:
505+
raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
506+
return ret;
469507
}
470508

471509
/**
@@ -550,11 +588,14 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
550588
return -EBUSY;
551589

552590
ret = _genpd_power_off(genpd, true);
553-
if (ret)
591+
if (ret) {
592+
genpd->states[genpd->state_idx].rejected++;
554593
return ret;
594+
}
555595

556596
genpd->status = GENPD_STATE_OFF;
557597
genpd_update_accounting(genpd);
598+
genpd->states[genpd->state_idx].usage++;
558599

559600
list_for_each_entry(link, &genpd->child_links, child_node) {
560601
genpd_sd_counter_dec(link->parent);
@@ -1270,13 +1311,14 @@ static int genpd_restore_noirq(struct device *dev)
12701311
* first time for the given domain in the present cycle.
12711312
*/
12721313
genpd_lock(genpd);
1273-
if (genpd->suspended_count++ == 0)
1314+
if (genpd->suspended_count++ == 0) {
12741315
/*
12751316
* The boot kernel might put the domain into arbitrary state,
12761317
* so make it appear as powered off to genpd_sync_power_on(),
12771318
* so that it tries to power it on in case it was really off.
12781319
*/
12791320
genpd->status = GENPD_STATE_OFF;
1321+
}
12801322

12811323
genpd_sync_power_on(genpd, true, 0);
12821324
genpd_unlock(genpd);
@@ -1592,6 +1634,101 @@ int pm_genpd_remove_device(struct device *dev)
15921634
}
15931635
EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
15941636

1637+
/**
1638+
* dev_pm_genpd_add_notifier - Add a genpd power on/off notifier for @dev
1639+
*
1640+
* @dev: Device that should be associated with the notifier
1641+
* @nb: The notifier block to register
1642+
*
1643+
* Users may call this function to add a genpd power on/off notifier for an
1644+
* attached @dev. Only one notifier per device is allowed. The notifier is
1645+
* sent when genpd is powering on/off the PM domain.
1646+
*
1647+
* It is assumed that the user guarantee that the genpd wouldn't be detached
1648+
* while this routine is getting called.
1649+
*
1650+
* Returns 0 on success and negative error values on failures.
1651+
*/
1652+
int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb)
1653+
{
1654+
struct generic_pm_domain *genpd;
1655+
struct generic_pm_domain_data *gpd_data;
1656+
int ret;
1657+
1658+
genpd = dev_to_genpd_safe(dev);
1659+
if (!genpd)
1660+
return -ENODEV;
1661+
1662+
if (WARN_ON(!dev->power.subsys_data ||
1663+
!dev->power.subsys_data->domain_data))
1664+
return -EINVAL;
1665+
1666+
gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
1667+
if (gpd_data->power_nb)
1668+
return -EEXIST;
1669+
1670+
genpd_lock(genpd);
1671+
ret = raw_notifier_chain_register(&genpd->power_notifiers, nb);
1672+
genpd_unlock(genpd);
1673+
1674+
if (ret) {
1675+
dev_warn(dev, "failed to add notifier for PM domain %s\n",
1676+
genpd->name);
1677+
return ret;
1678+
}
1679+
1680+
gpd_data->power_nb = nb;
1681+
return 0;
1682+
}
1683+
EXPORT_SYMBOL_GPL(dev_pm_genpd_add_notifier);
1684+
1685+
/**
1686+
* dev_pm_genpd_remove_notifier - Remove a genpd power on/off notifier for @dev
1687+
*
1688+
* @dev: Device that is associated with the notifier
1689+
*
1690+
* Users may call this function to remove a genpd power on/off notifier for an
1691+
* attached @dev.
1692+
*
1693+
* It is assumed that the user guarantee that the genpd wouldn't be detached
1694+
* while this routine is getting called.
1695+
*
1696+
* Returns 0 on success and negative error values on failures.
1697+
*/
1698+
int dev_pm_genpd_remove_notifier(struct device *dev)
1699+
{
1700+
struct generic_pm_domain *genpd;
1701+
struct generic_pm_domain_data *gpd_data;
1702+
int ret;
1703+
1704+
genpd = dev_to_genpd_safe(dev);
1705+
if (!genpd)
1706+
return -ENODEV;
1707+
1708+
if (WARN_ON(!dev->power.subsys_data ||
1709+
!dev->power.subsys_data->domain_data))
1710+
return -EINVAL;
1711+
1712+
gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
1713+
if (!gpd_data->power_nb)
1714+
return -ENODEV;
1715+
1716+
genpd_lock(genpd);
1717+
ret = raw_notifier_chain_unregister(&genpd->power_notifiers,
1718+
gpd_data->power_nb);
1719+
genpd_unlock(genpd);
1720+
1721+
if (ret) {
1722+
dev_warn(dev, "failed to remove notifier for PM domain %s\n",
1723+
genpd->name);
1724+
return ret;
1725+
}
1726+
1727+
gpd_data->power_nb = NULL;
1728+
return 0;
1729+
}
1730+
EXPORT_SYMBOL_GPL(dev_pm_genpd_remove_notifier);
1731+
15951732
static int genpd_add_subdomain(struct generic_pm_domain *genpd,
15961733
struct generic_pm_domain *subdomain)
15971734
{
@@ -1762,6 +1899,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
17621899
INIT_LIST_HEAD(&genpd->parent_links);
17631900
INIT_LIST_HEAD(&genpd->child_links);
17641901
INIT_LIST_HEAD(&genpd->dev_list);
1902+
RAW_INIT_NOTIFIER_HEAD(&genpd->power_notifiers);
17651903
genpd_lock_init(genpd);
17661904
genpd->gov = gov;
17671905
INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
@@ -2923,7 +3061,7 @@ static int idle_states_show(struct seq_file *s, void *data)
29233061
if (ret)
29243062
return -ERESTARTSYS;
29253063

2926-
seq_puts(s, "State Time Spent(ms)\n");
3064+
seq_puts(s, "State Time Spent(ms) Usage Rejected\n");
29273065

29283066
for (i = 0; i < genpd->state_count; i++) {
29293067
ktime_t delta = 0;
@@ -2935,7 +3073,8 @@ static int idle_states_show(struct seq_file *s, void *data)
29353073

29363074
msecs = ktime_to_ms(
29373075
ktime_add(genpd->states[i].idle_time, delta));
2938-
seq_printf(s, "S%-13i %lld\n", i, msecs);
3076+
seq_printf(s, "S%-13i %-14lld %-14llu %llu\n", i, msecs,
3077+
genpd->states[i].usage, genpd->states[i].rejected);
29393078
}
29403079

29413080
genpd_unlock(genpd);

drivers/base/power/main.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,6 @@ static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
363363
case PM_EVENT_THAW:
364364
case PM_EVENT_RECOVER:
365365
return ops->thaw;
366-
break;
367366
case PM_EVENT_RESTORE:
368367
return ops->restore;
369368
#endif /* CONFIG_HIBERNATE_CALLBACKS */

drivers/cpufreq/acpi-cpufreq.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,8 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
691691
cpumask_copy(policy->cpus, topology_core_cpumask(cpu));
692692
}
693693

694-
if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
694+
if (check_amd_hwpstate_cpu(cpu) && boot_cpu_data.x86 < 0x19 &&
695+
!acpi_pstate_strict) {
695696
cpumask_clear(policy->cpus);
696697
cpumask_set_cpu(cpu, policy->cpus);
697698
cpumask_copy(data->freqdomain_cpus,

drivers/cpufreq/cpufreq.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,23 +1454,22 @@ static int cpufreq_online(unsigned int cpu)
14541454
*/
14551455
if ((cpufreq_driver->flags & CPUFREQ_NEED_INITIAL_FREQ_CHECK)
14561456
&& has_target()) {
1457+
unsigned int old_freq = policy->cur;
1458+
14571459
/* Are we running at unknown frequency ? */
1458-
ret = cpufreq_frequency_table_get_index(policy, policy->cur);
1460+
ret = cpufreq_frequency_table_get_index(policy, old_freq);
14591461
if (ret == -EINVAL) {
1460-
/* Warn user and fix it */
1461-
pr_warn("%s: CPU%d: Running at unlisted freq: %u KHz\n",
1462-
__func__, policy->cpu, policy->cur);
1463-
ret = __cpufreq_driver_target(policy, policy->cur - 1,
1464-
CPUFREQ_RELATION_L);
1462+
ret = __cpufreq_driver_target(policy, old_freq - 1,
1463+
CPUFREQ_RELATION_L);
14651464

14661465
/*
14671466
* Reaching here after boot in a few seconds may not
14681467
* mean that system will remain stable at "unknown"
14691468
* frequency for longer duration. Hence, a BUG_ON().
14701469
*/
14711470
BUG_ON(ret);
1472-
pr_warn("%s: CPU%d: Unlisted initial frequency changed to: %u KHz\n",
1473-
__func__, policy->cpu, policy->cur);
1471+
pr_info("%s: CPU%d: Running at unlisted initial frequency: %u KHz, changing to: %u KHz\n",
1472+
__func__, policy->cpu, old_freq, policy->cur);
14741473
}
14751474
}
14761475

drivers/cpufreq/intel_pstate.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,24 @@ static void __init intel_pstate_sysfs_expose_params(void)
14201420
}
14211421
}
14221422

1423+
static void __init intel_pstate_sysfs_remove(void)
1424+
{
1425+
if (!intel_pstate_kobject)
1426+
return;
1427+
1428+
sysfs_remove_group(intel_pstate_kobject, &intel_pstate_attr_group);
1429+
1430+
if (!per_cpu_limits) {
1431+
sysfs_remove_file(intel_pstate_kobject, &max_perf_pct.attr);
1432+
sysfs_remove_file(intel_pstate_kobject, &min_perf_pct.attr);
1433+
1434+
if (x86_match_cpu(intel_pstate_cpu_ee_disable_ids))
1435+
sysfs_remove_file(intel_pstate_kobject, &energy_efficiency.attr);
1436+
}
1437+
1438+
kobject_put(intel_pstate_kobject);
1439+
}
1440+
14231441
static void intel_pstate_sysfs_expose_hwp_dynamic_boost(void)
14241442
{
14251443
int rc;
@@ -3063,8 +3081,10 @@ static int __init intel_pstate_init(void)
30633081
mutex_lock(&intel_pstate_driver_lock);
30643082
rc = intel_pstate_register_driver(default_driver);
30653083
mutex_unlock(&intel_pstate_driver_lock);
3066-
if (rc)
3084+
if (rc) {
3085+
intel_pstate_sysfs_remove();
30673086
return rc;
3087+
}
30683088

30693089
if (hwp_active) {
30703090
const struct x86_cpu_id *id;

0 commit comments

Comments
 (0)