Skip to content

Commit 1d6c915

Browse files
Kuppuswamy Sathyanarayananrafaeljw
authored andcommitted
powercap: intel_rapl: Prepare read_raw() interface for atomic-context callers
The current read_raw() implementation of the TPMI, MMIO and MSR interfaces does not distinguish between atomic and non-atomic callers. rapl_msr_read_raw() uses rdmsrq_safe_on_cpu(), which can sleep and issue cross CPU calls. When MSR-based RAPL PMU support is enabled, PMU event handlers can invoke this function from atomic context where sleeping or rescheduling is not allowed. In atomic context, the caller is already executing on the target CPU, so a direct rdmsrq() is sufficient. To support such usage, introduce an atomic flag to the read_raw() interface to allow callers pass the context information. Modify the common RAPL code to propagate this flag, and set the flag to reflect the calling contexts. Utilize the atomic flag in rapl_msr_read_raw() to perform direct MSR read with rdmsrq() when running in atomic context, and a sanity check to ensure target CPU matches the current CPU for such use cases. The TPMI and MMIO implementations do not require special atomic handling, so the flag is ignored in those paths. This is a preparatory patch for adding MSR-based RAPL PMU support. Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> [ rjw: Subject tweak ] Link: https://patch.msgid.link/20251121000539.386069-2-sathyanarayanan.kuppuswamy@linux.intel.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 58075ae commit 1d6c915

5 files changed

Lines changed: 31 additions & 15 deletions

File tree

drivers/powercap/intel_rapl_common.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ struct rapl_primitive_info {
253253
static void rapl_init_domains(struct rapl_package *rp);
254254
static int rapl_read_data_raw(struct rapl_domain *rd,
255255
enum rapl_primitives prim,
256-
bool xlate, u64 *data);
256+
bool xlate, u64 *data,
257+
bool atomic);
257258
static int rapl_write_data_raw(struct rapl_domain *rd,
258259
enum rapl_primitives prim,
259260
unsigned long long value);
@@ -289,7 +290,7 @@ static int get_energy_counter(struct powercap_zone *power_zone,
289290
cpus_read_lock();
290291
rd = power_zone_to_rapl_domain(power_zone);
291292

292-
if (!rapl_read_data_raw(rd, ENERGY_COUNTER, true, &energy_now)) {
293+
if (!rapl_read_data_raw(rd, ENERGY_COUNTER, true, &energy_now, false)) {
293294
*energy_raw = energy_now;
294295
cpus_read_unlock();
295296

@@ -830,7 +831,8 @@ prim_fixups(struct rapl_domain *rd, enum rapl_primitives prim)
830831
* 63-------------------------- 31--------------------------- 0
831832
*/
832833
static int rapl_read_data_raw(struct rapl_domain *rd,
833-
enum rapl_primitives prim, bool xlate, u64 *data)
834+
enum rapl_primitives prim, bool xlate, u64 *data,
835+
bool atomic)
834836
{
835837
u64 value;
836838
enum rapl_primitives prim_fixed = prim_fixups(rd, prim);
@@ -852,7 +854,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
852854

853855
ra.mask = rpi->mask;
854856

855-
if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
857+
if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra, atomic)) {
856858
pr_debug("failed to read reg 0x%llx for %s:%s\n", ra.reg.val, rd->rp->name, rd->name);
857859
return -EIO;
858860
}
@@ -904,7 +906,7 @@ static int rapl_read_pl_data(struct rapl_domain *rd, int pl,
904906
if (!is_pl_valid(rd, pl))
905907
return -EINVAL;
906908

907-
return rapl_read_data_raw(rd, prim, xlate, data);
909+
return rapl_read_data_raw(rd, prim, xlate, data, false);
908910
}
909911

910912
static int rapl_write_pl_data(struct rapl_domain *rd, int pl,
@@ -941,7 +943,7 @@ static int rapl_check_unit_core(struct rapl_domain *rd)
941943

942944
ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT];
943945
ra.mask = ~0;
944-
if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
946+
if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra, false)) {
945947
pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
946948
ra.reg.val, rd->rp->name, rd->name);
947949
return -ENODEV;
@@ -969,7 +971,7 @@ static int rapl_check_unit_atom(struct rapl_domain *rd)
969971

