intel_rapl: abstract register access operations
authorZhang Rui <rui.zhang@intel.com>
Wed, 10 Jul 2019 13:44:27 +0000 (21:44 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 11 Jul 2019 13:08:57 +0000 (15:08 +0200)
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>
drivers/powercap/intel_rapl.c
include/linux/intel_rapl.h

index 9f22aed49f24d61aea68df6a9faac32a3a4f45b4..d3b9d1cf4d48f0829e9a104b84fd441bd9383d77 100644 (file)
@@ -93,13 +93,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)
@@ -692,16 +685,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;
@@ -717,47 +710,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,
@@ -766,7 +735,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;
@@ -774,17 +743,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;
 }
@@ -1507,6 +1472,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;
@@ -1522,6 +1524,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;
index ec2c9e83274fe85c4b0e5cbe0007289dc5bf8740..ff215d64d1149a0a9ec113aea3a61ca0bd590164 100644 (file)
@@ -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 */