Skip to content

Commit 0136db5

Browse files
bwidawskdanvet
authored andcommitted
drm/i915: rc6 in sysfs
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 drm core). 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 rc6 modes enabled (as a hex mask): cat /sys/class/drm/card0/power/rc6_enable displays #ms GPU has been in rc6 since boot: cat /sys/class/drm/card0/power/rc6_residency_ms displays #ms GPU has been in deep rc6 since boot: cat /sys/class/drm/card0/power/rc6p_residency_ms displays #ms GPU has been in deepest rc6 since boot: cat /sys/class/drm/card0/power/rc6pp_residency_ms 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 can only guess at the reason reason for this. Those writing tools that utilize this value need to be careful and probably want to scrutinize the value very carefully. v2: use common rc6 residency units to milliseconds for the other RC6 types v3: don't create sysfs files for GEN <= 5 add a rc6_enable to show a mask of enabled rc6 types use unmerge instead of remove for sysfs group squash intel_enable_rc6() extraction into this patch v4: rename sysfs files (Chris) CC: Chris Wilson <chris@chris-wilson.co.uk> CC: Daniel Vetter <daniel.vetter@ffwll.ch>f CC: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Ben Widawsky <benjamin.widawsky@intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> [danvet: squash in the 64bit division fix by Chris Wilson.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
1 parent d1686ae commit 0136db5

File tree

5 files changed

+122
-1
lines changed

5 files changed

+122
-1
lines changed

drivers/gpu/drm/i915/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
1212
i915_gem_execbuffer.o \
1313
i915_gem_gtt.o \
1414
i915_gem_tiling.o \
15+
i915_sysfs.o \
1516
i915_trace_points.o \
1617
intel_display.o \
1718
intel_crt.o \

drivers/gpu/drm/i915/i915_dma.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,6 +2139,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
21392139
}
21402140
}
21412141

2142+
i915_setup_sysfs(dev);
2143+
21422144
/* Must be done after probing outputs */
21432145
intel_opregion_init(dev);
21442146
acpi_video_register();
@@ -2190,6 +2192,8 @@ int i915_driver_unload(struct drm_device *dev)
21902192
i915_mch_dev = NULL;
21912193
spin_unlock(&mchdev_lock);
21922194

2195+
i915_teardown_sysfs(dev);
2196+
21932197
if (dev_priv->mm.inactive_shrinker.shrink)
21942198
unregister_shrinker(&dev_priv->mm.inactive_shrinker);
21952199

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,10 @@ extern int i915_restore_state(struct drm_device *dev);
13851385
extern int i915_save_state(struct drm_device *dev);
13861386
extern int i915_restore_state(struct drm_device *dev);
13871387

1388+
/* i915_sysfs.c */
1389+
void i915_setup_sysfs(struct drm_device *dev_priv);
1390+
void i915_teardown_sysfs(struct drm_device *dev_priv);
1391+
13881392
/* intel_i2c.c */
13891393
extern int intel_setup_gmbus(struct drm_device *dev);
13901394
extern void intel_teardown_gmbus(struct drm_device *dev);
@@ -1441,6 +1445,7 @@ extern void ironlake_enable_rc6(struct drm_device *dev);
14411445
extern void gen6_set_rps(struct drm_device *dev, u8 val);
14421446
extern void intel_detect_pch(struct drm_device *dev);
14431447
extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
1448+
extern int intel_enable_rc6(const struct drm_device *dev);
14441449

14451450
extern bool i915_semaphore_is_enabled(struct drm_device *dev);
14461451
extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);

drivers/gpu/drm/i915/i915_sysfs.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright © 2012 Intel Corporation
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a
5+
* copy of this software and associated documentation files (the "Software"),
6+
* to deal in the Software without restriction, including without limitation
7+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
* and/or sell copies of the Software, and to permit persons to whom the
9+
* Software is furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice (including the next
12+
* paragraph) shall be included in all copies or substantial portions of the
13+
* Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21+
* IN THE SOFTWARE.
22+
*
23+
* Authors:
24+
* Ben Widawsky <ben@bwidawsk.net>
25+
*
26+
*/
27+
28+
#include <linux/device.h>
29+
#include <linux/module.h>
30+
#include <linux/stat.h>
31+
#include <linux/sysfs.h>
32+
#include "i915_drv.h"
33+
34+
static u32 calc_residency(struct drm_device *dev, const u32 reg)
35+
{
36+
struct drm_i915_private *dev_priv = dev->dev_private;
37+
u64 raw_time; /* 32b value may overflow during fixed point math */
38+
39+
if (!intel_enable_rc6(dev))
40+
return 0;
41+
42+
raw_time = I915_READ(reg) * 128ULL + 500;
43+
return do_div(raw_time, 100000);
44+
}
45+
46+
static ssize_t
47+
show_rc6_mask(struct device *dev, struct device_attribute *attr, char *buf)
48+
{
49+
struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
50+
return snprintf(buf, PAGE_SIZE, "%x", intel_enable_rc6(dminor->dev));
51+
}
52+
53+
static ssize_t
54+
show_rc6_ms(struct device *dev, struct device_attribute *attr, char *buf)
55+
{
56+
struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
57+
u32 rc6_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6);
58+
return snprintf(buf, PAGE_SIZE, "%u", rc6_residency);
59+
}
60+
61+
static ssize_t
62+
show_rc6p_ms(struct device *dev, struct device_attribute *attr, char *buf)
63+
{
64+
struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
65+
u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p);
66+
return snprintf(buf, PAGE_SIZE, "%u", rc6p_residency);
67+
}
68+
69+
static ssize_t
70+
show_rc6pp_ms(struct device *dev, struct device_attribute *attr, char *buf)
71+
{
72+
struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
73+
u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp);
74+
return snprintf(buf, PAGE_SIZE, "%u", rc6pp_residency);
75+
}
76+
77+
static DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL);
78+
static DEVICE_ATTR(rc6_residency_ms, S_IRUGO, show_rc6_ms, NULL);
79+
static DEVICE_ATTR(rc6p_residency_ms, S_IRUGO, show_rc6p_ms, NULL);
80+
static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL);
81+
82+
static struct attribute *rc6_attrs[] = {
83+
&dev_attr_rc6_enable.attr,
84+
&dev_attr_rc6_residency_ms.attr,
85+
&dev_attr_rc6p_residency_ms.attr,
86+
&dev_attr_rc6pp_residency_ms.attr,
87+
NULL
88+
};
89+
90+
static struct attribute_group rc6_attr_group = {
91+
.name = power_group_name,
92+
.attrs = rc6_attrs
93+
};
94+
95+
void i915_setup_sysfs(struct drm_device *dev)
96+
{
97+
int ret;
98+
99+
/* ILK doesn't have any residency information */
100+
if (INTEL_INFO(dev)->gen < 6)
101+
return;
102+
103+
ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
104+
if (ret)
105+
DRM_ERROR("sysfs setup failed\n");
106+
}
107+
108+
void i915_teardown_sysfs(struct drm_device *dev)
109+
{
110+
sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
111+
}

drivers/gpu/drm/i915/intel_display.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8547,7 +8547,7 @@ void intel_init_emon(struct drm_device *dev)
85478547
dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
85488548
}
85498549

8550-
static int intel_enable_rc6(struct drm_device *dev)
8550+
int intel_enable_rc6(const struct drm_device *dev)
85518551
{
85528552
/*
85538553
* Respect the kernel parameter if it is set

0 commit comments

Comments
 (0)