提交 e2590cd6 编写于 作者: Z Zhang Rui 提交者: Caspar Zhang

ICX: intel_rapl: abstract register access operations

commit beea8df821d928e7755917da6c1e45d6afde5148 upstream.

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: NPandruvada, Srinivas <srinivas.pandruvada@intel.com>
Tested-by: NPandruvada, Srinivas <srinivas.pandruvada@intel.com>
Signed-off-by: NZhang Rui <rui.zhang@intel.com>
Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: NYouquan Song <youquan.song@intel.com>
Signed-off-by: NJeffle Xu <jefflexu@linux.alibaba.com>
Acked-by: NJoseph Qi <joseph.qi@linux.alibaba.com>
Acked-by: NCaspar Zhang <caspar@linux.alibaba.com>
上级 4d3d37d1
......@@ -105,13 +105,6 @@ static struct rapl_if_priv rapl_msr_priv = {
/* per domain data, some are optional */
#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_POWER_LIMIT_SET BIT(1)
#define DOMAIN_STATE_BIOS_LOCKED BIT(2)
......@@ -704,16 +697,16 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
enum rapl_primitives prim,
bool xlate, u64 *data)
{
u64 value, final;
u32 msr;
u64 value;
struct rapl_primitive_info *rp = &rpi[prim];
struct reg_action ra;
int cpu;
if (!rp->name || rp->flag & RAPL_PRIMITIVE_DUMMY)
return -EINVAL;
msr = rd->regs[rp->id];
if (!msr)
ra.reg = rd->regs[rp->id];
if (!ra.reg)
return -EINVAL;
cpu = rd->rp->lead_cpu;
......@@ -729,47 +722,23 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
return 0;
}
if (rdmsrl_safe_on_cpu(cpu, msr, &value)) {
pr_debug("failed to read msr 0x%x on cpu %d\n", msr, cpu);
ra.mask = rp->mask;
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;
}
final = value & rp->mask;
final = final >> rp->shift;
value = ra.value >> rp->shift;
if (xlate)
*data = rapl_unit_xlate(rd, rp->unit, final, 0);
*data = rapl_unit_xlate(rd, rp->unit, value, 0);
else
*data = final;
*data = value;
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 */
static int rapl_write_data_raw(struct rapl_domain *rd,
enum rapl_primitives prim,
......@@ -778,7 +747,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
struct rapl_primitive_info *rp = &rpi[prim];
int cpu;
u64 bits;
struct msrl_action ma;
struct reg_action ra;
int ret;
cpu = rd->rp->lead_cpu;
......@@ -786,17 +755,13 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
bits <<= rp->shift;
bits &= rp->mask;
memset(&ma, 0, sizeof(ma));
memset(&ra, 0, sizeof(ra));
ma.msr_no = rd->regs[rp->id];
ma.clear_mask = rp->mask;
ma.set_mask = bits;
ra.reg = rd->regs[rp->id];
ra.mask = rp->mask;
ra.value = bits;
ret = smp_call_function_single(cpu, msrl_update_func, &ma, 1);
if (ret)
WARN_ON_ONCE(ret);
else
ret = ma.err;
ret = rd->rp->priv->write_raw(cpu, &ra);
return ret;
}
......@@ -1524,6 +1489,43 @@ static struct notifier_block rapl_pm_notifier = {
.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)
{
const struct x86_cpu_id *id;
......@@ -1539,6 +1541,8 @@ static int __init rapl_init(void)
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();
if (ret)
return ret;
......
......@@ -88,6 +88,13 @@ struct rapl_domain {
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
* @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.
* @reg_unit: Register for getting energy/power/time unit.
* @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 powercap_control_type *control_type;
......@@ -104,6 +115,8 @@ struct rapl_if_priv {
enum cpuhp_state pcap_rapl_online;
u32 reg_unit;
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 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册