提交 df6eedc8 编写于 作者: B Ben Widawsky 提交者: Daniel Vetter

drm/i915: Add current/max/min GPU freq to sysfs

Userspace applications such as PowerTOP are interesting in being able to
read the current GPU frequency. The patch itself sets up a generic array
for gen6 attributes so we can easily add other items in the future (and
it also happens to be just about the cleanest way to do this).

The patch is a nice addition to
commit 1ac02185dff3afac146d745ba220dc6672d1d162
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Thu Aug 30 13:26:48 2012 +0200

    drm/i915: add a tracepoint for gpu frequency changes

Reading the GPU frequncy can be done by reading a file like:
/sys/class/drm/card0/render_frequency_mhz
Reviewed-by: NChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: NBen Widawsky <ben@bwidawsk.net>
Signed-off-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
上级 c8735b0c
...@@ -203,6 +203,69 @@ static struct bin_attribute dpf_attrs = { ...@@ -203,6 +203,69 @@ static struct bin_attribute dpf_attrs = {
.mmap = NULL .mmap = NULL
}; };
static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
struct device_attribute *attr, char *buf)
{
struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
struct drm_device *dev = minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
mutex_unlock(&dev->struct_mutex);
return snprintf(buf, PAGE_SIZE, "%d", ret);
}
static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
{
struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
struct drm_device *dev = minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
mutex_unlock(&dev->struct_mutex);
return snprintf(buf, PAGE_SIZE, "%d", ret);
}
static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
{
struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
struct drm_device *dev = minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
mutex_unlock(&dev->struct_mutex);
return snprintf(buf, PAGE_SIZE, "%d", ret);
}
static DEVICE_ATTR(gt_cur_freq_mhz, S_IRUGO, gt_cur_freq_mhz_show, NULL);
static DEVICE_ATTR(gt_max_freq_mhz, S_IRUGO | S_IWUSR, gt_max_freq_mhz_show, NULL);
static DEVICE_ATTR(gt_min_freq_mhz, S_IRUGO | S_IWUSR, gt_min_freq_mhz_show, NULL);
static const struct attribute *gen6_attrs[] = {
&dev_attr_gt_cur_freq_mhz.attr,
&dev_attr_gt_max_freq_mhz.attr,
&dev_attr_gt_min_freq_mhz.attr,
NULL,
};
void i915_setup_sysfs(struct drm_device *dev) void i915_setup_sysfs(struct drm_device *dev)
{ {
int ret; int ret;
...@@ -220,10 +283,17 @@ void i915_setup_sysfs(struct drm_device *dev) ...@@ -220,10 +283,17 @@ void i915_setup_sysfs(struct drm_device *dev)
if (ret) if (ret)
DRM_ERROR("l3 parity sysfs setup failed\n"); DRM_ERROR("l3 parity sysfs setup failed\n");
} }
if (INTEL_INFO(dev)->gen >= 6) {
ret = sysfs_create_files(&dev->primary->kdev.kobj, gen6_attrs);
if (ret)
DRM_ERROR("gen6 sysfs setup failed\n");
}
} }
void i915_teardown_sysfs(struct drm_device *dev) void i915_teardown_sysfs(struct drm_device *dev)
{ {
sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs);
device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); device_remove_bin_file(&dev->primary->kdev, &dpf_attrs);
sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册