Skip to content

Commit f786dfa

Browse files
committed
Merge tag 'pm-5.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael Wysocki: "These fix the device links support in runtime PM, correct mistakes in the cpuidle documentation, fix the handling of policy limits changes in the schedutil cpufreq governor, fix assorted issues in the OPP (operating performance points) framework and make one janitorial change. Specifics: - Unify the handling of managed and stateless device links in the runtime PM framework and prevent runtime PM references to devices from being leaked after device link removal (Rafael Wysocki). - Fix two mistakes in the cpuidle documentation (Julia Lawall). - Prevent the schedutil cpufreq governor from missing policy limits updates in some cases (Viresh Kumar). - Prevent static OPPs from being dropped by mistake (Viresh Kumar). - Prevent helper function in the OPP framework from returning prematurely (Viresh Kumar). - Prevent opp_table_lock from being held too long during removal of OPP tables with no more active references (Viresh Kumar). - Drop redundant semicolon from the Intel RAPL power capping driver (Tom Rix)" * tag 'pm-5.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PM: runtime: Resume the device earlier in __device_release_driver() PM: runtime: Drop pm_runtime_clean_up_links() PM: runtime: Drop runtime PM references to supplier on link removal powercap/intel_rapl: remove unneeded semicolon Documentation: PM: cpuidle: correct path name Documentation: PM: cpuidle: correct typo cpufreq: schedutil: Don't skip freq update if need_freq_update is set opp: Reduce the size of critical section in _opp_table_kref_release() opp: Fix early exit from dev_pm_opp_register_set_opp_helper() opp: Don't always remove static OPPs in _of_add_opp_table_v1()
2 parents 1a09247 + 8c14577 commit f786dfa

9 files changed

Lines changed: 49 additions & 68 deletions

File tree

Documentation/admin-guide/pm/cpuidle.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ order to ask the hardware to enter that state. Also, for each
478478
statistics of the given idle state. That information is exposed by the kernel
479479
via ``sysfs``.
480480

481-
For each CPU in the system, there is a :file:`/sys/devices/system/cpu<N>/cpuidle/`
481+
For each CPU in the system, there is a :file:`/sys/devices/system/cpu/cpu<N>/cpuidle/`
482482
directory in ``sysfs``, where the number ``<N>`` is assigned to the given
483483
CPU at the initialization time. That directory contains a set of subdirectories
484484
called :file:`state0`, :file:`state1` and so on, up to the number of idle state
@@ -494,7 +494,7 @@ object corresponding to it, as follows:
494494
residency.
495495

496496
``below``
497-
Total number of times this idle state had been asked for, but cerainly
497+
Total number of times this idle state had been asked for, but certainly
498498
a deeper idle state would have been a better match for the observed idle
499499
duration.
500500

drivers/base/core.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,8 +773,7 @@ static void __device_link_del(struct kref *kref)
773773
dev_dbg(link->consumer, "Dropping the link to %s\n",
774774
dev_name(link->supplier));
775775

776-
if (link->flags & DL_FLAG_PM_RUNTIME)
777-
pm_runtime_drop_link(link->consumer);
776+
pm_runtime_drop_link(link);
778777

779778
list_del_rcu(&link->s_node);
780779
list_del_rcu(&link->c_node);
@@ -788,8 +787,7 @@ static void __device_link_del(struct kref *kref)
788787
dev_info(link->consumer, "Dropping the link to %s\n",
789788
dev_name(link->supplier));
790789

791-
if (link->flags & DL_FLAG_PM_RUNTIME)
792-
pm_runtime_drop_link(link->consumer);
790+
pm_runtime_drop_link(link);
793791

794792
list_del(&link->s_node);
795793
list_del(&link->c_node);

drivers/base/dd.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
11171117

11181118
drv = dev->driver;
11191119
if (drv) {
1120+
pm_runtime_get_sync(dev);
1121+
11201122
while (device_links_busy(dev)) {
11211123
__device_driver_unlock(dev, parent);
11221124

@@ -1128,13 +1130,12 @@ static void __device_release_driver(struct device *dev, struct device *parent)
11281130
* have released the driver successfully while this one
11291131
* was waiting, so check for that.
11301132
*/
1131-
if (dev->driver != drv)
1133+
if (dev->driver != drv) {
1134+
pm_runtime_put(dev);
11321135
return;
1136+
}
11331137
}
11341138

1135-
pm_runtime_get_sync(dev);
1136-
pm_runtime_clean_up_links(dev);
1137-
11381139
driver_sysfs_remove(dev);
11391140

11401141
if (dev->bus)

drivers/base/power/runtime.c

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,42 +1642,6 @@ void pm_runtime_remove(struct device *dev)
16421642
pm_runtime_reinit(dev);
16431643
}
16441644

