Skip to content

Commit 1aa09b9

Browse files
zhang-ruirafaeljw
authored andcommitted
powercap: intel_rapl: Fix locking in TPMI RAPL
The RAPL framework uses CPU hotplug locking to protect the rapl_packages list and rp->lead_cpu to guarantee that 1. the RAPL package device is not unprobed and freed 2. the cached rp->lead_cpu is always valid for operations like powercap sysfs accesses. Current RAPL APIs assume being called from CPU hotplug callbacks which hold the CPU hotplug lock, but TPMI RAPL driver invokes the APIs in the driver's .probe() function without acquiring the CPU hotplug lock. Fix the problem by providing both locked and lockless versions of RAPL APIs. Fixes: 9eef7f9 ("powercap: intel_rapl: Introduce RAPL TPMI interface driver") Signed-off-by: Zhang Rui <rui.zhang@intel.com> Cc: 6.5+ <stable@vger.kernel.org> # 6.5+ Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 2d1f500 commit 1aa09b9

File tree

4 files changed

+40
-11
lines changed

4 files changed

+40
-11
lines changed

drivers/powercap/intel_rapl_common.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
77

8+
#include <linux/cleanup.h>
89
#include <linux/kernel.h>
910
#include <linux/module.h>
1011
#include <linux/list.h>
@@ -1504,7 +1505,7 @@ static int rapl_detect_domains(struct rapl_package *rp)
15041505
}
15051506

15061507
/* called from CPU hotplug notifier, hotplug lock held */
1507-
void rapl_remove_package(struct rapl_package *rp)
1508+
void rapl_remove_package_cpuslocked(struct rapl_package *rp)
15081509
{
15091510
struct rapl_domain *rd, *rd_package = NULL;
15101511

@@ -1533,10 +1534,18 @@ void rapl_remove_package(struct rapl_package *rp)
15331534
list_del(&rp->plist);
15341535
kfree(rp);
15351536
}
1537+
EXPORT_SYMBOL_GPL(rapl_remove_package_cpuslocked);
1538+
1539+
void rapl_remove_package(struct rapl_package *rp)
1540+
{
1541+
guard(cpus_read_lock)();
1542+
rapl_remove_package_cpuslocked(rp);
1543+
}
15361544
EXPORT_SYMBOL_GPL(rapl_remove_package);
15371545

15381546
/* caller to ensure CPU hotplug lock is held */
1539-
struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu)
1547+
struct rapl_package *rapl_find_package_domain_cpuslocked(int id, struct rapl_if_priv *priv,
1548+
bool id_is_cpu)
15401549
{
15411550
struct rapl_package *rp;
15421551
int uid;
@@ -1554,10 +1563,17 @@ struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv,
15541563

15551564
return NULL;
15561565
}
1566+
EXPORT_SYMBOL_GPL(rapl_find_package_domain_cpuslocked);
1567+
1568+
struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu)
1569+
{
1570+
guard(cpus_read_lock)();
1571+
return rapl_find_package_domain_cpuslocked(id, priv, id_is_cpu);
1572+
}
15571573
EXPORT_SYMBOL_GPL(rapl_find_package_domain);
15581574

15591575
/* called from CPU hotplug notifier, hotplug lock held */
1560-
struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu)
1576+
struct rapl_package *rapl_add_package_cpuslocked(int id, struct rapl_if_priv *priv, bool id_is_cpu)
15611577
{
15621578
struct rapl_package *rp;
15631579
int ret;
@@ -1603,6 +1619,13 @@ struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id
16031619
kfree(rp);
16041620
return ERR_PTR(ret);
16051621
}
1622+
EXPORT_SYMBOL_GPL(rapl_add_package_cpuslocked);
1623+
1624+
struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu)
1625+
{
1626+
guard(cpus_read_lock)();
1627+
return rapl_add_package_cpuslocked(id, priv, id_is_cpu);
1628+
}
16061629
EXPORT_SYMBOL_GPL(rapl_add_package);
16071630

16081631
static void power_limit_state_save(void)

drivers/powercap/intel_rapl_msr.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ static int rapl_cpu_online(unsigned int cpu)
7373
{
7474
struct rapl_package *rp;
7575

76-
rp = rapl_find_package_domain(cpu, rapl_msr_priv, true);
76+
rp = rapl_find_package_domain_cpuslocked(cpu, rapl_msr_priv, true);
7777
if (!rp) {
78-
rp = rapl_add_package(cpu, rapl_msr_priv, true);
78+
rp = rapl_add_package_cpuslocked(cpu, rapl_msr_priv, true);
7979
if (IS_ERR(rp))
8080
return PTR_ERR(rp);
8181
}
@@ -88,14 +88,14 @@ static int rapl_cpu_down_prep(unsigned int cpu)
8888
struct rapl_package *rp;
8989
int lead_cpu;
9090

91-
rp = rapl_find_package_domain(cpu, rapl_msr_priv, true);
91+
rp = rapl_find_package_domain_cpuslocked(cpu, rapl_msr_priv, true);
9292
if (!rp)
9393
return 0;
9494

9595
cpumask_clear_cpu(cpu, &rp->cpumask);
9696
lead_cpu = cpumask_first(&rp->cpumask);
9797
if (lead_cpu >= nr_cpu_ids)
98-
rapl_remove_package(rp);
98+
rapl_remove_package_cpuslocked(rp);
9999
else if (rp->lead_cpu == cpu)
100100
rp->lead_cpu = lead_cpu;
101101
return 0;

drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ static int rapl_mmio_cpu_online(unsigned int cpu)
2727
if (topology_physical_package_id(cpu))
2828
return 0;
2929

30-
rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true);
30+
rp = rapl_find_package_domain_cpuslocked(cpu, &rapl_mmio_priv, true);
3131
if (!rp) {
32-
rp = rapl_add_package(cpu, &rapl_mmio_priv, true);
32+
rp = rapl_add_package_cpuslocked(cpu, &rapl_mmio_priv, true);
3333
if (IS_ERR(rp))
3434
return PTR_ERR(rp);
3535
}
@@ -42,14 +42,14 @@ static int rapl_mmio_cpu_down_prep(unsigned int cpu)
4242
struct rapl_package *rp;
4343
int lead_cpu;
4444

45-
rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true);
45+
rp = rapl_find_package_domain_cpuslocked(cpu, &rapl_mmio_priv, true);
4646
if (!rp)
4747
return 0;
4848

4949
cpumask_clear_cpu(cpu, &rp->cpumask);
5050
lead_cpu = cpumask_first(&rp->cpumask);
5151
if (lead_cpu >= nr_cpu_ids)
52-
rapl_remove_package(rp);
52+
rapl_remove_package_cpuslocked(rp);
5353
else if (rp->lead_cpu == cpu)
5454
rp->lead_cpu = lead_cpu;
5555
return 0;

include/linux/intel_rapl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ struct rapl_package {
178178
struct rapl_if_priv *priv;
179179
};
180180

181+
struct rapl_package *rapl_find_package_domain_cpuslocked(int id, struct rapl_if_priv *priv,
182+
bool id_is_cpu);
183+
struct rapl_package *rapl_add_package_cpuslocked(int id, struct rapl_if_priv *priv,
184+
bool id_is_cpu);
185+
void rapl_remove_package_cpuslocked(struct rapl_package *rp);
186+
181187
struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu);
182188
struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu);
183189
void rapl_remove_package(struct rapl_package *rp);

0 commit comments

Comments
 (0)