Skip to content

Commit 6fec833

Browse files
committed
cpufreq: Add and use cpufreq policy locking guards
Introduce "read" and "write" locking guards for cpufreq policies and use them where applicable in the cpufreq core. No intentional functional impact. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> Acked-by: Sudeep Holla <sudeep.holla@arm.com> Tested-by: Sudeep Holla <sudeep.holla@arm.com> Link: https://patch.msgid.link/8518682.T7Z3S40VBb@rjwysocki.net
1 parent 68974e3 commit 6fec833

2 files changed

Lines changed: 60 additions & 67 deletions

File tree

drivers/cpufreq/cpufreq.c

Lines changed: 54 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,35 +1009,33 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
10091009
{
10101010
struct cpufreq_policy *policy = to_policy(kobj);
10111011
struct freq_attr *fattr = to_attr(attr);
1012-
ssize_t ret = -EBUSY;
10131012

10141013
if (!fattr->show)
10151014
return -EIO;
10161015

1017-
down_read(&policy->rwsem);
1016+
guard(cpufreq_policy_read)(policy);
1017+
10181018
if (likely(!policy_is_inactive(policy)))
1019-
ret = fattr->show(policy, buf);
1020-
up_read(&policy->rwsem);
1019+
return fattr->show(policy, buf);
10211020

1022-
return ret;
1021+
return -EBUSY;
10231022
}
10241023

10251024
static ssize_t store(struct kobject *kobj, struct attribute *attr,
10261025
const char *buf, size_t count)
10271026
{
10281027
struct cpufreq_policy *policy = to_policy(kobj);
10291028
struct freq_attr *fattr = to_attr(attr);
1030-
ssize_t ret = -EBUSY;
10311029

10321030
if (!fattr->store)
10331031
return -EIO;
10341032

1035-
down_write(&policy->rwsem);
1033+
guard(cpufreq_policy_write)(policy);
1034+
10361035
if (likely(!policy_is_inactive(policy)))
1037-
ret = fattr->store(policy, buf, count);
1038-
up_write(&policy->rwsem);
1036+
return fattr->store(policy, buf, count);
10391037

1040-
return ret;
1038+
return -EBUSY;
10411039
}
10421040

10431041
static void cpufreq_sysfs_release(struct kobject *kobj)
@@ -1195,7 +1193,8 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp
11951193
if (cpumask_test_cpu(cpu, policy->cpus))
11961194
return 0;
11971195

1198-
down_write(&policy->rwsem);
1196+
guard(cpufreq_policy_write)(policy);
1197+
11991198
if (has_target())
12001199
cpufreq_stop_governor(policy);
12011200

@@ -1206,7 +1205,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp
12061205
if (ret)
12071206
pr_err("%s: Failed to start governor\n", __func__);
12081207
}
1209-
up_write(&policy->rwsem);
1208+
12101209
return ret;
12111210
}
12121211

@@ -1226,9 +1225,10 @@ static void handle_update(struct work_struct *work)
12261225
container_of(work, struct cpufreq_policy, update);
12271226

12281227
pr_debug("handle_update for cpu %u called\n", policy->cpu);
1229-
down_write(&policy->rwsem);
1228+
1229+
guard(cpufreq_policy_write)(policy);
1230+
12301231
refresh_frequency_limits(policy);
1231-
up_write(&policy->rwsem);
12321232
}
12331233

