mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-06 22:58:29 +00:00
intel_rapl: abstract register access operations
MSR and MMIO RAPL interfaces have different ways to access the registers, thus in order to abstract the register access operations, two callbacks, .read_raw()/.write_raw() are introduced, and they should be implemented by MSR RAPL and MMIO RAPL interface driver respectly. This patch implements them for the MSR I/F only. Reviewed-by: Pandruvada, Srinivas <srinivas.pandruvada@intel.com> Tested-by: Pandruvada, Srinivas <srinivas.pandruvada@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
7fde2712a7
commit
beea8df821
2 changed files with 70 additions and 53 deletions
|
@ -93,13 +93,6 @@ static struct rapl_if_priv rapl_msr_priv = {
|
||||||
/* per domain data, some are optional */
|
/* per domain data, some are optional */
|
||||||
#define NR_RAW_PRIMITIVES (NR_RAPL_PRIMITIVES - 2)
|
#define NR_RAW_PRIMITIVES (NR_RAPL_PRIMITIVES - 2)
|
||||||
|
|
||||||
struct msrl_action {
|
|
||||||
u32 msr_no;
|
|
||||||
u64 clear_mask;
|
|
||||||
u64 set_mask;
|
|
||||||
int err;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DOMAIN_STATE_INACTIVE BIT(0)
|
#define DOMAIN_STATE_INACTIVE BIT(0)
|
||||||
#define DOMAIN_STATE_POWER_LIMIT_SET BIT(1)
|
#define DOMAIN_STATE_POWER_LIMIT_SET BIT(1)
|
||||||
#define DOMAIN_STATE_BIOS_LOCKED BIT(2)
|
#define DOMAIN_STATE_BIOS_LOCKED BIT(2)
|
||||||
|
@ -692,16 +685,16 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
|
||||||
enum rapl_primitives prim,
|
enum rapl_primitives prim,
|
||||||
bool xlate, u64 *data)
|
bool xlate, u64 *data)
|
||||||
{
|
{
|
||||||
u64 value, final;
|
u64 value;
|
||||||
u32 msr;
|
|
||||||
struct rapl_primitive_info *rp = &rpi[prim];
|
struct rapl_primitive_info *rp = &rpi[prim];
|
||||||
|
struct reg_action ra;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
if (!rp->name || rp->flag & RAPL_PRIMITIVE_DUMMY)
|
if (!rp->name || rp->flag & RAPL_PRIMITIVE_DUMMY)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
msr = rd->regs[rp->id];
|
ra.reg = rd->regs[rp->id];
|
||||||
if (!msr)
|
if (!ra.reg)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
cpu = rd->rp->lead_cpu;
|
cpu = rd->rp->lead_cpu;
|
||||||
|
@ -717,47 +710,23 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rdmsrl_safe_on_cpu(cpu, msr, &value)) {
|
ra.mask = rp->mask;
|
||||||
pr_debug("failed to read msr 0x%x on cpu %d\n", msr, cpu);
|
|
||||||
|
if (rd->rp->priv->read_raw(cpu, &ra)) {
|
||||||
|
pr_debug("failed to read reg 0x%x on cpu %d\n", ra.reg, cpu);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
final = value & rp->mask;
|
value = ra.value >> rp->shift;
|
||||||
final = final >> rp->shift;
|
|
||||||
if (xlate)
|
if (xlate)
|
||||||
*data = rapl_unit_xlate(rd, rp->unit, final, 0);
|
*data = rapl_unit_xlate(rd, rp->unit, value, 0);
|
||||||
else
|
else
|
||||||
*data = final;
|
*data = value;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int msrl_update_safe(u32 msr_no, u64 clear_mask, u64 set_mask)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
u64 val;
|
|
||||||
|
|
||||||
err = rdmsrl_safe(msr_no, &val);
|
|
||||||
if (err)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
val &= ~clear_mask;
|
|
||||||
val |= set_mask;
|
|
||||||
|
|
||||||
err = wrmsrl_safe(msr_no, val);
|
|
||||||
|
|
||||||
out:
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msrl_update_func(void *info)
|
|
||||||
{
|
|
||||||
struct msrl_action *ma = info;
|
|
||||||
|
|
||||||
ma->err = msrl_update_safe(ma->msr_no, ma->clear_mask, ma->set_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Similar use of primitive info in the read counterpart */
|
/* Similar use of primitive info in the read counterpart */
|
||||||
static int rapl_write_data_raw(struct rapl_domain *rd,
|
static int rapl_write_data_raw(struct rapl_domain *rd,
|
||||||
enum rapl_primitives prim,
|
enum rapl_primitives prim,
|
||||||
|
@ -766,7 +735,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
|
||||||
struct rapl_primitive_info *rp = &rpi[prim];
|
struct rapl_primitive_info *rp = &rpi[prim];
|
||||||
int cpu;
|
int cpu;
|
||||||
u64 bits;
|
u64 bits;
|
||||||
struct msrl_action ma;
|
struct reg_action ra;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cpu = rd->rp->lead_cpu;
|
cpu = rd->rp->lead_cpu;
|
||||||
|
@ -774,17 +743,13 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
|
||||||
bits <<= rp->shift;
|
bits <<= rp->shift;
|
||||||
bits &= rp->mask;
|
bits &= rp->mask;
|
||||||
|
|
||||||
memset(&ma, 0, sizeof(ma));
|
memset(&ra, 0, sizeof(ra));
|
||||||
|
|
||||||
ma.msr_no = rd->regs[rp->id];
|
ra.reg = rd->regs[rp->id];
|
||||||
ma.clear_mask = rp->mask;
|
ra.mask = rp->mask;
|
||||||
ma.set_mask = bits;
|
ra.value = bits;
|
||||||
|
|
||||||
ret = smp_call_function_single(cpu, msrl_update_func, &ma, 1);
|
ret = rd->rp->priv->write_raw(cpu, &ra);
|
||||||
if (ret)
|
|
||||||
WARN_ON_ONCE(ret);
|
|
||||||
else
|
|
||||||
ret = ma.err;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1507,6 +1472,43 @@ static struct notifier_block rapl_pm_notifier = {
|
||||||
.notifier_call = rapl_pm_callback,
|
.notifier_call = rapl_pm_callback,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int rapl_msr_read_raw(int cpu, struct reg_action *ra)
|
||||||
|
{
|
||||||
|
if (rdmsrl_safe_on_cpu(cpu, ra->reg, &ra->value)) {
|
||||||
|
pr_debug("failed to read msr 0x%x on cpu %d\n", ra->reg, cpu);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
ra->value &= ra->mask;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rapl_msr_update_func(void *info)
|
||||||
|
{
|
||||||
|
struct reg_action *ra = info;
|
||||||
|
u64 val;
|
||||||
|
|
||||||
|
ra->err = rdmsrl_safe(ra->reg, &val);
|
||||||
|
if (ra->err)
|
||||||
|
return;
|
||||||
|
|
||||||
|
val &= ~ra->mask;
|
||||||
|
val |= ra->value;
|
||||||
|
|
||||||
|
ra->err = wrmsrl_safe(ra->reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int rapl_msr_write_raw(int cpu, struct reg_action *ra)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = smp_call_function_single(cpu, rapl_msr_update_func, ra, 1);
|
||||||
|
if (WARN_ON_ONCE(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return ra->err;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init rapl_init(void)
|
static int __init rapl_init(void)
|
||||||
{
|
{
|
||||||
const struct x86_cpu_id *id;
|
const struct x86_cpu_id *id;
|
||||||
|
@ -1522,6 +1524,8 @@ static int __init rapl_init(void)
|
||||||
|
|
||||||
rapl_defaults = (struct rapl_defaults *)id->driver_data;
|
rapl_defaults = (struct rapl_defaults *)id->driver_data;
|
||||||
|
|
||||||
|
rapl_msr_priv.read_raw = rapl_msr_read_raw;
|
||||||
|
rapl_msr_priv.write_raw = rapl_msr_write_raw;
|
||||||
ret = rapl_register_powercap();
|
ret = rapl_register_powercap();
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -88,6 +88,13 @@ struct rapl_domain {
|
||||||
struct rapl_package *rp;
|
struct rapl_package *rp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct reg_action {
|
||||||
|
u32 reg;
|
||||||
|
u64 mask;
|
||||||
|
u64 value;
|
||||||
|
int err;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct rapl_if_priv: private data for different RAPL interfaces
|
* struct rapl_if_priv: private data for different RAPL interfaces
|
||||||
* @control_type: Each RAPL interface must have its own powercap
|
* @control_type: Each RAPL interface must have its own powercap
|
||||||
|
@ -97,6 +104,10 @@ struct rapl_domain {
|
||||||
* @pcap_rapl_online: CPU hotplug state for each RAPL interface.
|
* @pcap_rapl_online: CPU hotplug state for each RAPL interface.
|
||||||
* @reg_unit: Register for getting energy/power/time unit.
|
* @reg_unit: Register for getting energy/power/time unit.
|
||||||
* @regs: Register sets for different RAPL Domains.
|
* @regs: Register sets for different RAPL Domains.
|
||||||
|
* @read_raw: Callback for reading RAPL interface specific
|
||||||
|
* registers.
|
||||||
|
* @write_raw: Callback for writing RAPL interface specific
|
||||||
|
* registers.
|
||||||
*/
|
*/
|
||||||
struct rapl_if_priv {
|
struct rapl_if_priv {
|
||||||
struct powercap_control_type *control_type;
|
struct powercap_control_type *control_type;
|
||||||
|
@ -104,6 +115,8 @@ struct rapl_if_priv {
|
||||||
enum cpuhp_state pcap_rapl_online;
|
enum cpuhp_state pcap_rapl_online;
|
||||||
u32 reg_unit;
|
u32 reg_unit;
|
||||||
u32 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX];
|
u32 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX];
|
||||||
|
int (*read_raw)(int cpu, struct reg_action *ra);
|
||||||
|
int (*write_raw)(int cpu, struct reg_action *ra);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* maximum rapl package domain name: package-%d-die-%d */
|
/* maximum rapl package domain name: package-%d-die-%d */
|
||||||
|
|
Loading…
Add table
Reference in a new issue