diff mbox

[7/7] drm/i915: expose energy counter on SNB and IVB

Message ID 1346964850-2228-8-git-send-email-ben@bwidawsk.net (mailing list archive)
State Rejected
Delegated to: Jesse Barnes
Headers show

Commit Message

Ben Widawsky Sept. 6, 2012, 8:54 p.m. UTC
From: Jesse Barnes <jbarnes@virtuousgeek.org>

On SNB and IVB, there's an MSR (also exposed through MCHBAR) we can use
to read out the amount of energy used over time.  Expose this in sysfs
to make it easy to do power comparisons with different configurations.

If the platform supports it, the file will show up under the
drm/card0/power subdirectory of the PCI device in sysfs as gt_energy_uJ.
The value in the file is a running total of energy (in microjoules)
consumed by the graphics device.

v2: move to sysfs (Ben, Daniel)
    expose a simple value (Chris)
    drop unrelated hunk (Ben)

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

v3: by Ben
Tied it into existing rc6  sysfs entries and named that a more generic
"power attrs." Fixed rebase conflicts.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_reg.h   |  2 ++
 drivers/gpu/drm/i915/i915_sysfs.c | 25 +++++++++++++++++++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

Comments

Daniel Vetter Sept. 7, 2012, 10:03 a.m. UTC | #1
On Thu, Sep 06, 2012 at 01:54:10PM -0700, Ben Widawsky wrote:
> From: Jesse Barnes <jbarnes@virtuousgeek.org>
> 
> On SNB and IVB, there's an MSR (also exposed through MCHBAR) we can use
> to read out the amount of energy used over time.  Expose this in sysfs
> to make it easy to do power comparisons with different configurations.
> 
> If the platform supports it, the file will show up under the
> drm/card0/power subdirectory of the PCI device in sysfs as gt_energy_uJ.
> The value in the file is a running total of energy (in microjoules)
> consumed by the graphics device.
> 
> v2: move to sysfs (Ben, Daniel)
>     expose a simple value (Chris)
>     drop unrelated hunk (Ben)
> 
> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 
> v3: by Ben
> Tied it into existing rc6  sysfs entries and named that a more generic
> "power attrs." Fixed rebase conflicts.
> 
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/i915_reg.h   |  2 ++
>  drivers/gpu/drm/i915/i915_sysfs.c | 25 +++++++++++++++++++++++--
>  2 files changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index d0b60f2..0e34f5f 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1242,6 +1242,8 @@
>  #define CLKCFG_MEM_800					(3 << 4)
>  #define CLKCFG_MEM_MASK					(7 << 4)
>  
> +#define SECP_NRG_STTS			(MCHBAR_MIRROR_BASE_SNB + 0x592c)
> +
>  #define TSC1			0x11001
>  #define   TSE			(1<<0)
>  #define TR1			0x11006
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index e3a31ae..6bbc9af 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -76,22 +76,43 @@ show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf)
>  	return snprintf(buf, PAGE_SIZE, "%u", rc6pp_residency);
>  }
>  
> +#define MSR_IA32_PACKAGE_POWER_SKU_UNIT		0x00000606
> +
> +static ssize_t
> +show_gt_energy_uJ(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> +	struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
> +	struct drm_i915_private *dev_priv = dminor->dev->dev_private;
> +	u64 ppsu;
> +	u32 val, units;
> +
> +	rdmsrl(MSR_IA32_PACKAGE_POWER_SKU_UNIT, ppsu);
> +
> +	ppsu = (ppsu & 0x1f00) >> 8;
> +	units = 1000000 / (1 << ppsu); /* convert to uJ */
> +	val = I915_READ(SECP_NRG_STTS);
> +
> +	return snprintf(buf, PAGE_SIZE, "%u", val * units);

Besides that this could overflow it also introduces rounding errors that
accumulate. I guess we need a 64 mul+div here, like in the residency
counters.
-Daniel

> +}
> +
>  static DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL);
>  static DEVICE_ATTR(rc6_residency_ms, S_IRUGO, show_rc6_ms, NULL);
>  static DEVICE_ATTR(rc6p_residency_ms, S_IRUGO, show_rc6p_ms, NULL);
>  static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL);
> +static DEVICE_ATTR(gt_energy_uJ, S_IRUGO, show_gt_energy_uJ, NULL);
>  
> -static struct attribute *rc6_attrs[] = {
> +static struct attribute *power_attrs[] = {
>  	&dev_attr_rc6_enable.attr,
>  	&dev_attr_rc6_residency_ms.attr,
>  	&dev_attr_rc6p_residency_ms.attr,
>  	&dev_attr_rc6pp_residency_ms.attr,
> +	&dev_attr_gt_energy_uJ.attr,
>  	NULL
>  };
>  
>  static struct attribute_group rc6_attr_group = {
>  	.name = power_group_name,
> -	.attrs =  rc6_attrs
> +	.attrs =  power_attrs
>  };
>  #endif
>  
> -- 
> 1.7.12
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ben Widawsky Sept. 7, 2012, 5:51 p.m. UTC | #2
On Fri, 7 Sep 2012 12:03:37 +0200
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Thu, Sep 06, 2012 at 01:54:10PM -0700, Ben Widawsky wrote:
> > From: Jesse Barnes <jbarnes@virtuousgeek.org>
> > 
> > On SNB and IVB, there's an MSR (also exposed through MCHBAR) we can use
> > to read out the amount of energy used over time.  Expose this in sysfs
> > to make it easy to do power comparisons with different configurations.
> > 
> > If the platform supports it, the file will show up under the
> > drm/card0/power subdirectory of the PCI device in sysfs as gt_energy_uJ.
> > The value in the file is a running total of energy (in microjoules)
> > consumed by the graphics device.
> > 
> > v2: move to sysfs (Ben, Daniel)
> >     expose a simple value (Chris)
> >     drop unrelated hunk (Ben)
> > 
> > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> > 
> > v3: by Ben
> > Tied it into existing rc6  sysfs entries and named that a more generic
> > "power attrs." Fixed rebase conflicts.
> > 
> > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> > ---
> >  drivers/gpu/drm/i915/i915_reg.h   |  2 ++
> >  drivers/gpu/drm/i915/i915_sysfs.c | 25 +++++++++++++++++++++++--
> >  2 files changed, 25 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index d0b60f2..0e34f5f 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -1242,6 +1242,8 @@
> >  #define CLKCFG_MEM_800					(3 << 4)
> >  #define CLKCFG_MEM_MASK					(7 << 4)
> >  
> > +#define SECP_NRG_STTS			(MCHBAR_MIRROR_BASE_SNB + 0x592c)
> > +
> >  #define TSC1			0x11001
> >  #define   TSE			(1<<0)
> >  #define TR1			0x11006
> > diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> > index e3a31ae..6bbc9af 100644
> > --- a/drivers/gpu/drm/i915/i915_sysfs.c
> > +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> > @@ -76,22 +76,43 @@ show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf)
> >  	return snprintf(buf, PAGE_SIZE, "%u", rc6pp_residency);
> >  }
> >  
> > +#define MSR_IA32_PACKAGE_POWER_SKU_UNIT		0x00000606
> > +
> > +static ssize_t
> > +show_gt_energy_uJ(struct device *dev, struct device_attribute *attr, char *buf)
> > +{
> > +	struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
> > +	struct drm_i915_private *dev_priv = dminor->dev->dev_private;
> > +	u64 ppsu;
> > +	u32 val, units;
> > +
> > +	rdmsrl(MSR_IA32_PACKAGE_POWER_SKU_UNIT, ppsu);
> > +
> > +	ppsu = (ppsu & 0x1f00) >> 8;
> > +	units = 1000000 / (1 << ppsu); /* convert to uJ */
> > +	val = I915_READ(SECP_NRG_STTS);
> > +
> > +	return snprintf(buf, PAGE_SIZE, "%u", val * units);
> 
> Besides that this could overflow it also introduces rounding errors that
> accumulate. I guess we need a 64 mul+div here, like in the residency
> counters.
> -Daniel
> 

Jesse, I'm not fixing this one for you since I screwed up the residency
math enough times before.

> > +}
> > +
> >  static DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL);
> >  static DEVICE_ATTR(rc6_residency_ms, S_IRUGO, show_rc6_ms, NULL);
> >  static DEVICE_ATTR(rc6p_residency_ms, S_IRUGO, show_rc6p_ms, NULL);
> >  static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL);
> > +static DEVICE_ATTR(gt_energy_uJ, S_IRUGO, show_gt_energy_uJ, NULL);
> >  
> > -static struct attribute *rc6_attrs[] = {
> > +static struct attribute *power_attrs[] = {
> >  	&dev_attr_rc6_enable.attr,
> >  	&dev_attr_rc6_residency_ms.attr,
> >  	&dev_attr_rc6p_residency_ms.attr,
> >  	&dev_attr_rc6pp_residency_ms.attr,
> > +	&dev_attr_gt_energy_uJ.attr,
> >  	NULL
> >  };
> >  
> >  static struct attribute_group rc6_attr_group = {
> >  	.name = power_group_name,
> > -	.attrs =  rc6_attrs
> > +	.attrs =  power_attrs
> >  };
> >  #endif
> >  
> > -- 
> > 1.7.12
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
Chris Wilson April 10, 2013, 2:27 p.m. UTC | #3
On Fri, Sep 07, 2012 at 10:51:44AM -0700, Ben Widawsky wrote:
> On Fri, 7 Sep 2012 12:03:37 +0200
> Daniel Vetter <daniel@ffwll.ch> wrote:
> 
> > On Thu, Sep 06, 2012 at 01:54:10PM -0700, Ben Widawsky wrote:
> > > From: Jesse Barnes <jbarnes@virtuousgeek.org>
> > > 
> > > On SNB and IVB, there's an MSR (also exposed through MCHBAR) we can use
> > > to read out the amount of energy used over time.  Expose this in sysfs
> > > to make it easy to do power comparisons with different configurations.
> > > 
> > > If the platform supports it, the file will show up under the
> > > drm/card0/power subdirectory of the PCI device in sysfs as gt_energy_uJ.
> > > The value in the file is a running total of energy (in microjoules)
> > > consumed by the graphics device.
> > > 
> > > v2: move to sysfs (Ben, Daniel)
> > >     expose a simple value (Chris)
> > >     drop unrelated hunk (Ben)
> > > 
> > > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> > > 
> > > v3: by Ben
> > > Tied it into existing rc6  sysfs entries and named that a more generic
> > > "power attrs." Fixed rebase conflicts.
> > > 
> > > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>

A reminder that we never finished this patch.
-Chris
Ben Widawsky April 10, 2013, 7:13 p.m. UTC | #4
On Wed, Apr 10, 2013 at 03:27:05PM +0100, Chris Wilson wrote:
> On Fri, Sep 07, 2012 at 10:51:44AM -0700, Ben Widawsky wrote:
> > On Fri, 7 Sep 2012 12:03:37 +0200
> > Daniel Vetter <daniel@ffwll.ch> wrote:
> > 
> > > On Thu, Sep 06, 2012 at 01:54:10PM -0700, Ben Widawsky wrote:
> > > > From: Jesse Barnes <jbarnes@virtuousgeek.org>
> > > > 
> > > > On SNB and IVB, there's an MSR (also exposed through MCHBAR) we can use
> > > > to read out the amount of energy used over time.  Expose this in sysfs
> > > > to make it easy to do power comparisons with different configurations.
> > > > 
> > > > If the platform supports it, the file will show up under the
> > > > drm/card0/power subdirectory of the PCI device in sysfs as gt_energy_uJ.
> > > > The value in the file is a running total of energy (in microjoules)
> > > > consumed by the graphics device.
> > > > 
> > > > v2: move to sysfs (Ben, Daniel)
> > > >     expose a simple value (Chris)
> > > >     drop unrelated hunk (Ben)
> > > > 
> > > > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> > > > 
> > > > v3: by Ben
> > > > Tied it into existing rc6  sysfs entries and named that a more generic
> > > > "power attrs." Fixed rebase conflicts.
> > > > 
> > > > Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> 
> A reminder that we never finished this patch.
> -Chris
> 
> -- 
> Chris Wilson, Intel Open Source Technology Centre

This will be supported in the RAPL driver, so I think we don't need it.
The latest version of that can be found:
https://lkml.org/lkml/2013/4/9/812
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index d0b60f2..0e34f5f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1242,6 +1242,8 @@ 
 #define CLKCFG_MEM_800					(3 << 4)
 #define CLKCFG_MEM_MASK					(7 << 4)
 
+#define SECP_NRG_STTS			(MCHBAR_MIRROR_BASE_SNB + 0x592c)
+
 #define TSC1			0x11001
 #define   TSE			(1<<0)
 #define TR1			0x11006
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index e3a31ae..6bbc9af 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -76,22 +76,43 @@  show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf)
 	return snprintf(buf, PAGE_SIZE, "%u", rc6pp_residency);
 }
 
