[Intel-gfx] [PATCH 3/3] drm/i915: rc6 in sysfs

Daniel Vetter daniel at ffwll.ch
Sun Mar 25 14:15:56 CEST 2012


On Sat, Mar 24, 2012 at 07:09:46PM -0700, Ben Widawsky wrote:
> Merge rc6 information into the power group for our device. Until now the
> i915 driver has not had any sysfs entries (aside from the connector
> stuff enabled by libdrm). Since it seems like we're likely to have more
> in the future I created a new file for sysfs stubs, as well as the rc6
> sysfs functions which don't really belong elsewhere (perhaps
> i915_suspend, but most of the stuff is in intel_display,c).
> 
> displays #ms GPU has been in rc6 since boot:
> cat /sys/class/drm/card0/power/rc6
> 
> displays #ms GPU has been in deep rc6 since boot:
> cat /sys/class/drm/card0/power/rc6p
> 
> displays #ms GPU has been in deepest rc6 since boot:
> cat /sys/class/drm/card0/power/rc6pp
> 
> Important note: I've seen on SNB that even when RC6 is *not* enabled the
> rc6 register seems to have a random value in it. I cannot explain a
> reason for this. Those writing tools that utilize this value need to be
> careful and probably want to scrutinize the value very carefully.
> 
> Please see intel-gpu-tools patches for sample code.
> 
> CC: Arjan van de Ven <arjan at linux.intel.com>
> Signed-off-by: Ben Widawsky <ben at bwidawsk.net>