1645-
/**
1646-
* pm_runtime_clean_up_links - Prepare links to consumers for driver removal.
1647-
* @dev: Device whose driver is going to be removed.
1648-
*
1649-
* Check links from this device to any consumers and if any of them have active
1650-
* runtime PM references to the device, drop the usage counter of the device
1651-
* (as many times as needed).
1652-
*
1653-
* Links with the DL_FLAG_MANAGED flag unset are ignored.
1654-
*
1655-
* Since the device is guaranteed to be runtime-active at the point this is
1656-
* called, nothing else needs to be done here.
1657-
*
1658-
* Moreover, this is called after device_links_busy() has returned 'false', so
1659-
* the status of each link is guaranteed to be DL_STATE_SUPPLIER_UNBIND and
1660-
* therefore rpm_active can't be manipulated concurrently.
1661-
*/
1662-
void pm_runtime_clean_up_links(struct device *dev)
1663-
{
1664-
struct device_link *link;
1665-
int idx;
1666-
1667-
idx = device_links_read_lock();
1668-
1669-
list_for_each_entry_rcu(link, &dev->links.consumers, s_node,
1670-
device_links_read_lock_held()) {
1671-
if (!(link->flags & DL_FLAG_MANAGED))
1672-
continue;
1673-
1674-
while (refcount_dec_not_one(&link->rpm_active))
1675-
pm_runtime_put_noidle(dev);
1676-
}
1677-
1678-
device_links_read_unlock(idx);
1679-
}
1680-
16811645
/**
16821646
* pm_runtime_get_suppliers - Resume and reference-count supplier devices.
16831647
* @dev: Consumer device.
@@ -1729,14 +1693,33 @@ void pm_runtime_new_link(struct device *dev)
17291693
spin_unlock_irq(&dev->power.lock);
17301694
}
17311695

1732-
void pm_runtime_drop_link(struct device *dev)
1696+
static void pm_runtime_drop_link_count(struct device *dev)
17331697
{
17341698
spin_lock_irq(&dev->power.lock);
17351699
WARN_ON(dev->power.links_count == 0);
17361700
dev->power.links_count--;
17371701
spin_unlock_irq(&dev->power.lock);
17381702
}
17391703

1704+
/**
1705+
* pm_runtime_drop_link - Prepare for device link removal.
1706+
* @link: Device link going away.
1707+
*
1708+
* Drop the link count of the consumer end of @link and decrement the supplier
1709+
* device's runtime PM usage counter as many times as needed to drop all of the
1710+
* PM runtime reference to it from the consumer.
1711+
*/
1712+
void pm_runtime_drop_link(struct device_link *link)
1713+
{
1714+
if (!(link->flags & DL_FLAG_PM_RUNTIME))
1715+
return;
1716+
1717+
pm_runtime_drop_link_count(link->consumer);
1718+
1719+
while (refcount_dec_not_one(&link->rpm_active))
1720+
pm_runtime_put(link->supplier);
1721+
}
1722+
17401723
static bool pm_runtime_need_not_resume(struct device *dev)
17411724
{
17421725
return atomic_read(&dev->power.usage_count) <= 1 &&

drivers/opp/core.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,10 @@ static void _opp_table_kref_release(struct kref *kref)
11811181
struct opp_device *opp_dev, *temp;
11821182
int i;
11831183

1184+
/* Drop the lock as soon as we can */
1185+
list_del(&opp_table->node);
1186+
mutex_unlock(&opp_table_lock);
1187+
11841188
_of_clear_opp_table(opp_table);
11851189

11861190
/* Release clk */
@@ -1208,10 +1212,7 @@ static void _opp_table_kref_release(struct kref *kref)
12081212

12091213
mutex_destroy(&opp_table->genpd_virt_dev_lock);
12101214
mutex_destroy(&opp_table->lock);
1211-
list_del(&opp_table->node);
12121215
kfree(opp_table);
1213-
1214-
mutex_unlock(&opp_table_lock);
12151216
}
12161217

12171218
void dev_pm_opp_put_opp_table(struct opp_table *opp_table)
@@ -1930,7 +1931,7 @@ struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
19301931
return ERR_PTR(-EINVAL);
19311932

19321933
opp_table = dev_pm_opp_get_opp_table(dev);
1933-
if (!IS_ERR(opp_table))
1934+
if (IS_ERR(opp_table))
19341935
return opp_table;
19351936

19361937
/* This should be called before OPPs are initialized */