12341234
static int cpufreq_notifier_min(struct notifier_block *nb, unsigned long freq,
@@ -1254,11 +1254,11 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
12541254
struct kobject *kobj;
12551255
struct completion *cmp;
12561256

1257-
down_write(&policy->rwsem);
1258-
cpufreq_stats_free_table(policy);
1259-
kobj = &policy->kobj;
1260-
cmp = &policy->kobj_unregister;
1261-
up_write(&policy->rwsem);
1257+
scoped_guard(cpufreq_policy_write, policy) {
1258+
cpufreq_stats_free_table(policy);
1259+
kobj = &policy->kobj;
1260+
cmp = &policy->kobj_unregister;
1261+
}
12621262
kobject_put(kobj);
12631263

12641264
/*
@@ -1409,7 +1409,7 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
14091409
unsigned int j;
14101410
int ret;
14111411

1412-
down_write(&policy->rwsem);
1412+
guard(cpufreq_policy_write)(policy);
14131413

14141414
policy->cpu = cpu;
14151415
policy->governor = NULL;
@@ -1586,10 +1586,7 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
15861586
goto out_destroy_policy;
15871587
}
15881588

1589-
out_unlock:
1590-
up_write(&policy->rwsem);
1591-
1592-
return ret;
1589+
return 0;
15931590

15941591
out_destroy_policy:
15951592
for_each_cpu(j, policy->real_cpus)
@@ -1606,7 +1603,7 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
16061603
out_clear_policy:
16071604
cpumask_clear(policy->cpus);
16081605

1609-
goto out_unlock;
1606+
return ret;
16101607
}
16111608

16121609
static int cpufreq_online(unsigned int cpu)
@@ -1754,11 +1751,10 @@ static int cpufreq_offline(unsigned int cpu)
17541751
return 0;
17551752
}
17561753

1757-
down_write(&policy->rwsem);
1754+
guard(cpufreq_policy_write)(policy);
17581755

17591756
__cpufreq_offline(cpu, policy);
17601757

1761-
up_write(&policy->rwsem);
17621758
return 0;
17631759
}
17641760

@@ -1775,33 +1771,29 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
17751771
if (!policy)
17761772
return;
17771773

1778-
down_write(&policy->rwsem);
1774+
scoped_guard(cpufreq_policy_write, policy) {
1775+
if (cpu_online(cpu))
1776+
__cpufreq_offline(cpu, policy);
17791777

1780-
if (cpu_online(cpu))
1781-
__cpufreq_offline(cpu, policy);
1778+
remove_cpu_dev_symlink(policy, cpu, dev);
17821779

1783-
remove_cpu_dev_symlink(policy, cpu, dev);
1780+
if (!cpumask_empty(policy->real_cpus))
1781+
return;
17841782

1785-
if (!cpumask_empty(policy->real_cpus)) {
1786-
up_write(&policy->rwsem);
1787-
return;
1788-
}
1783+
/*
1784+
* Unregister cpufreq cooling once all the CPUs of the policy
1785+
* are removed.
1786+
*/
1787+
if (cpufreq_thermal_control_enabled(cpufreq_driver)) {
1788+
cpufreq_cooling_unregister(policy->cdev);
1789+
policy->cdev = NULL;
1790+
}
17891791

1790-
/*
1791-
* Unregister cpufreq cooling once all the CPUs of the policy are
1792-
* removed.
1793-
*/
1794-
if (cpufreq_thermal_control_enabled(cpufreq_driver)) {
1795-
cpufreq_cooling_unregister(policy->cdev);
1796-
policy->cdev = NULL;
1792+
/* We did light-weight exit earlier, do full tear down now */
1793+
if (cpufreq_driver->offline && cpufreq_driver->exit)
1794+
cpufreq_driver->exit(policy);
17971795
}
17981796

1799-
/* We did light-weight exit earlier, do full tear down now */
1800-
if (cpufreq_driver->offline && cpufreq_driver->exit)
1801-
cpufreq_driver->exit(policy);
1802-
1803-
up_write(&policy->rwsem);
1804-
18051797
cpufreq_policy_free(policy);
18061798
}
18071799

@@ -1954,15 +1946,16 @@ unsigned int cpufreq_get(unsigned int cpu)
19541946
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
19551947
unsigned int ret_freq = 0;
19561948

1957-
if (policy) {
1958-
down_read(&policy->rwsem);
1949+
if (!policy)
1950+
return 0;
1951+
1952+
scoped_guard(cpufreq_policy_read, policy) {
19591953
if (cpufreq_driver->get)
19601954
ret_freq = __cpufreq_get(policy);
1961-
up_read(&policy->rwsem);
1962-
1963-
cpufreq_cpu_put(policy);
19641955
}
19651956

1957+
cpufreq_cpu_put(policy);
1958+
19661959
return ret_freq;
19671960
}
19681961
EXPORT_SYMBOL(cpufreq_get);
@@ -2022,9 +2015,9 @@ void cpufreq_suspend(void)
20222015

20232016
for_each_active_policy(policy) {
20242017
if (has_target()) {
2025-
down_write(&policy->rwsem);
2026-
cpufreq_stop_governor(policy);
2027-
up_write(&policy->rwsem);
2018+
scoped_guard(cpufreq_policy_write, policy) {
2019+
cpufreq_stop_governor(policy);
2020+
}
20282021
}
20292022

20302023
if (cpufreq_driver->suspend && cpufreq_driver->suspend(policy))
@@ -2065,9 +2058,9 @@ void cpufreq_resume(void)
20652058
pr_err("%s: Failed to resume driver: %s\n", __func__,
20662059
cpufreq_driver->name);
20672060
} else if (has_target()) {
2068-
down_write(&policy->rwsem);
2069-
ret = cpufreq_start_governor(policy);
2070-
up_write(&policy->rwsem);
2061+
scoped_guard(cpufreq_policy_write, policy) {
2062+
ret = cpufreq_start_governor(policy);
2063+
}
20712064

20722065
if (ret)
20732066
pr_err("%s: Failed to start governor for CPU%u's policy\n",
@@ -2434,15 +2427,9 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
24342427
unsigned int target_freq,
24352428
unsigned int relation)
24362429
{
2437-
int ret;
2430+
guard(cpufreq_policy_write)(policy);
24382431

2439-
down_write(&policy->rwsem);
2440-
2441-
ret = __cpufreq_driver_target(policy, target_freq, relation);
2442-
2443-
up_write(&policy->rwsem);
2444-
2445-
return ret;
2432+
return __cpufreq_driver_target(policy, target_freq, relation);
24462433
}
24472434
EXPORT_SYMBOL_GPL(cpufreq_driver_target);
24482435

include/linux/cpufreq.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ struct cpufreq_policy {
170170
struct notifier_block nb_max;
171171
};
172172

173+
DEFINE_GUARD(cpufreq_policy_write, struct cpufreq_policy *,
174+
down_write(&_T->rwsem), up_write(&_T->rwsem))
175+
176+
DEFINE_GUARD(cpufreq_policy_read, struct cpufreq_policy *,
177+
down_read(&_T->rwsem), up_read(&_T->rwsem))
178+
173179
/*
174180
* Used for passing new cpufreq policy data to the cpufreq driver's ->verify()
175181
* callback for sanitization. That callback is only expected to modify the min

0 commit comments

Comments
 (0)