intel_rapl: support two power limits for every RAPL domain
authorZhang Rui <rui.zhang@intel.com>
Wed, 10 Jul 2019 13:44:32 +0000 (21:44 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 11 Jul 2019 13:08:58 +0000 (15:08 +0200)
RAPL MSR interface supports 2 power limits for package domain, and 1 power
limit for other domains, while RAPL MMIO interface supports 2 power limits
for both package and dram domains.
And when 2 power limits are supported, the FW_LOCK bit is in bit 63 of the
register, instead of bit 31.

Remove the assumption that only pakcage domain supports 2 power limits.
And allow the RAPL interface driver to specify the number of power limits
supported, for every single RAPL domain it owns..

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_common.c
drivers/powercap/intel_rapl_msr.c
include/linux/intel_rapl.h

index 8e4de036f6d0453d0435c209223089da232c2e5e..db8df19d8133fe31bff2131b6d4ee369d77af95d 100644 (file)
@@ -38,8 +38,8 @@
 #define POWER_LIMIT2_MASK       (0x7FFFULL<<32)
 #define POWER_LIMIT2_ENABLE     BIT_ULL(47)
 #define POWER_LIMIT2_CLAMP      BIT_ULL(48)
-#define POWER_PACKAGE_LOCK      BIT_ULL(63)
-#define POWER_PP_LOCK           BIT(31)
+#define POWER_HIGH_LOCK         BIT_ULL(63)
+#define POWER_LOW_LOCK          BIT(31)
 
 #define TIME_WINDOW1_MASK       (0x7FULL<<17)
 #define TIME_WINDOW2_MASK       (0x7FULL<<49)
@@ -513,60 +513,38 @@ static const struct powercap_zone_constraint_ops constraint_ops = {
 /* called after domain detection and package level data are set */
 static void rapl_init_domains(struct rapl_package *rp)
 {
-       int i;
+       enum rapl_domain_type i;
+       enum rapl_domain_reg_id j;
        struct rapl_domain *rd = rp->domains;
 
        for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
                unsigned int mask = rp->domain_map & (1 << i);
 
-               rd->regs[RAPL_DOMAIN_REG_LIMIT] =
-                   rp->priv->regs[i][RAPL_DOMAIN_REG_LIMIT];
-               rd->regs[RAPL_DOMAIN_REG_STATUS] =
-                   rp->priv->regs[i][RAPL_DOMAIN_REG_STATUS];
-               rd->regs[RAPL_DOMAIN_REG_PERF] =
-                   rp->priv->regs[i][RAPL_DOMAIN_REG_PERF];
-               rd->regs[RAPL_DOMAIN_REG_POLICY] =
-                   rp->priv->regs[i][RAPL_DOMAIN_REG_POLICY];
-               rd->regs[RAPL_DOMAIN_REG_INFO] =
-                   rp->priv->regs[i][RAPL_DOMAIN_REG_INFO];
-
-               switch (mask) {
-               case BIT(RAPL_DOMAIN_PACKAGE):
-                       rd->name = rapl_domain_names[RAPL_DOMAIN_PACKAGE];
-                       rd->id = RAPL_DOMAIN_PACKAGE;
-                       rd->rpl[0].prim_id = PL1_ENABLE;
-                       rd->rpl[0].name = pl1_name;
+               if (!mask)
+                       continue;
+
+               rd->rp = rp;
+               rd->name = rapl_domain_names[i];
+               rd->id = i;
+               rd->rpl[0].prim_id = PL1_ENABLE;
+               rd->rpl[0].name = pl1_name;
+               /* some domain may support two power limits */
+               if (rp->priv->limits[i] == 2) {
                        rd->rpl[1].prim_id = PL2_ENABLE;
                        rd->rpl[1].name = pl2_name;
-                       break;
-               case BIT(RAPL_DOMAIN_PP0):
-                       rd->name = rapl_domain_names[RAPL_DOMAIN_PP0];
-                       rd->id = RAPL_DOMAIN_PP0;
-                       rd->rpl[0].prim_id = PL1_ENABLE;
-                       rd->rpl[0].name = pl1_name;
-                       break;
-               case BIT(RAPL_DOMAIN_PP1):
-                       rd->name = rapl_domain_names[RAPL_DOMAIN_PP1];
-                       rd->id = RAPL_DOMAIN_PP1;
-                       rd->rpl[0].prim_id = PL1_ENABLE;
-                       rd->rpl[0].name = pl1_name;
-                       break;
-               case BIT(RAPL_DOMAIN_DRAM):
-                       rd->name = rapl_domain_names[RAPL_DOMAIN_DRAM];
-                       rd->id = RAPL_DOMAIN_DRAM;
-                       rd->rpl[0].prim_id = PL1_ENABLE;
-                       rd->rpl[0].name = pl1_name;
+               }
+
+               for (j = 0; j < RAPL_DOMAIN_REG_MAX; j++)
+                       rd->regs[j] = rp->priv->regs[i][j];
+
+               if (i == RAPL_DOMAIN_DRAM) {
                        rd->domain_energy_unit =
                            rapl_defaults->dram_domain_energy_unit;
                        if (rd->domain_energy_unit)
                                pr_info("DRAM domain energy unit %dpj\n",
                                        rd->domain_energy_unit);
-                       break;
-               }
-               if (mask) {
-                       rd->rp = rp;
-                       rd++;
                }
+               rd++;
        }
 }
 
@@ -613,7 +591,7 @@ static struct rapl_primitive_info rpi[] = {
                            RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
        PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32,
                            RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
-       PRIMITIVE_INFO_INIT(FW_LOCK, POWER_PP_LOCK, 31,
+       PRIMITIVE_INFO_INIT(FW_LOCK, POWER_LOW_LOCK, 31,
                            RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
        PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15,
                            RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
@@ -675,9 +653,9 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
 
        cpu = rd->rp->lead_cpu;
 
-       /* special-case package domain, which uses a different bit */
-       if (prim == FW_LOCK && rd->id == RAPL_DOMAIN_PACKAGE) {
-               rp->mask = POWER_PACKAGE_LOCK;
+       /* domain with 2 limits has different bit */
+       if (prim == FW_LOCK && rd->rp->priv->limits[rd->id] == 2) {
+               rp->mask = POWER_HIGH_LOCK;
                rp->shift = 63;
        }
        /* non-hardware data are collected by the polling thread */
index 6cd8a8fb9238ba0afb4db8f98cfb0b8780d511f4..bc14a4579acb82f7e0e7dc6aa8ef9032a51abfdf 100644 (file)
@@ -41,6 +41,7 @@ static struct rapl_if_priv rapl_msr_priv = {
                MSR_DRAM_POWER_LIMIT, MSR_DRAM_ENERGY_STATUS, MSR_DRAM_PERF_STATUS, 0, MSR_DRAM_POWER_INFO },
        .regs[RAPL_DOMAIN_PLATFORM] = {
                MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0},
+       .limits[RAPL_DOMAIN_PACKAGE] = 2,
 };
 
 /* Handles CPU hotplug on multi-socket systems.
index 649e19981eb0f350ebe5aa2f521db13a18a81153..0c179d92d11068528dacc2891bbed5910e81c109 100644 (file)
@@ -104,6 +104,7 @@ struct reg_action {
  * @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.
+ * @limits:                    Number of power limits supported by each domain.
  * @read_raw:                  Callback for reading RAPL interface specific
  *                             registers.
  * @write_raw:                 Callback for writing RAPL interface specific
@@ -115,6 +116,7 @@ struct rapl_if_priv {
        enum cpuhp_state pcap_rapl_online;
        u64 reg_unit;
        u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX];
+       int limits[RAPL_DOMAIN_MAX];
        int (*read_raw)(int cpu, struct reg_action *ra);
        int (*write_raw)(int cpu, struct reg_action *ra);
 };