+#define MSR_IA32_PACKAGE_POWER_SKU_UNIT		0x00000606
+
+static ssize_t
+show_gt_energy_uJ(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
+	struct drm_i915_private *dev_priv = dminor->dev->dev_private;
+	u64 ppsu;
+	u32 val, units;
+
+	rdmsrl(MSR_IA32_PACKAGE_POWER_SKU_UNIT, ppsu);
+
+	ppsu = (ppsu & 0x1f00) >> 8;
+	units = 1000000 / (1 << ppsu); /* convert to uJ */
+	val = I915_READ(SECP_NRG_STTS);
+
+	return snprintf(buf, PAGE_SIZE, "%u", val * units);
+}
+
 static DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL);
 static DEVICE_ATTR(rc6_residency_ms, S_IRUGO, show_rc6_ms, NULL);
 static DEVICE_ATTR(rc6p_residency_ms, S_IRUGO, show_rc6p_ms, NULL);
 static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL);
+static DEVICE_ATTR(gt_energy_uJ, S_IRUGO, show_gt_energy_uJ, NULL);
 
-static struct attribute *rc6_attrs[] = {
+static struct attribute *power_attrs[] = {
 	&dev_attr_rc6_enable.attr,
 	&dev_attr_rc6_residency_ms.attr,
 	&dev_attr_rc6p_residency_ms.attr,
 	&dev_attr_rc6pp_residency_ms.attr,
+	&dev_attr_gt_energy_uJ.attr,
 	NULL
 };
 
 static struct attribute_group rc6_attr_group = {
 	.name = power_group_name,
-	.attrs =  rc6_attrs
+	.attrs =  power_attrs
 };
 #endif