Skip to content

Commit f442bd2

Browse files
zhang-ruirafaeljw
authored andcommitted
powercap: intel_rapl: Add support for lock bit per Power Limit
With RAPL MSR/MMIO Interface, each RAPL domain has one Power Limit register. Each Power Limit register has one lock bit which tells the OS if the power limit register can be used or not. Depending on the number of power limits supported by the power limit register, the lock bit may apply to one or more power limits. With RAPL TPMI Interface, each RAPL domain has multiple Power Limits, and each Power Limit has its own register, with a lock bit. To handle this, introduce support for lock bit per Power Limit. For existing RAPL MSR/MMIO Interfaces, the lock bit in the Power Limit register applies to all the Power Limits controlled by this register. Remove the per domain DOMAIN_STATE_BIOS_LOCKED flag at the same time because it can be replaced by the per Power Limit lock. No functional change intended. Signed-off-by: Zhang Rui <[email protected]> Tested-by: Wang Wendy <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 9050a9c commit f442bd2

File tree

2 files changed

+32
-20
lines changed

2 files changed

+32
-20
lines changed

drivers/powercap/intel_rapl_common.c

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ enum unit_type {
9494

9595
#define DOMAIN_STATE_INACTIVE BIT(0)
9696
#define DOMAIN_STATE_POWER_LIMIT_SET BIT(1)
97-
#define DOMAIN_STATE_BIOS_LOCKED BIT(2)
9897

9998
static const char *pl_names[NR_POWER_LIMITS] = {
10099
[POWER_LIMIT1] = "long_term",
@@ -108,6 +107,7 @@ enum pl_prims {
108107
PL_LIMIT,
109108
PL_TIME_WINDOW,
110109
PL_MAX_POWER,
110+
PL_LOCK,
111111
};
112112

113113
static bool is_pl_valid(struct rapl_domain *rd, int pl)
@@ -117,7 +117,18 @@ static bool is_pl_valid(struct rapl_domain *rd, int pl)
117117
return rd->rpl[pl].name ? true : false;
118118
}
119119

120-
static int get_pl_prim(int pl, enum pl_prims prim)
120+
static int get_pl_lock_prim(struct rapl_domain *rd, int pl)
121+
{
122+
/*
123+
* Power Limit register that supports two power limits has a different
124+
* bit position for the Lock bit.
125+
*/
126+
if (rd->rp->priv->limits[rd->id] & BIT(POWER_LIMIT2))
127+
return FW_HIGH_LOCK;
128+
return FW_LOCK;
129+
}
130+
131+
static int get_pl_prim(struct rapl_domain *rd, int pl, enum pl_prims prim)
121132
{
122133
switch (pl) {
123134
case POWER_LIMIT1:
@@ -131,6 +142,8 @@ static int get_pl_prim(int pl, enum pl_prims prim)
131142
return TIME_WINDOW1;
132143
if (prim == PL_MAX_POWER)
133144
return THERMAL_SPEC_POWER;
145+
if (prim == PL_LOCK)
146+
return get_pl_lock_prim(rd, pl);
134147
return -EINVAL;
135148
case POWER_LIMIT2:
136149
if (prim == PL_ENABLE)
@@ -143,6 +156,8 @@ static int get_pl_prim(int pl, enum pl_prims prim)
143156
return TIME_WINDOW2;
144157
if (prim == PL_MAX_POWER)
145158
return MAX_POWER;
159+
if (prim == PL_LOCK)
160+
return get_pl_lock_prim(rd, pl);
146161
return -EINVAL;
147162
case POWER_LIMIT4:
148163
if (prim == PL_LIMIT)
@@ -314,7 +329,7 @@ static int get_domain_enable(struct powercap_zone *power_zone, bool *mode)
314329
u64 val;
315330
int ret;
316331

317-
if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
332+
if (rd->rpl[POWER_LIMIT1].locked) {
318333
*mode = false;
319334
return 0;
320335
}
@@ -599,6 +614,8 @@ static struct rapl_primitive_info rpi_default[NR_RAPL_PRIMITIVES] = {
599614
RAPL_DOMAIN_REG_STATUS, ENERGY_UNIT, 0),
600615
[FW_LOCK] = PRIMITIVE_INFO_INIT(FW_LOCK, POWER_LOW_LOCK, 31,
601616
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
617+
[FW_HIGH_LOCK] = PRIMITIVE_INFO_INIT(FW_LOCK, POWER_HIGH_LOCK, 63,
618+
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
602619
[PL1_ENABLE] = PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15,
603620
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
604621
[PL1_CLAMP] = PRIMITIVE_INFO_INIT(PL1_CLAMP, POWER_LIMIT1_CLAMP, 16,
@@ -719,11 +736,6 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
719736

720737
cpu = rd->rp->lead_cpu;
721738

722-
/* domain with 2 limits has different bit */
723-
if (prim == FW_LOCK && (rd->rp->priv->limits[rd->id] & BIT(POWER_LIMIT2))) {
724-
rpi->mask = POWER_HIGH_LOCK;
725-
rpi->shift = 63;
726-
}
727739
/* non-hardware data are collected by the polling thread */
728740
if (rpi->flag & RAPL_PRIMITIVE_DERIVED) {
729741
*data = rd->rdd.primitives[prim];
@@ -781,7 +793,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
781793
static int rapl_read_pl_data(struct rapl_domain *rd, int pl,
782794
enum pl_prims pl_prim, bool xlate, u64 *data)
783795
{
784-
enum rapl_primitives prim = get_pl_prim(pl, pl_prim);
796+
enum rapl_primitives prim = get_pl_prim(rd, pl, pl_prim);
785797

786798
if (!is_pl_valid(rd, pl))
787799
return -EINVAL;
@@ -793,12 +805,12 @@ static int rapl_write_pl_data(struct rapl_domain *rd, int pl,
793805
enum pl_prims pl_prim,
794806
unsigned long long value)
795807
{
796-
enum rapl_primitives prim = get_pl_prim(pl, pl_prim);
808+
enum rapl_primitives prim = get_pl_prim(rd, pl, pl_prim);
797809

798810
if (!is_pl_valid(rd, pl))
799811
return -EINVAL;
800812

801-
if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
813+
if (rd->rpl[pl].locked) {
802814
pr_warn("%s:%s:%s locked by BIOS\n", rd->rp->name, rd->name, pl_names[pl]);
803815
return -EACCES;
804816
}
@@ -1305,17 +1317,15 @@ static void rapl_detect_powerlimit(struct rapl_domain *rd)
13051317
u64 val64;
13061318
int i;
13071319

1308-
/* check if the domain is locked by BIOS, ignore if MSR doesn't exist */
1309-
if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) {
1310-
if (val64) {
1311-
pr_info("RAPL %s domain %s locked by BIOS\n",
1312-
rd->rp->name, rd->name);
1313-
rd->state |= DOMAIN_STATE_BIOS_LOCKED;
1320+
for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++) {
1321+
if (!rapl_read_pl_data(rd, i, PL_LOCK, false, &val64)) {
1322+
if (val64) {
1323+
rd->rpl[i].locked = true;
1324+
pr_info("%s:%s:%s locked by BIOS\n",
1325+
rd->rp->name, rd->name, pl_names[i]);
1326+
}
13141327
}
1315-
}
13161328

1317-
/* check if power limit exists, otherwise domain is monitoring only */
1318-
for (i = POWER_LIMIT1; i < NR_POWER_LIMITS; i++) {
13191329
if (rapl_read_pl_data(rd, i, PL_ENABLE, false, &val64))
13201330
rd->rpl[i].name = NULL;
13211331
}

include/linux/intel_rapl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum rapl_primitives {
4242
POWER_LIMIT4,
4343
ENERGY_COUNTER,
4444
FW_LOCK,
45+
FW_HIGH_LOCK,
4546

4647
PL1_ENABLE, /* power limit 1, aka long term */
4748
PL1_CLAMP, /* allow frequency to go below OS request */
@@ -81,6 +82,7 @@ struct rapl_power_limit {
8182
struct powercap_zone_constraint *constraint;
8283
struct rapl_domain *domain;
8384
const char *name;
85+
bool locked;
8486
u64 last_power_limit;
8587
};
8688

0 commit comments

Comments
 (0)