mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 12:21:22 -05:00
Merge tag 'pm-6.19-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael Wysocki:
"These fix three issues in the power capping code including one recent
regression and a runtime PM framework regression introduced during the
6.17 development cycle:
- Fix CPU hotplug locking deadlock reported by lockdep after a recent
update of the Intel RAPL power capping driver (Srinivas Pandruvada)
- Fix sscanf() error return value handling in the power capping core
and a race condition in register_control_type() (Sumeet Pawnikar)
- Fix a concurrent bit field update issue in the runtime PM core code
by only updating the bit field in question when runtime PM is
disabled (Rafael Wysocki)"
* tag 'pm-6.19-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
powercap: intel_rapl: Fix possible recursive lock warning
PM: runtime: Do not clear needs_force_resume with enabled runtime PM
powercap: fix sscanf() error return value handling
powercap: fix race condition in register_control_type()
This commit is contained in:
@@ -1868,16 +1868,18 @@ void pm_runtime_init(struct device *dev)
|
||||
*/
|
||||
void pm_runtime_reinit(struct device *dev)
|
||||
{
|
||||
if (!pm_runtime_enabled(dev)) {
|
||||
if (dev->power.runtime_status == RPM_ACTIVE)
|
||||
pm_runtime_set_suspended(dev);
|
||||
if (dev->power.irq_safe) {
|
||||
spin_lock_irq(&dev->power.lock);
|
||||
dev->power.irq_safe = 0;
|
||||
spin_unlock_irq(&dev->power.lock);
|
||||
if (dev->parent)
|
||||
pm_runtime_put(dev->parent);
|
||||
}
|
||||
if (pm_runtime_enabled(dev))
|
||||
return;
|
||||
|
||||
if (dev->power.runtime_status == RPM_ACTIVE)
|
||||
pm_runtime_set_suspended(dev);
|
||||
|
||||
if (dev->power.irq_safe) {
|
||||
spin_lock_irq(&dev->power.lock);
|
||||
dev->power.irq_safe = 0;
|
||||
spin_unlock_irq(&dev->power.lock);
|
||||
if (dev->parent)
|
||||
pm_runtime_put(dev->parent);
|
||||
}
|
||||
/*
|
||||
* Clear power.needs_force_resume in case it has been set by
|
||||
|
||||
@@ -2032,7 +2032,7 @@ static int rapl_pmu_update(struct rapl_package *rp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rapl_package_add_pmu(struct rapl_package *rp)
|
||||
int rapl_package_add_pmu_locked(struct rapl_package *rp)
|
||||
{
|
||||
struct rapl_package_pmu_data *data = &rp->pmu_data;
|
||||
int idx;
|
||||
@@ -2040,8 +2040,6 @@ int rapl_package_add_pmu(struct rapl_package *rp)
|
||||
if (rp->has_pmu)
|
||||
return -EEXIST;
|
||||
|
||||
guard(cpus_read_lock)();
|
||||
|
||||
for (idx = 0; idx < rp->nr_domains; idx++) {
|
||||
struct rapl_domain *rd = &rp->domains[idx];
|
||||
int domain = rd->id;
|
||||
@@ -2091,17 +2089,23 @@ int rapl_package_add_pmu(struct rapl_package *rp)
|
||||
|
||||
return rapl_pmu_update(rp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rapl_package_add_pmu_locked);
|
||||
|
||||
int rapl_package_add_pmu(struct rapl_package *rp)
|
||||
{
|
||||
guard(cpus_read_lock)();
|
||||
|
||||
return rapl_package_add_pmu_locked(rp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rapl_package_add_pmu);
|
||||
|
||||
void rapl_package_remove_pmu(struct rapl_package *rp)
|
||||
void rapl_package_remove_pmu_locked(struct rapl_package *rp)
|
||||
{
|
||||
struct rapl_package *pos;
|
||||
|
||||
if (!rp->has_pmu)
|
||||
return;
|
||||
|
||||
guard(cpus_read_lock)();
|
||||
|
||||
list_for_each_entry(pos, &rapl_packages, plist) {
|
||||
/* PMU is still needed */
|
||||
if (pos->has_pmu && pos != rp)
|
||||
@@ -2111,6 +2115,14 @@ void rapl_package_remove_pmu(struct rapl_package *rp)
|
||||
perf_pmu_unregister(&rapl_pmu.pmu);
|
||||
memset(&rapl_pmu, 0, sizeof(struct rapl_pmu));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rapl_package_remove_pmu_locked);
|
||||
|
||||
void rapl_package_remove_pmu(struct rapl_package *rp)
|
||||
{
|
||||
guard(cpus_read_lock)();
|
||||
|
||||
rapl_package_remove_pmu_locked(rp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rapl_package_remove_pmu);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ static int rapl_cpu_online(unsigned int cpu)
|
||||
if (IS_ERR(rp))
|
||||
return PTR_ERR(rp);
|
||||
if (rapl_msr_pmu)
|
||||
rapl_package_add_pmu(rp);
|
||||
rapl_package_add_pmu_locked(rp);
|
||||
}
|
||||
cpumask_set_cpu(cpu, &rp->cpumask);
|
||||
return 0;
|
||||
@@ -101,7 +101,7 @@ static int rapl_cpu_down_prep(unsigned int cpu)
|
||||
lead_cpu = cpumask_first(&rp->cpumask);
|
||||
if (lead_cpu >= nr_cpu_ids) {
|
||||
if (rapl_msr_pmu)
|
||||
rapl_package_remove_pmu(rp);
|
||||
rapl_package_remove_pmu_locked(rp);
|
||||
rapl_remove_package_cpuslocked(rp);
|
||||
} else if (rp->lead_cpu == cpu) {
|
||||
rp->lead_cpu = lead_cpu;
|
||||
|
||||
@@ -68,7 +68,7 @@ static ssize_t show_constraint_##_attr(struct device *dev, \
|
||||
int id; \
|
||||
struct powercap_zone_constraint *pconst;\
|
||||
\
|
||||
if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
|
||||
if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1) \
|
||||
return -EINVAL; \
|
||||
if (id >= power_zone->const_id_cnt) \
|
||||
return -EINVAL; \
|
||||
@@ -93,7 +93,7 @@ static ssize_t store_constraint_##_attr(struct device *dev,\
|
||||
int id; \
|
||||
struct powercap_zone_constraint *pconst;\
|
||||
\
|
||||
if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
|
||||
if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1) \
|
||||
return -EINVAL; \
|
||||
if (id >= power_zone->const_id_cnt) \
|
||||
return -EINVAL; \
|
||||
@@ -162,7 +162,7 @@ static ssize_t show_constraint_name(struct device *dev,
|
||||
ssize_t len = -ENODATA;
|
||||
struct powercap_zone_constraint *pconst;
|
||||
|
||||
if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id))
|
||||
if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1)
|
||||
return -EINVAL;
|
||||
if (id >= power_zone->const_id_cnt)
|
||||
return -EINVAL;
|
||||
@@ -625,17 +625,23 @@ struct powercap_control_type *powercap_register_control_type(
|
||||
INIT_LIST_HEAD(&control_type->node);
|
||||
control_type->dev.class = &powercap_class;
|
||||
dev_set_name(&control_type->dev, "%s", name);
|
||||
result = device_register(&control_type->dev);
|
||||
if (result) {
|
||||
put_device(&control_type->dev);
|
||||
return ERR_PTR(result);
|
||||
}
|
||||
idr_init(&control_type->idr);
|
||||
|
||||
mutex_lock(&powercap_cntrl_list_lock);
|
||||
list_add_tail(&control_type->node, &powercap_cntrl_list);
|
||||
mutex_unlock(&powercap_cntrl_list_lock);
|
||||
|
||||
result = device_register(&control_type->dev);
|
||||
if (result) {
|
||||
mutex_lock(&powercap_cntrl_list_lock);
|
||||
list_del(&control_type->node);
|
||||
mutex_unlock(&powercap_cntrl_list_lock);
|
||||
|
||||
idr_destroy(&control_type->idr);
|
||||
put_device(&control_type->dev);
|
||||
return ERR_PTR(result);
|
||||
}
|
||||
|
||||
return control_type;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(powercap_register_control_type);
|
||||
|
||||
@@ -214,10 +214,14 @@ void rapl_remove_package(struct rapl_package *rp);
|
||||
|
||||
#ifdef CONFIG_PERF_EVENTS
|
||||
int rapl_package_add_pmu(struct rapl_package *rp);
|
||||
int rapl_package_add_pmu_locked(struct rapl_package *rp);
|
||||
void rapl_package_remove_pmu(struct rapl_package *rp);
|
||||
void rapl_package_remove_pmu_locked(struct rapl_package *rp);
|
||||
#else
|
||||
static inline int rapl_package_add_pmu(struct rapl_package *rp) { return 0; }
|
||||
static inline int rapl_package_add_pmu_locked(struct rapl_package *rp) { return 0; }
|
||||
static inline void rapl_package_remove_pmu(struct rapl_package *rp) { }
|
||||
static inline void rapl_package_remove_pmu_locked(struct rapl_package *rp) { }
|
||||
#endif
|
||||
|
||||
#endif /* __INTEL_RAPL_H__ */
|
||||
|
||||
Reference in New Issue
Block a user