drivers/opp/of.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,8 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
944944
nr -= 2;
945945
}
946946

947+
return 0;
948+
947949
remove_static_opp:
948950
_opp_remove_all_static(opp_table);
949951

drivers/powercap/intel_rapl_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type,
620620
case ARBITRARY_UNIT:
621621
default:
622622
return value;
623-
};
623+
}
624624

625625
if (to_raw)
626626
return div64_u64(value, units) * scale;

include/linux/pm_runtime.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,10 @@ extern u64 pm_runtime_autosuspend_expiration(struct device *dev);
5454
extern void pm_runtime_update_max_time_suspended(struct device *dev,
5555
s64 delta_ns);
5656
extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable);
57-
extern void pm_runtime_clean_up_links(struct device *dev);
5857
extern void pm_runtime_get_suppliers(struct device *dev);
5958
extern void pm_runtime_put_suppliers(struct device *dev);
6059
extern void pm_runtime_new_link(struct device *dev);
61-
extern void pm_runtime_drop_link(struct device *dev);
60+
extern void pm_runtime_drop_link(struct device_link *link);
6261

6362
/**
6463
* pm_runtime_get_if_in_use - Conditionally bump up runtime PM usage counter.
@@ -276,11 +275,10 @@ static inline u64 pm_runtime_autosuspend_expiration(
276275
struct device *dev) { return 0; }
277276
static inline void pm_runtime_set_memalloc_noio(struct device *dev,
278277
bool enable){}
279-
static inline void pm_runtime_clean_up_links(struct device *dev) {}
280278
static inline void pm_runtime_get_suppliers(struct device *dev) {}
281279
static inline void pm_runtime_put_suppliers(struct device *dev) {}
282280
static inline void pm_runtime_new_link(struct device *dev) {}
283-
static inline void pm_runtime_drop_link(struct device *dev) {}
281+
static inline void pm_runtime_drop_link(struct device_link *link) {}
284282

285283
#endif /* !CONFIG_PM */
286284

kernel/sched/cpufreq_schedutil.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,12 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
102102
static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time,
103103
unsigned int next_freq)
104104
{
105-
if (sg_policy->next_freq == next_freq &&
106-
!cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS))
107-
return false;
105+
if (!sg_policy->need_freq_update) {
106+
if (sg_policy->next_freq == next_freq)
107+
return false;
108+
} else {
109+
sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS);
110+
}
108111

109112
sg_policy->next_freq = next_freq;
110113
sg_policy->last_freq_update_time = time;
@@ -162,11 +165,9 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy,
162165

163166
freq = map_util_freq(util, freq, max);
164167

165-
if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update &&
166-
!cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS))
168+
if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
167169
return sg_policy->next_freq;
168170

169-
sg_policy->need_freq_update = false;
170171
sg_policy->cached_raw_freq = freq;
171172
return cpufreq_driver_resolve_freq(policy, freq);
172173
}
@@ -442,7 +443,6 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
442443
struct sugov_policy *sg_policy = sg_cpu->sg_policy;
443444
unsigned long util, max;
444445
unsigned int next_f;
445-
bool busy;
446446
unsigned int cached_freq = sg_policy->cached_raw_freq;
447447

448448
sugov_iowait_boost(sg_cpu, time, flags);
@@ -453,9 +453,6 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
453453
if (!sugov_should_update_freq(sg_policy, time))
454454
return;
455455

456-
/* Limits may have changed, don't skip frequency update */
457-
busy = !sg_policy->need_freq_update && sugov_cpu_is_busy(sg_cpu);
458-
459456
util = sugov_get_util(sg_cpu);
460457
max = sg_cpu->max;
461458
util = sugov_iowait_apply(sg_cpu, time, util, max);
@@ -464,7 +461,7 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
464461
* Do not reduce the frequency if the CPU has not been idle
465462
* recently, as the reduction is likely to be premature then.
466463
*/
467-
if (busy && next_f < sg_policy->next_freq) {
464+
if (sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
468465
next_f = sg_policy->next_freq;
469466

470467
/* Restore cached freq as next_freq has changed */
@@ -829,9 +826,10 @@ static int sugov_start(struct cpufreq_policy *policy)
829826
sg_policy->next_freq = 0;
830827
sg_policy->work_in_progress = false;
831828
sg_policy->limits_changed = false;
832-
sg_policy->need_freq_update = false;
833829
sg_policy->cached_raw_freq = 0;
834830

831+
sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS);
832+
835833
for_each_cpu(cpu, policy->cpus) {
836834
struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
837835

0 commit comments

Comments
 (0)