970972
ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT];
971973
ra.mask = ~0;
972-
if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
974+
if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra, false)) {
973975
pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
974976
ra.reg.val, rd->rp->name, rd->name);
975977
return -ENODEV;
@@ -1156,7 +1158,7 @@ static int rapl_check_unit_tpmi(struct rapl_domain *rd)
11561158

11571159
ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT];
11581160
ra.mask = ~0;
1159-
if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
1161+
if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra, false)) {
11601162
pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
11611163
ra.reg.val, rd->rp->name, rd->name);
11621164
return -ENODEV;
@@ -1328,7 +1330,7 @@ static void rapl_update_domain_data(struct rapl_package *rp)
13281330
struct rapl_primitive_info *rpi = get_rpi(rp, prim);
13291331

13301332
if (!rapl_read_data_raw(&rp->domains[dmn], prim,
1331-
rpi->unit, &val))
1333+
rpi->unit, &val, false))
13321334
rp->domains[dmn].rdd.primitives[prim] = val;
13331335
}
13341336
}
@@ -1428,7 +1430,7 @@ static int rapl_check_domain(int domain, struct rapl_package *rp)
14281430
*/
14291431

14301432
ra.mask = ENERGY_STATUS_MASK;
1431-
if (rp->priv->read_raw(get_rid(rp), &ra) || !ra.value)
1433+
if (rp->priv->read_raw(get_rid(rp), &ra, false) || !ra.value)
14321434
return -ENODEV;
14331435

14341436
return 0;
@@ -1639,7 +1641,7 @@ static u64 event_read_counter(struct perf_event *event)
16391641
if (event->hw.idx < 0)
16401642
return 0;
16411643

1642-
ret = rapl_read_data_raw(&rp->domains[event->hw.idx], ENERGY_COUNTER, false, &val);
1644+
ret = rapl_read_data_raw(&rp->domains[event->hw.idx], ENERGY_COUNTER, false, &val, true);
16431645

16441646
/* Return 0 for failed read */
16451647
if (ret)

drivers/powercap/intel_rapl_msr.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,26 @@ static int rapl_cpu_down_prep(unsigned int cpu)
102102
return 0;
103103
}
104104

105-
static int rapl_msr_read_raw(int cpu, struct reg_action *ra)
105+
static int rapl_msr_read_raw(int cpu, struct reg_action *ra, bool atomic)
106106
{
107+
/*
108+
* When called from atomic-context (eg PMU event handler)
109+
* perform MSR read directly using rdmsrq().
110+
*/
111+
if (atomic) {
112+
if (unlikely(smp_processor_id() != cpu))
113+
return -EIO;
114+
115+
rdmsrq(ra->reg.msr, ra->value);
116+
goto out;
117+
}
118+
107119
if (rdmsrq_safe_on_cpu(cpu, ra->reg.msr, &ra->value)) {
108120
pr_debug("failed to read msr 0x%x on cpu %d\n", ra->reg.msr, cpu);
109121
return -EIO;
110122
}
123+
124+
out:
111125
ra->value &= ra->mask;
112126
return 0;
113127
}

drivers/powercap/intel_rapl_tpmi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static DEFINE_MUTEX(tpmi_rapl_lock);
6060

6161
static struct powercap_control_type *tpmi_control_type;
6262

63-
static int tpmi_rapl_read_raw(int id, struct reg_action *ra)
63+
static int tpmi_rapl_read_raw(int id, struct reg_action *ra, bool atomic)
6464
{
6565
if (!ra->reg.mmio)
6666
return -EINVAL;

drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ static const struct rapl_mmio_regs rapl_mmio_default = {
1919
.limits[RAPL_DOMAIN_DRAM] = BIT(POWER_LIMIT2),
2020
};
2121

22-
static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
22+
static int rapl_mmio_read_raw(int cpu, struct reg_action *ra, bool atomic)
2323
{
2424
if (!ra->reg.mmio)
2525
return -EINVAL;

include/linux/intel_rapl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ struct rapl_if_priv {
152152
union rapl_reg reg_unit;
153153
union rapl_reg regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX];
154154
int limits[RAPL_DOMAIN_MAX];
155-
int (*read_raw)(int id, struct reg_action *ra);
155+
int (*read_raw)(int id, struct reg_action *ra, bool atomic);
156156
int (*write_raw)(int id, struct reg_action *ra);
157157
void *defaults;
158158
void *rpi;

0 commit comments

Comments
 (0)