Re: [PATCH v2] powercap/rapl: handle domain energy unit

2015-03-13 Thread Rafael J. Wysocki
On Friday, March 13, 2015 03:48:56 AM Jacob Pan wrote:
> The current driver assumes all RAPL domains within a CPU package
> have the same energy unit. This is no longer true for HSW server
> CPUs since DRAM domain has is own fixed energy unit which can be
> different than the package energy unit enumerated by package
> power MSR. In fact, the default HSW EP package power unit is 61uJ
> whereas DRAM domain unit is 15.3uJ. The result is that DRAM power
> consumption is counted 4x more than real power reported by energy
> counters, similarly for max_energy_range_uj of DRAM domain.
> 
> This patch adds domain specific energy unit per cpu type, it allows
> domain energy unit to override package energy unit if non zero.
> 
> Please see this document for details.
> "Intel Xeon Processor E5-1600 and E5-2600 v3 Product Families, Volume 2
> of 2. Datasheet, September 2014, Reference Number: 330784-001 "
> 
> Signed-off-by: Jacob Pan 

Queued up this one for 4.0-rc5, thanks!

> ---
>  drivers/powercap/intel_rapl.c | 54 
> +++
>  1 file changed, 39 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
> index 97b5e4e..63d4033 100644
> --- a/drivers/powercap/intel_rapl.c
> +++ b/drivers/powercap/intel_rapl.c
> @@ -73,7 +73,7 @@
>  
>  #define TIME_WINDOW_MAX_MSEC 4
>  #define TIME_WINDOW_MIN_MSEC 250
> -
> +#define ENERGY_UNIT_SCALE1000 /* scale from driver unit to powercap unit 
> */
>  enum unit_type {
>   ARBITRARY_UNIT, /* no translation */
>   POWER_UNIT,
> @@ -158,6 +158,7 @@ struct rapl_domain {
>   struct rapl_power_limit rpl[NR_POWER_LIMITS];
>   u64 attr_map; /* track capabilities */
>   unsigned int state;
> + unsigned int domain_energy_unit;
>   int package_id;
>  };
>  #define power_zone_to_rapl_domain(_zone) \
> @@ -190,6 +191,7 @@ struct rapl_defaults {
>   void (*set_floor_freq)(struct rapl_domain *rd, bool mode);
>   u64 (*compute_time_window)(struct rapl_package *rp, u64 val,
>   bool to_raw);
> + unsigned int dram_domain_energy_unit;
>  };
>  static struct rapl_defaults *rapl_defaults;
>  
> @@ -227,7 +229,8 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
>  static int rapl_write_data_raw(struct rapl_domain *rd,
>   enum rapl_primitives prim,
>   unsigned long long value);
> -static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
> +static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
> + enum unit_type type, u64 value,
>   int to_raw);
>  static void package_power_limit_irq_save(int package_id);
>  
> @@ -305,7 +308,9 @@ static int get_energy_counter(struct powercap_zone 
> *power_zone, u64 *energy_raw)
>  
>  static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy)
>  {
> - *energy = rapl_unit_xlate(0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
> + struct rapl_domain *rd = power_zone_to_rapl_domain(pcd_dev);
> +
> + *energy = rapl_unit_xlate(rd, 0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
>   return 0;
>  }
>  
> @@ -639,6 +644,11 @@ static void rapl_init_domains(struct rapl_package *rp)
>   rd->msrs[4] = MSR_DRAM_POWER_INFO;
>   rd->rpl[0].prim_id = PL1_ENABLE;
>   rd->rpl[0].name = pl1_name;
> + 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) {
> @@ -648,11 +658,13 @@ static void rapl_init_domains(struct rapl_package *rp)
>   }
>  }
>  
> -static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
> +static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
> + enum unit_type type, u64 value,
>   int to_raw)
>  {
>   u64 units = 1;
>   struct rapl_package *rp;
> + u64 scale = 1;
>  
>   rp = find_package_by_id(package);
>   if (!rp)
> @@ -663,7 +675,12 @@ static u64 rapl_unit_xlate(int package, enum unit_type 
> type, u64 value,
>   units = rp->power_unit;
>   break;
>   case ENERGY_UNIT:
> - units = rp->energy_unit;
> + scale = ENERGY_UNIT_SCALE;
> + /* per domain unit takes precedence */
> + if (rd && rd->domain_energy_unit)
> + units = rd->domain_energy_unit;
> + else
> + units = rp->energy_unit;
>   break;
>   case TIME_UNIT:
>   return rapl_defaults->compute_time_window(rp, value, to_raw);
> @@ -673,11 +690,11 @@ static u64 rapl_unit_xlate(int package, enum u

[PATCH v2] powercap/rapl: handle domain energy unit

2015-03-13 Thread Jacob Pan
The current driver assumes all RAPL domains within a CPU package
have the same energy unit. This is no longer true for HSW server
CPUs since DRAM domain has is own fixed energy unit which can be
different than the package energy unit enumerated by package
power MSR. In fact, the default HSW EP package power unit is 61uJ
whereas DRAM domain unit is 15.3uJ. The result is that DRAM power
consumption is counted 4x more than real power reported by energy
counters, similarly for max_energy_range_uj of DRAM domain.

This patch adds domain specific energy unit per cpu type, it allows
domain energy unit to override package energy unit if non zero.

Please see this document for details.
"Intel Xeon Processor E5-1600 and E5-2600 v3 Product Families, Volume 2
of 2. Datasheet, September 2014, Reference Number: 330784-001 "

Signed-off-by: Jacob Pan 
---
 drivers/powercap/intel_rapl.c | 54 +++
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 97b5e4e..63d4033 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -73,7 +73,7 @@
 
 #define TIME_WINDOW_MAX_MSEC 4
 #define TIME_WINDOW_MIN_MSEC 250
-
+#define ENERGY_UNIT_SCALE1000 /* scale from driver unit to powercap unit */
 enum unit_type {
ARBITRARY_UNIT, /* no translation */
POWER_UNIT,
@@ -158,6 +158,7 @@ struct rapl_domain {
struct rapl_power_limit rpl[NR_POWER_LIMITS];
u64 attr_map; /* track capabilities */
unsigned int state;
+   unsigned int domain_energy_unit;
int package_id;
 };
 #define power_zone_to_rapl_domain(_zone) \
@@ -190,6 +191,7 @@ struct rapl_defaults {
void (*set_floor_freq)(struct rapl_domain *rd, bool mode);
u64 (*compute_time_window)(struct rapl_package *rp, u64 val,
bool to_raw);
+   unsigned int dram_domain_energy_unit;
 };
 static struct rapl_defaults *rapl_defaults;
 
@@ -227,7 +229,8 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
 static int rapl_write_data_raw(struct rapl_domain *rd,
enum rapl_primitives prim,
unsigned long long value);
-static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
+   enum unit_type type, u64 value,
int to_raw);
 static void package_power_limit_irq_save(int package_id);
 
@@ -305,7 +308,9 @@ static int get_energy_counter(struct powercap_zone 
*power_zone, u64 *energy_raw)
 
 static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy)
 {
-   *energy = rapl_unit_xlate(0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
+   struct rapl_domain *rd = power_zone_to_rapl_domain(pcd_dev);
+
+   *energy = rapl_unit_xlate(rd, 0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
return 0;
 }
 
@@ -639,6 +644,11 @@ static void rapl_init_domains(struct rapl_package *rp)
rd->msrs[4] = MSR_DRAM_POWER_INFO;
rd->rpl[0].prim_id = PL1_ENABLE;
rd->rpl[0].name = pl1_name;
+   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) {
@@ -648,11 +658,13 @@ static void rapl_init_domains(struct rapl_package *rp)
}
 }
 
-static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
+   enum unit_type type, u64 value,
int to_raw)
 {
u64 units = 1;
struct rapl_package *rp;
+   u64 scale = 1;
 
rp = find_package_by_id(package);
if (!rp)
@@ -663,7 +675,12 @@ static u64 rapl_unit_xlate(int package, enum unit_type 
type, u64 value,
units = rp->power_unit;
break;
case ENERGY_UNIT:
-   units = rp->energy_unit;
+   scale = ENERGY_UNIT_SCALE;
+   /* per domain unit takes precedence */
+   if (rd && rd->domain_energy_unit)
+   units = rd->domain_energy_unit;
+   else
+   units = rp->energy_unit;
break;
case TIME_UNIT:
return rapl_defaults->compute_time_window(rp, value, to_raw);
@@ -673,11 +690,11 @@ static u64 rapl_unit_xlate(int package, enum unit_type 
type, u64 value,
};
 
if (to_raw)
-   return div64_u64(value, units);
+   return div64_u64(value, units) * scale;
 
value *= units;
 
-   return value;
+   return di