I like this (with the cleanups you've mentioned). While you dig around in
sysfs, can I volunteer you to add another patch to create an official
interface for i915_max_freq? Maybe call it max_gpu_freq_MHz (if MHz is an
acceptable unit for sysfs files). We have a bug report which might get
partially happy with this (there seem to be other issues):

https://bugzilla.kernel.org/show_bug.cgi?id=41392a

Cheers, Daniel

> ---
>  drivers/gpu/drm/i915/Makefile       |    1 +
>  drivers/gpu/drm/i915/i915_debugfs.c |    2 +-
>  drivers/gpu/drm/i915/i915_dma.c     |    4 ++
>  drivers/gpu/drm/i915/i915_drv.h     |    4 ++
>  drivers/gpu/drm/i915/i915_sysfs.c   |  106 +++++++++++++++++++++++++++++++++++
>  5 files changed, 116 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/i915/i915_sysfs.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index ce7fc77..f801330 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -12,6 +12,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
>  	  i915_gem_execbuffer.o \
>  	  i915_gem_gtt.o \
>  	  i915_gem_tiling.o \
> +	  i915_sysfs.o \
>  	  i915_trace_points.o \
>  	  intel_display.o \
>  	  intel_crt.o \
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 72457ff..4257151 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1134,9 +1134,9 @@ static int gen6_drpc_info(struct seq_file *m)
>  	seq_printf(m, "Core Power Down: %s\n",
>  		   yesno(gt_core_status & GEN6_CORE_CPD_STATE_MASK));
>  
> +	/* Not exactly sure what this is */
>  	seq_printf(m, "RC6 \"Locked to RPn\" residency since boot: %d\n",
>  		   I915_READ(GEN6_GT_GFX_RC6_LOCKED));
> -	/* Not exactly sure what this is */
>  	seq_printf(m, "RC6 residency since boot: %d\n",
>  		   I915_READ(GEN6_GT_GFX_RC6));
>  	seq_printf(m, "RC6+ residency since boot: %d\n",
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index fdff009..64dfbb8 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -2113,6 +2113,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  		}
>  	}
>  
> +	i915_setup_sysfs(dev);
> +
>  	/* Must be done after probing outputs */
>  	intel_opregion_init(dev);
>  	acpi_video_register();
> @@ -2164,6 +2166,8 @@ int i915_driver_unload(struct drm_device *dev)
>  	i915_mch_dev = NULL;
>  	spin_unlock(&mchdev_lock);
>  
> +	i915_teardown_sysfs(dev);
> +
>  	if (dev_priv->mm.inactive_shrinker.shrink)
>  		unregister_shrinker(&dev_priv->mm.inactive_shrinker);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 22ab4db..e267774 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1365,6 +1365,10 @@ extern int i915_restore_state(struct drm_device *dev);
>  extern int i915_save_state(struct drm_device *dev);
>  extern int i915_restore_state(struct drm_device *dev);
>  
> +/* i915_sysfs.c */
> +void i915_setup_sysfs(struct drm_device *dev_priv);
> +void i915_teardown_sysfs(struct drm_device *dev_priv);
> +
>  /* intel_i2c.c */
>  extern int intel_setup_gmbus(struct drm_device *dev);
>  extern void intel_teardown_gmbus(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> new file mode 100644
> index 0000000..a18a955f
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -0,0 +1,106 @@
> +/*
> + * Copyright © 2012 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *    Ben Widawsky <ben at bwidawsk.net>
> + *
> + */
> +
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/stat.h>
> +#include <linux/sysfs.h>
> +#include "i915_drv.h"
> +
> +static u32 calc_residency(struct drm_device *dev, const u32 reg)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u64 raw_time;
> +	u32 residency;
> +
> +	if (!intel_enable_rc6(dev))
> +		return 0;
> +
> +	raw_time = I915_READ(reg) * 128ULL;
> +	residency = DIV_ROUND_CLOSEST(raw_time, 1000) / 100;
> +	return residency;
> +}
> +
> +static ssize_t
> +show_rc6pp_ms(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> +	struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
> +	u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp);
> +	return snprintf(buf, PAGE_SIZE, "%u", rc6pp_residency);
> +}
> +
> +static ssize_t
> +show_rc6_ms(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;
> +	/* 32b value may overflow during fixed point math */
> +	u64 time = (I915_READ(GEN6_GT_GFX_RC6) * 128);
> +	u32 rc6_residency = DIV_ROUND_CLOSEST(time, 1000) / 100;
> +	return snprintf(buf, PAGE_SIZE, "%u", rc6_residency);
> +}
> +
> +static ssize_t
> +show_rc6p_ms(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;
> +	/* 32b value may overflow during fixed point math */
> +	u64 time = (I915_READ(GEN6_GT_GFX_RC6p) * 128);
> +	u32 rc6p_residency = DIV_ROUND_CLOSEST(time, 1000) / 100;
> +	return snprintf(buf, PAGE_SIZE, "%u", rc6p_residency);
> +}
> +
> +static DEVICE_ATTR(rc6, S_IRUGO, show_rc6_ms, NULL);
> +static DEVICE_ATTR(rc6p, S_IRUGO, show_rc6p_ms, NULL);
> +static DEVICE_ATTR(rc6pp, S_IRUGO, show_rc6pp_ms, NULL);
> +
> +static struct attribute *rc6_attrs[] = {
> +	&dev_attr_rc6.attr,
> +	&dev_attr_rc6p.attr,
> +	&dev_attr_rc6pp.attr,
> +	NULL
> +};
> +
> +static struct attribute_group rc6_attr_group = {
> +	.name = power_group_name,
> +	.attrs =  rc6_attrs
> +};
> +
> +void i915_setup_sysfs(struct drm_device *dev)
> +{
> +	int ret;
> +
> +	ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
> +	if (ret)
> +		DRM_ERROR("sysfs setup failed\n");
> +}
> +
> +void i915_teardown_sysfs(struct drm_device *dev)
> +{
> +	sysfs_remove_group(&dev->primary->kdev.kobj, &rc6_attr_group);
> +}
> -- 
> 1.7.9.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Mail: daniel at ffwll.ch
Mobile: +41 (0)79 365 57 48



More information about the Intel-gfx mailing list