xref: /dflybsd-src/sys/dev/drm/i915/i915_sysfs.c (revision aee94f86171368465eaa15d649743f13cea3363a)
1477eb7f9SFrançois Tigeot /*
2477eb7f9SFrançois Tigeot  * Copyright © 2012 Intel Corporation
3477eb7f9SFrançois Tigeot  *
4477eb7f9SFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
5477eb7f9SFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
6477eb7f9SFrançois Tigeot  * to deal in the Software without restriction, including without limitation
7477eb7f9SFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8477eb7f9SFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
9477eb7f9SFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
10477eb7f9SFrançois Tigeot  *
11477eb7f9SFrançois Tigeot  * The above copyright notice and this permission notice (including the next
12477eb7f9SFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
13477eb7f9SFrançois Tigeot  * Software.
14477eb7f9SFrançois Tigeot  *
15477eb7f9SFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16477eb7f9SFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17477eb7f9SFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18477eb7f9SFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19477eb7f9SFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20477eb7f9SFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21477eb7f9SFrançois Tigeot  * IN THE SOFTWARE.
22477eb7f9SFrançois Tigeot  *
23477eb7f9SFrançois Tigeot  * Authors:
24477eb7f9SFrançois Tigeot  *    Ben Widawsky <ben@bwidawsk.net>
25477eb7f9SFrançois Tigeot  *
26477eb7f9SFrançois Tigeot  */
27477eb7f9SFrançois Tigeot 
28477eb7f9SFrançois Tigeot #include <drm/drmP.h>
29477eb7f9SFrançois Tigeot #include <linux/device.h>
30477eb7f9SFrançois Tigeot #include <linux/module.h>
31477eb7f9SFrançois Tigeot #include "intel_drv.h"
32477eb7f9SFrançois Tigeot #include "i915_drv.h"
33477eb7f9SFrançois Tigeot 
34477eb7f9SFrançois Tigeot #if 0
35477eb7f9SFrançois Tigeot #define dev_to_drm_minor(d) dev_get_drvdata((d))
36477eb7f9SFrançois Tigeot 
37477eb7f9SFrançois Tigeot #ifdef CONFIG_PM
38*aee94f86SFrançois Tigeot static u32 calc_residency(struct drm_device *dev,
39*aee94f86SFrançois Tigeot 			  i915_reg_t reg)
40477eb7f9SFrançois Tigeot {
41477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
42477eb7f9SFrançois Tigeot 	u64 raw_time; /* 32b value may overflow during fixed point math */
43352ff8bdSFrançois Tigeot 	u64 units = 128ULL, div = 100000ULL;
44477eb7f9SFrançois Tigeot 	u32 ret;
45477eb7f9SFrançois Tigeot 
46477eb7f9SFrançois Tigeot 	if (!intel_enable_rc6(dev))
47477eb7f9SFrançois Tigeot 		return 0;
48477eb7f9SFrançois Tigeot 
49477eb7f9SFrançois Tigeot 	intel_runtime_pm_get(dev_priv);
50477eb7f9SFrançois Tigeot 
51477eb7f9SFrançois Tigeot 	/* On VLV and CHV, residency time is in CZ units rather than 1.28us */
52*aee94f86SFrançois Tigeot 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
53352ff8bdSFrançois Tigeot 		units = 1;
54352ff8bdSFrançois Tigeot 		div = dev_priv->czclk_freq;
55477eb7f9SFrançois Tigeot 
56477eb7f9SFrançois Tigeot 		if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
57477eb7f9SFrançois Tigeot 			units <<= 8;
58352ff8bdSFrançois Tigeot 	} else if (IS_BROXTON(dev)) {
59352ff8bdSFrançois Tigeot 		units = 1;
60352ff8bdSFrançois Tigeot 		div = 1200;		/* 833.33ns */
61477eb7f9SFrançois Tigeot 	}
62477eb7f9SFrançois Tigeot 
63477eb7f9SFrançois Tigeot 	raw_time = I915_READ(reg) * units;
64477eb7f9SFrançois Tigeot 	ret = DIV_ROUND_UP_ULL(raw_time, div);
65477eb7f9SFrançois Tigeot 
66477eb7f9SFrançois Tigeot 	intel_runtime_pm_put(dev_priv);
67477eb7f9SFrançois Tigeot 	return ret;
68477eb7f9SFrançois Tigeot }
69477eb7f9SFrançois Tigeot 
70477eb7f9SFrançois Tigeot static ssize_t
71477eb7f9SFrançois Tigeot show_rc6_mask(struct device *kdev, struct device_attribute *attr, char *buf)
72477eb7f9SFrançois Tigeot {
73477eb7f9SFrançois Tigeot 	struct drm_minor *dminor = dev_to_drm_minor(kdev);
74477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%x\n", intel_enable_rc6(dminor->dev));
75477eb7f9SFrançois Tigeot }
76477eb7f9SFrançois Tigeot 
77477eb7f9SFrançois Tigeot static ssize_t
78477eb7f9SFrançois Tigeot show_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf)
79477eb7f9SFrançois Tigeot {
80477eb7f9SFrançois Tigeot 	struct drm_minor *dminor = dev_get_drvdata(kdev);
81477eb7f9SFrançois Tigeot 	u32 rc6_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6);
82477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%u\n", rc6_residency);
83477eb7f9SFrançois Tigeot }
84477eb7f9SFrançois Tigeot 
85477eb7f9SFrançois Tigeot static ssize_t
86477eb7f9SFrançois Tigeot show_rc6p_ms(struct device *kdev, struct device_attribute *attr, char *buf)
87477eb7f9SFrançois Tigeot {
88477eb7f9SFrançois Tigeot 	struct drm_minor *dminor = dev_to_drm_minor(kdev);
89477eb7f9SFrançois Tigeot 	u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p);
90477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%u\n", rc6p_residency);
91477eb7f9SFrançois Tigeot }
92477eb7f9SFrançois Tigeot 
93477eb7f9SFrançois Tigeot static ssize_t
94477eb7f9SFrançois Tigeot show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf)
95477eb7f9SFrançois Tigeot {
96477eb7f9SFrançois Tigeot 	struct drm_minor *dminor = dev_to_drm_minor(kdev);
97477eb7f9SFrançois Tigeot 	u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp);
98477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%u\n", rc6pp_residency);
99477eb7f9SFrançois Tigeot }
100477eb7f9SFrançois Tigeot 
101477eb7f9SFrançois Tigeot static ssize_t
102477eb7f9SFrançois Tigeot show_media_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf)
103477eb7f9SFrançois Tigeot {
104477eb7f9SFrançois Tigeot 	struct drm_minor *dminor = dev_get_drvdata(kdev);
105477eb7f9SFrançois Tigeot 	u32 rc6_residency = calc_residency(dminor->dev, VLV_GT_MEDIA_RC6);
106477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%u\n", rc6_residency);
107477eb7f9SFrançois Tigeot }
108477eb7f9SFrançois Tigeot 
109477eb7f9SFrançois Tigeot static DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL);
110477eb7f9SFrançois Tigeot static DEVICE_ATTR(rc6_residency_ms, S_IRUGO, show_rc6_ms, NULL);
111477eb7f9SFrançois Tigeot static DEVICE_ATTR(rc6p_residency_ms, S_IRUGO, show_rc6p_ms, NULL);
112477eb7f9SFrançois Tigeot static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL);
113477eb7f9SFrançois Tigeot static DEVICE_ATTR(media_rc6_residency_ms, S_IRUGO, show_media_rc6_ms, NULL);
114477eb7f9SFrançois Tigeot 
115477eb7f9SFrançois Tigeot static struct attribute *rc6_attrs[] = {
116477eb7f9SFrançois Tigeot 	&dev_attr_rc6_enable.attr,
117477eb7f9SFrançois Tigeot 	&dev_attr_rc6_residency_ms.attr,
118477eb7f9SFrançois Tigeot 	NULL
119477eb7f9SFrançois Tigeot };
120477eb7f9SFrançois Tigeot 
121477eb7f9SFrançois Tigeot static struct attribute_group rc6_attr_group = {
122477eb7f9SFrançois Tigeot 	.name = power_group_name,
123477eb7f9SFrançois Tigeot 	.attrs =  rc6_attrs
124477eb7f9SFrançois Tigeot };
125477eb7f9SFrançois Tigeot 
126477eb7f9SFrançois Tigeot static struct attribute *rc6p_attrs[] = {
127477eb7f9SFrançois Tigeot 	&dev_attr_rc6p_residency_ms.attr,
128477eb7f9SFrançois Tigeot 	&dev_attr_rc6pp_residency_ms.attr,
129477eb7f9SFrançois Tigeot 	NULL
130477eb7f9SFrançois Tigeot };
131477eb7f9SFrançois Tigeot 
132477eb7f9SFrançois Tigeot static struct attribute_group rc6p_attr_group = {
133477eb7f9SFrançois Tigeot 	.name = power_group_name,
134477eb7f9SFrançois Tigeot 	.attrs =  rc6p_attrs
135477eb7f9SFrançois Tigeot };
136477eb7f9SFrançois Tigeot 
137477eb7f9SFrançois Tigeot static struct attribute *media_rc6_attrs[] = {
138477eb7f9SFrançois Tigeot 	&dev_attr_media_rc6_residency_ms.attr,
139477eb7f9SFrançois Tigeot 	NULL
140477eb7f9SFrançois Tigeot };
141477eb7f9SFrançois Tigeot 
142477eb7f9SFrançois Tigeot static struct attribute_group media_rc6_attr_group = {
143477eb7f9SFrançois Tigeot 	.name = power_group_name,
144477eb7f9SFrançois Tigeot 	.attrs =  media_rc6_attrs
145477eb7f9SFrançois Tigeot };
146477eb7f9SFrançois Tigeot #endif
147477eb7f9SFrançois Tigeot 
148477eb7f9SFrançois Tigeot static int l3_access_valid(struct drm_device *dev, loff_t offset)
149477eb7f9SFrançois Tigeot {
150477eb7f9SFrançois Tigeot 	if (!HAS_L3_DPF(dev))
151477eb7f9SFrançois Tigeot 		return -EPERM;
152477eb7f9SFrançois Tigeot 
153477eb7f9SFrançois Tigeot 	if (offset % 4 != 0)
154477eb7f9SFrançois Tigeot 		return -EINVAL;
155477eb7f9SFrançois Tigeot 
156477eb7f9SFrançois Tigeot 	if (offset >= GEN7_L3LOG_SIZE)
157477eb7f9SFrançois Tigeot 		return -ENXIO;
158477eb7f9SFrançois Tigeot 
159477eb7f9SFrançois Tigeot 	return 0;
160477eb7f9SFrançois Tigeot }
161477eb7f9SFrançois Tigeot 
162477eb7f9SFrançois Tigeot static ssize_t
163477eb7f9SFrançois Tigeot i915_l3_read(struct file *filp, struct kobject *kobj,
164477eb7f9SFrançois Tigeot 	     struct bin_attribute *attr, char *buf,
165477eb7f9SFrançois Tigeot 	     loff_t offset, size_t count)
166477eb7f9SFrançois Tigeot {
167477eb7f9SFrançois Tigeot 	struct device *dev = container_of(kobj, struct device, kobj);
168477eb7f9SFrançois Tigeot 	struct drm_minor *dminor = dev_to_drm_minor(dev);
169477eb7f9SFrançois Tigeot 	struct drm_device *drm_dev = dminor->dev;
170477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = drm_dev->dev_private;
171477eb7f9SFrançois Tigeot 	int slice = (int)(uintptr_t)attr->private;
172477eb7f9SFrançois Tigeot 	int ret;
173477eb7f9SFrançois Tigeot 
174477eb7f9SFrançois Tigeot 	count = round_down(count, 4);
175477eb7f9SFrançois Tigeot 
176477eb7f9SFrançois Tigeot 	ret = l3_access_valid(drm_dev, offset);
177477eb7f9SFrançois Tigeot 	if (ret)
178477eb7f9SFrançois Tigeot 		return ret;
179477eb7f9SFrançois Tigeot 
180477eb7f9SFrançois Tigeot 	count = min_t(size_t, GEN7_L3LOG_SIZE - offset, count);
181477eb7f9SFrançois Tigeot 
182477eb7f9SFrançois Tigeot 	ret = i915_mutex_lock_interruptible(drm_dev);
183477eb7f9SFrançois Tigeot 	if (ret)
184477eb7f9SFrançois Tigeot 		return ret;
185477eb7f9SFrançois Tigeot 
186477eb7f9SFrançois Tigeot 	if (dev_priv->l3_parity.remap_info[slice])
187477eb7f9SFrançois Tigeot 		memcpy(buf,
188477eb7f9SFrançois Tigeot 		       dev_priv->l3_parity.remap_info[slice] + (offset/4),
189477eb7f9SFrançois Tigeot 		       count);
190477eb7f9SFrançois Tigeot 	else
191477eb7f9SFrançois Tigeot 		memset(buf, 0, count);
192477eb7f9SFrançois Tigeot 
193477eb7f9SFrançois Tigeot 	mutex_unlock(&drm_dev->struct_mutex);
194477eb7f9SFrançois Tigeot 
195477eb7f9SFrançois Tigeot 	return count;
196477eb7f9SFrançois Tigeot }
197477eb7f9SFrançois Tigeot 
198477eb7f9SFrançois Tigeot static ssize_t
199477eb7f9SFrançois Tigeot i915_l3_write(struct file *filp, struct kobject *kobj,
200477eb7f9SFrançois Tigeot 	      struct bin_attribute *attr, char *buf,
201477eb7f9SFrançois Tigeot 	      loff_t offset, size_t count)
202477eb7f9SFrançois Tigeot {
203477eb7f9SFrançois Tigeot 	struct device *dev = container_of(kobj, struct device, kobj);
204477eb7f9SFrançois Tigeot 	struct drm_minor *dminor = dev_to_drm_minor(dev);
205477eb7f9SFrançois Tigeot 	struct drm_device *drm_dev = dminor->dev;
206477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = drm_dev->dev_private;
207477eb7f9SFrançois Tigeot 	struct intel_context *ctx;
208477eb7f9SFrançois Tigeot 	u32 *temp = NULL; /* Just here to make handling failures easy */
209477eb7f9SFrançois Tigeot 	int slice = (int)(uintptr_t)attr->private;
210477eb7f9SFrançois Tigeot 	int ret;
211477eb7f9SFrançois Tigeot 
212477eb7f9SFrançois Tigeot 	if (!HAS_HW_CONTEXTS(drm_dev))
213477eb7f9SFrançois Tigeot 		return -ENXIO;
214477eb7f9SFrançois Tigeot 
215477eb7f9SFrançois Tigeot 	ret = l3_access_valid(drm_dev, offset);
216477eb7f9SFrançois Tigeot 	if (ret)
217477eb7f9SFrançois Tigeot 		return ret;
218477eb7f9SFrançois Tigeot 
219477eb7f9SFrançois Tigeot 	ret = i915_mutex_lock_interruptible(drm_dev);
220477eb7f9SFrançois Tigeot 	if (ret)
221477eb7f9SFrançois Tigeot 		return ret;
222477eb7f9SFrançois Tigeot 
223477eb7f9SFrançois Tigeot 	if (!dev_priv->l3_parity.remap_info[slice]) {
224477eb7f9SFrançois Tigeot 		temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
225477eb7f9SFrançois Tigeot 		if (!temp) {
226477eb7f9SFrançois Tigeot 			mutex_unlock(&drm_dev->struct_mutex);
227477eb7f9SFrançois Tigeot 			return -ENOMEM;
228477eb7f9SFrançois Tigeot 		}
229477eb7f9SFrançois Tigeot 	}
230477eb7f9SFrançois Tigeot 
231477eb7f9SFrançois Tigeot 	ret = i915_gpu_idle(drm_dev);
232477eb7f9SFrançois Tigeot 	if (ret) {
233477eb7f9SFrançois Tigeot 		kfree(temp);
234477eb7f9SFrançois Tigeot 		mutex_unlock(&drm_dev->struct_mutex);
235477eb7f9SFrançois Tigeot 		return ret;
236477eb7f9SFrançois Tigeot 	}
237477eb7f9SFrançois Tigeot 
238477eb7f9SFrançois Tigeot 	/* TODO: Ideally we really want a GPU reset here to make sure errors
239477eb7f9SFrançois Tigeot 	 * aren't propagated. Since I cannot find a stable way to reset the GPU
240477eb7f9SFrançois Tigeot 	 * at this point it is left as a TODO.
241477eb7f9SFrançois Tigeot 	*/
242477eb7f9SFrançois Tigeot 	if (temp)
243477eb7f9SFrançois Tigeot 		dev_priv->l3_parity.remap_info[slice] = temp;
244477eb7f9SFrançois Tigeot 
245477eb7f9SFrançois Tigeot 	memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count);
246477eb7f9SFrançois Tigeot 
247477eb7f9SFrançois Tigeot 	/* NB: We defer the remapping until we switch to the context */
248477eb7f9SFrançois Tigeot 	list_for_each_entry(ctx, &dev_priv->context_list, link)
249477eb7f9SFrançois Tigeot 		ctx->remap_slice |= (1<<slice);
250477eb7f9SFrançois Tigeot 
251477eb7f9SFrançois Tigeot 	mutex_unlock(&drm_dev->struct_mutex);
252477eb7f9SFrançois Tigeot 
253477eb7f9SFrançois Tigeot 	return count;
254477eb7f9SFrançois Tigeot }
255477eb7f9SFrançois Tigeot 
256477eb7f9SFrançois Tigeot static struct bin_attribute dpf_attrs = {
257477eb7f9SFrançois Tigeot 	.attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)},
258477eb7f9SFrançois Tigeot 	.size = GEN7_L3LOG_SIZE,
259477eb7f9SFrançois Tigeot 	.read = i915_l3_read,
260477eb7f9SFrançois Tigeot 	.write = i915_l3_write,
261477eb7f9SFrançois Tigeot 	.mmap = NULL,
262477eb7f9SFrançois Tigeot 	.private = (void *)0
263477eb7f9SFrançois Tigeot };
264477eb7f9SFrançois Tigeot 
265477eb7f9SFrançois Tigeot static struct bin_attribute dpf_attrs_1 = {
266477eb7f9SFrançois Tigeot 	.attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)},
267477eb7f9SFrançois Tigeot 	.size = GEN7_L3LOG_SIZE,
268477eb7f9SFrançois Tigeot 	.read = i915_l3_read,
269477eb7f9SFrançois Tigeot 	.write = i915_l3_write,
270477eb7f9SFrançois Tigeot 	.mmap = NULL,
271477eb7f9SFrançois Tigeot 	.private = (void *)1
272477eb7f9SFrançois Tigeot };
273477eb7f9SFrançois Tigeot 
274477eb7f9SFrançois Tigeot static ssize_t gt_act_freq_mhz_show(struct device *kdev,
275477eb7f9SFrançois Tigeot 				    struct device_attribute *attr, char *buf)
276477eb7f9SFrançois Tigeot {
277477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
278477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
279477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
280477eb7f9SFrançois Tigeot 	int ret;
281477eb7f9SFrançois Tigeot 
282477eb7f9SFrançois Tigeot 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
283477eb7f9SFrançois Tigeot 
284477eb7f9SFrançois Tigeot 	intel_runtime_pm_get(dev_priv);
285477eb7f9SFrançois Tigeot 
286477eb7f9SFrançois Tigeot 	mutex_lock(&dev_priv->rps.hw_lock);
287*aee94f86SFrançois Tigeot 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
288477eb7f9SFrançois Tigeot 		u32 freq;
289477eb7f9SFrançois Tigeot 		freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
290477eb7f9SFrançois Tigeot 		ret = intel_gpu_freq(dev_priv, (freq >> 8) & 0xff);
291477eb7f9SFrançois Tigeot 	} else {
292477eb7f9SFrançois Tigeot 		u32 rpstat = I915_READ(GEN6_RPSTAT1);
293477eb7f9SFrançois Tigeot 		if (IS_GEN9(dev_priv))
294477eb7f9SFrançois Tigeot 			ret = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT;
295477eb7f9SFrançois Tigeot 		else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
296477eb7f9SFrançois Tigeot 			ret = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
297477eb7f9SFrançois Tigeot 		else
298477eb7f9SFrançois Tigeot 			ret = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
299477eb7f9SFrançois Tigeot 		ret = intel_gpu_freq(dev_priv, ret);
300477eb7f9SFrançois Tigeot 	}
301477eb7f9SFrançois Tigeot 	mutex_unlock(&dev_priv->rps.hw_lock);
302477eb7f9SFrançois Tigeot 
303477eb7f9SFrançois Tigeot 	intel_runtime_pm_put(dev_priv);
304477eb7f9SFrançois Tigeot 
305477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
306477eb7f9SFrançois Tigeot }
307477eb7f9SFrançois Tigeot 
308477eb7f9SFrançois Tigeot static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
309477eb7f9SFrançois Tigeot 				    struct device_attribute *attr, char *buf)
310477eb7f9SFrançois Tigeot {
311477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
312477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
313477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
314477eb7f9SFrançois Tigeot 	int ret;
315477eb7f9SFrançois Tigeot 
316477eb7f9SFrançois Tigeot 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
317477eb7f9SFrançois Tigeot 
318477eb7f9SFrançois Tigeot 	intel_runtime_pm_get(dev_priv);
319477eb7f9SFrançois Tigeot 
320477eb7f9SFrançois Tigeot 	mutex_lock(&dev_priv->rps.hw_lock);
321477eb7f9SFrançois Tigeot 	ret = intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq);
322477eb7f9SFrançois Tigeot 	mutex_unlock(&dev_priv->rps.hw_lock);
323477eb7f9SFrançois Tigeot 
324477eb7f9SFrançois Tigeot 	intel_runtime_pm_put(dev_priv);
325477eb7f9SFrançois Tigeot 
326477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
327477eb7f9SFrançois Tigeot }
328477eb7f9SFrançois Tigeot 
329477eb7f9SFrançois Tigeot static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
330477eb7f9SFrançois Tigeot 				     struct device_attribute *attr, char *buf)
331477eb7f9SFrançois Tigeot {
332477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
333477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
334477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
335477eb7f9SFrançois Tigeot 
336477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE,
337477eb7f9SFrançois Tigeot 			"%d\n",
338477eb7f9SFrançois Tigeot 			intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
339477eb7f9SFrançois Tigeot }
340477eb7f9SFrançois Tigeot 
341477eb7f9SFrançois Tigeot static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
342477eb7f9SFrançois Tigeot {
343477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
344477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
345477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
346477eb7f9SFrançois Tigeot 	int ret;
347477eb7f9SFrançois Tigeot 
348477eb7f9SFrançois Tigeot 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
349477eb7f9SFrançois Tigeot 
350477eb7f9SFrançois Tigeot 	mutex_lock(&dev_priv->rps.hw_lock);
351477eb7f9SFrançois Tigeot 	ret = intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit);
352477eb7f9SFrançois Tigeot 	mutex_unlock(&dev_priv->rps.hw_lock);
353477eb7f9SFrançois Tigeot 
354477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
355477eb7f9SFrançois Tigeot }
356477eb7f9SFrançois Tigeot 
357477eb7f9SFrançois Tigeot static ssize_t gt_max_freq_mhz_store(struct device *kdev,
358477eb7f9SFrançois Tigeot 				     struct device_attribute *attr,
359477eb7f9SFrançois Tigeot 				     const char *buf, size_t count)
360477eb7f9SFrançois Tigeot {
361477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
362477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
363477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
364477eb7f9SFrançois Tigeot 	u32 val;
365477eb7f9SFrançois Tigeot 	ssize_t ret;
366477eb7f9SFrançois Tigeot 
367477eb7f9SFrançois Tigeot 	ret = kstrtou32(buf, 0, &val);
368477eb7f9SFrançois Tigeot 	if (ret)
369477eb7f9SFrançois Tigeot 		return ret;
370477eb7f9SFrançois Tigeot 
371477eb7f9SFrançois Tigeot 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
372477eb7f9SFrançois Tigeot 
373477eb7f9SFrançois Tigeot 	mutex_lock(&dev_priv->rps.hw_lock);
374477eb7f9SFrançois Tigeot 
375477eb7f9SFrançois Tigeot 	val = intel_freq_opcode(dev_priv, val);
376477eb7f9SFrançois Tigeot 
377477eb7f9SFrançois Tigeot 	if (val < dev_priv->rps.min_freq ||
378477eb7f9SFrançois Tigeot 	    val > dev_priv->rps.max_freq ||
379477eb7f9SFrançois Tigeot 	    val < dev_priv->rps.min_freq_softlimit) {
380477eb7f9SFrançois Tigeot 		mutex_unlock(&dev_priv->rps.hw_lock);
381477eb7f9SFrançois Tigeot 		return -EINVAL;
382477eb7f9SFrançois Tigeot 	}
383477eb7f9SFrançois Tigeot 
384477eb7f9SFrançois Tigeot 	if (val > dev_priv->rps.rp0_freq)
385477eb7f9SFrançois Tigeot 		DRM_DEBUG("User requested overclocking to %d\n",
386477eb7f9SFrançois Tigeot 			  intel_gpu_freq(dev_priv, val));
387477eb7f9SFrançois Tigeot 
388477eb7f9SFrançois Tigeot 	dev_priv->rps.max_freq_softlimit = val;
389477eb7f9SFrançois Tigeot 
390477eb7f9SFrançois Tigeot 	val = clamp_t(int, dev_priv->rps.cur_freq,
391477eb7f9SFrançois Tigeot 		      dev_priv->rps.min_freq_softlimit,
392477eb7f9SFrançois Tigeot 		      dev_priv->rps.max_freq_softlimit);
393477eb7f9SFrançois Tigeot 
394477eb7f9SFrançois Tigeot 	/* We still need *_set_rps to process the new max_delay and
395477eb7f9SFrançois Tigeot 	 * update the interrupt limits and PMINTRMSK even though
396477eb7f9SFrançois Tigeot 	 * frequency request may be unchanged. */
397477eb7f9SFrançois Tigeot 	intel_set_rps(dev, val);
398477eb7f9SFrançois Tigeot 
399477eb7f9SFrançois Tigeot 	mutex_unlock(&dev_priv->rps.hw_lock);
400477eb7f9SFrançois Tigeot 
401477eb7f9SFrançois Tigeot 	return count;
402477eb7f9SFrançois Tigeot }
403477eb7f9SFrançois Tigeot 
404477eb7f9SFrançois Tigeot static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
405477eb7f9SFrançois Tigeot {
406477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
407477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
408477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
409477eb7f9SFrançois Tigeot 	int ret;
410477eb7f9SFrançois Tigeot 
411477eb7f9SFrançois Tigeot 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
412477eb7f9SFrançois Tigeot 
413477eb7f9SFrançois Tigeot 	mutex_lock(&dev_priv->rps.hw_lock);
414477eb7f9SFrançois Tigeot 	ret = intel_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit);
415477eb7f9SFrançois Tigeot 	mutex_unlock(&dev_priv->rps.hw_lock);
416477eb7f9SFrançois Tigeot 
417477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
418477eb7f9SFrançois Tigeot }
419477eb7f9SFrançois Tigeot 
420477eb7f9SFrançois Tigeot static ssize_t gt_min_freq_mhz_store(struct device *kdev,
421477eb7f9SFrançois Tigeot 				     struct device_attribute *attr,
422477eb7f9SFrançois Tigeot 				     const char *buf, size_t count)
423477eb7f9SFrançois Tigeot {
424477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
425477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
426477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
427477eb7f9SFrançois Tigeot 	u32 val;
428477eb7f9SFrançois Tigeot 	ssize_t ret;
429477eb7f9SFrançois Tigeot 
430477eb7f9SFrançois Tigeot 	ret = kstrtou32(buf, 0, &val);
431477eb7f9SFrançois Tigeot 	if (ret)
432477eb7f9SFrançois Tigeot 		return ret;
433477eb7f9SFrançois Tigeot 
434477eb7f9SFrançois Tigeot 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
435477eb7f9SFrançois Tigeot 
436477eb7f9SFrançois Tigeot 	mutex_lock(&dev_priv->rps.hw_lock);
437477eb7f9SFrançois Tigeot 
438477eb7f9SFrançois Tigeot 	val = intel_freq_opcode(dev_priv, val);
439477eb7f9SFrançois Tigeot 
440477eb7f9SFrançois Tigeot 	if (val < dev_priv->rps.min_freq ||
441477eb7f9SFrançois Tigeot 	    val > dev_priv->rps.max_freq ||
442477eb7f9SFrançois Tigeot 	    val > dev_priv->rps.max_freq_softlimit) {
443477eb7f9SFrançois Tigeot 		mutex_unlock(&dev_priv->rps.hw_lock);
444477eb7f9SFrançois Tigeot 		return -EINVAL;
445477eb7f9SFrançois Tigeot 	}
446477eb7f9SFrançois Tigeot 
447477eb7f9SFrançois Tigeot 	dev_priv->rps.min_freq_softlimit = val;
448477eb7f9SFrançois Tigeot 
449477eb7f9SFrançois Tigeot 	val = clamp_t(int, dev_priv->rps.cur_freq,
450477eb7f9SFrançois Tigeot 		      dev_priv->rps.min_freq_softlimit,
451477eb7f9SFrançois Tigeot 		      dev_priv->rps.max_freq_softlimit);
452477eb7f9SFrançois Tigeot 
453477eb7f9SFrançois Tigeot 	/* We still need *_set_rps to process the new min_delay and
454477eb7f9SFrançois Tigeot 	 * update the interrupt limits and PMINTRMSK even though
455477eb7f9SFrançois Tigeot 	 * frequency request may be unchanged. */
456477eb7f9SFrançois Tigeot 	intel_set_rps(dev, val);
457477eb7f9SFrançois Tigeot 
458477eb7f9SFrançois Tigeot 	mutex_unlock(&dev_priv->rps.hw_lock);
459477eb7f9SFrançois Tigeot 
460477eb7f9SFrançois Tigeot 	return count;
461477eb7f9SFrançois Tigeot 
462477eb7f9SFrançois Tigeot }
463477eb7f9SFrançois Tigeot 
464477eb7f9SFrançois Tigeot static DEVICE_ATTR(gt_act_freq_mhz, S_IRUGO, gt_act_freq_mhz_show, NULL);
465477eb7f9SFrançois Tigeot static DEVICE_ATTR(gt_cur_freq_mhz, S_IRUGO, gt_cur_freq_mhz_show, NULL);
466477eb7f9SFrançois Tigeot static DEVICE_ATTR(gt_max_freq_mhz, S_IRUGO | S_IWUSR, gt_max_freq_mhz_show, gt_max_freq_mhz_store);
467477eb7f9SFrançois Tigeot static DEVICE_ATTR(gt_min_freq_mhz, S_IRUGO | S_IWUSR, gt_min_freq_mhz_show, gt_min_freq_mhz_store);
468477eb7f9SFrançois Tigeot 
469477eb7f9SFrançois Tigeot static DEVICE_ATTR(vlv_rpe_freq_mhz, S_IRUGO, vlv_rpe_freq_mhz_show, NULL);
470477eb7f9SFrançois Tigeot 
471477eb7f9SFrançois Tigeot static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf);
472477eb7f9SFrançois Tigeot static DEVICE_ATTR(gt_RP0_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
473477eb7f9SFrançois Tigeot static DEVICE_ATTR(gt_RP1_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
474477eb7f9SFrançois Tigeot static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
475477eb7f9SFrançois Tigeot 
476477eb7f9SFrançois Tigeot /* For now we have a static number of RP states */
477477eb7f9SFrançois Tigeot static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
478477eb7f9SFrançois Tigeot {
479477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
480477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
481477eb7f9SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
482477eb7f9SFrançois Tigeot 	u32 val;
483477eb7f9SFrançois Tigeot 
484477eb7f9SFrançois Tigeot 	if (attr == &dev_attr_gt_RP0_freq_mhz)
485477eb7f9SFrançois Tigeot 		val = intel_gpu_freq(dev_priv, dev_priv->rps.rp0_freq);
486477eb7f9SFrançois Tigeot 	else if (attr == &dev_attr_gt_RP1_freq_mhz)
487477eb7f9SFrançois Tigeot 		val = intel_gpu_freq(dev_priv, dev_priv->rps.rp1_freq);
488477eb7f9SFrançois Tigeot 	else if (attr == &dev_attr_gt_RPn_freq_mhz)
489477eb7f9SFrançois Tigeot 		val = intel_gpu_freq(dev_priv, dev_priv->rps.min_freq);
490477eb7f9SFrançois Tigeot 	else
491477eb7f9SFrançois Tigeot 		BUG();
492477eb7f9SFrançois Tigeot 
493477eb7f9SFrançois Tigeot 	return snprintf(buf, PAGE_SIZE, "%d\n", val);
494477eb7f9SFrançois Tigeot }
495477eb7f9SFrançois Tigeot 
496477eb7f9SFrançois Tigeot static const struct attribute *gen6_attrs[] = {
497477eb7f9SFrançois Tigeot 	&dev_attr_gt_act_freq_mhz.attr,
498477eb7f9SFrançois Tigeot 	&dev_attr_gt_cur_freq_mhz.attr,
499477eb7f9SFrançois Tigeot 	&dev_attr_gt_max_freq_mhz.attr,
500477eb7f9SFrançois Tigeot 	&dev_attr_gt_min_freq_mhz.attr,
501477eb7f9SFrançois Tigeot 	&dev_attr_gt_RP0_freq_mhz.attr,
502477eb7f9SFrançois Tigeot 	&dev_attr_gt_RP1_freq_mhz.attr,
503477eb7f9SFrançois Tigeot 	&dev_attr_gt_RPn_freq_mhz.attr,
504477eb7f9SFrançois Tigeot 	NULL,
505477eb7f9SFrançois Tigeot };
506477eb7f9SFrançois Tigeot 
507477eb7f9SFrançois Tigeot static const struct attribute *vlv_attrs[] = {
508477eb7f9SFrançois Tigeot 	&dev_attr_gt_act_freq_mhz.attr,
509477eb7f9SFrançois Tigeot 	&dev_attr_gt_cur_freq_mhz.attr,
510477eb7f9SFrançois Tigeot 	&dev_attr_gt_max_freq_mhz.attr,
511477eb7f9SFrançois Tigeot 	&dev_attr_gt_min_freq_mhz.attr,
512477eb7f9SFrançois Tigeot 	&dev_attr_gt_RP0_freq_mhz.attr,
513477eb7f9SFrançois Tigeot 	&dev_attr_gt_RP1_freq_mhz.attr,
514477eb7f9SFrançois Tigeot 	&dev_attr_gt_RPn_freq_mhz.attr,
515477eb7f9SFrançois Tigeot 	&dev_attr_vlv_rpe_freq_mhz.attr,
516477eb7f9SFrançois Tigeot 	NULL,
517477eb7f9SFrançois Tigeot };
518477eb7f9SFrançois Tigeot 
519477eb7f9SFrançois Tigeot static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
520477eb7f9SFrançois Tigeot 				struct bin_attribute *attr, char *buf,
521477eb7f9SFrançois Tigeot 				loff_t off, size_t count)
522477eb7f9SFrançois Tigeot {
523477eb7f9SFrançois Tigeot 
524477eb7f9SFrançois Tigeot 	struct device *kdev = container_of(kobj, struct device, kobj);
525477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
526477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
527477eb7f9SFrançois Tigeot 	struct i915_error_state_file_priv error_priv;
528477eb7f9SFrançois Tigeot 	struct drm_i915_error_state_buf error_str;
529477eb7f9SFrançois Tigeot 	ssize_t ret_count = 0;
530477eb7f9SFrançois Tigeot 	int ret;
531477eb7f9SFrançois Tigeot 
532477eb7f9SFrançois Tigeot 	memset(&error_priv, 0, sizeof(error_priv));
533477eb7f9SFrançois Tigeot 
534477eb7f9SFrançois Tigeot 	ret = i915_error_state_buf_init(&error_str, to_i915(dev), count, off);
535477eb7f9SFrançois Tigeot 	if (ret)
536477eb7f9SFrançois Tigeot 		return ret;
537477eb7f9SFrançois Tigeot 
538477eb7f9SFrançois Tigeot 	error_priv.dev = dev;
539477eb7f9SFrançois Tigeot 	i915_error_state_get(dev, &error_priv);
540477eb7f9SFrançois Tigeot 
541477eb7f9SFrançois Tigeot 	ret = i915_error_state_to_str(&error_str, &error_priv);
542477eb7f9SFrançois Tigeot 	if (ret)
543477eb7f9SFrançois Tigeot 		goto out;
544477eb7f9SFrançois Tigeot 
545477eb7f9SFrançois Tigeot 	ret_count = count < error_str.bytes ? count : error_str.bytes;
546477eb7f9SFrançois Tigeot 
547477eb7f9SFrançois Tigeot 	memcpy(buf, error_str.buf, ret_count);
548477eb7f9SFrançois Tigeot out:
549477eb7f9SFrançois Tigeot 	i915_error_state_put(&error_priv);
550477eb7f9SFrançois Tigeot 	i915_error_state_buf_release(&error_str);
551477eb7f9SFrançois Tigeot 
552477eb7f9SFrançois Tigeot 	return ret ?: ret_count;
553477eb7f9SFrançois Tigeot }
554477eb7f9SFrançois Tigeot 
555477eb7f9SFrançois Tigeot static ssize_t error_state_write(struct file *file, struct kobject *kobj,
556477eb7f9SFrançois Tigeot 				 struct bin_attribute *attr, char *buf,
557477eb7f9SFrançois Tigeot 				 loff_t off, size_t count)
558477eb7f9SFrançois Tigeot {
559477eb7f9SFrançois Tigeot 	struct device *kdev = container_of(kobj, struct device, kobj);
560477eb7f9SFrançois Tigeot 	struct drm_minor *minor = dev_to_drm_minor(kdev);
561477eb7f9SFrançois Tigeot 	struct drm_device *dev = minor->dev;
562477eb7f9SFrançois Tigeot 	int ret;
563477eb7f9SFrançois Tigeot 
564477eb7f9SFrançois Tigeot 	DRM_DEBUG_DRIVER("Resetting error state\n");
565477eb7f9SFrançois Tigeot 
566477eb7f9SFrançois Tigeot 	ret = mutex_lock_interruptible(&dev->struct_mutex);
567477eb7f9SFrançois Tigeot 	if (ret)
568477eb7f9SFrançois Tigeot 		return ret;
569477eb7f9SFrançois Tigeot 
570477eb7f9SFrançois Tigeot 	i915_destroy_error_state(dev);
571477eb7f9SFrançois Tigeot 	mutex_unlock(&dev->struct_mutex);
572477eb7f9SFrançois Tigeot 
573477eb7f9SFrançois Tigeot 	return count;
574477eb7f9SFrançois Tigeot }
575477eb7f9SFrançois Tigeot 
576477eb7f9SFrançois Tigeot static struct bin_attribute error_state_attr = {
577477eb7f9SFrançois Tigeot 	.attr.name = "error",
578477eb7f9SFrançois Tigeot 	.attr.mode = S_IRUSR | S_IWUSR,
579477eb7f9SFrançois Tigeot 	.size = 0,
580477eb7f9SFrançois Tigeot 	.read = error_state_read,
581477eb7f9SFrançois Tigeot 	.write = error_state_write,
582477eb7f9SFrançois Tigeot };
583477eb7f9SFrançois Tigeot #endif
584477eb7f9SFrançois Tigeot 
585477eb7f9SFrançois Tigeot void i915_setup_sysfs(struct drm_device *dev)
586477eb7f9SFrançois Tigeot {
587477eb7f9SFrançois Tigeot #if 0
588477eb7f9SFrançois Tigeot 	int ret;
589477eb7f9SFrançois Tigeot 
590477eb7f9SFrançois Tigeot #ifdef CONFIG_PM
591477eb7f9SFrançois Tigeot 	if (HAS_RC6(dev)) {
592477eb7f9SFrançois Tigeot 		ret = sysfs_merge_group(&dev->primary->kdev->kobj,
593477eb7f9SFrançois Tigeot 					&rc6_attr_group);
594477eb7f9SFrançois Tigeot 		if (ret)
595477eb7f9SFrançois Tigeot 			DRM_ERROR("RC6 residency sysfs setup failed\n");
596477eb7f9SFrançois Tigeot 	}
597477eb7f9SFrançois Tigeot 	if (HAS_RC6p(dev)) {
598477eb7f9SFrançois Tigeot 		ret = sysfs_merge_group(&dev->primary->kdev->kobj,
599477eb7f9SFrançois Tigeot 					&rc6p_attr_group);
600477eb7f9SFrançois Tigeot 		if (ret)
601477eb7f9SFrançois Tigeot 			DRM_ERROR("RC6p residency sysfs setup failed\n");
602477eb7f9SFrançois Tigeot 	}
603*aee94f86SFrançois Tigeot 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
604477eb7f9SFrançois Tigeot 		ret = sysfs_merge_group(&dev->primary->kdev->kobj,
605477eb7f9SFrançois Tigeot 					&media_rc6_attr_group);
606477eb7f9SFrançois Tigeot 		if (ret)
607477eb7f9SFrançois Tigeot 			DRM_ERROR("Media RC6 residency sysfs setup failed\n");
608477eb7f9SFrançois Tigeot 	}
609477eb7f9SFrançois Tigeot #endif
610477eb7f9SFrançois Tigeot 	if (HAS_L3_DPF(dev)) {
611477eb7f9SFrançois Tigeot 		ret = device_create_bin_file(dev->primary->kdev, &dpf_attrs);
612477eb7f9SFrançois Tigeot 		if (ret)
613477eb7f9SFrançois Tigeot 			DRM_ERROR("l3 parity sysfs setup failed\n");
614477eb7f9SFrançois Tigeot 
615477eb7f9SFrançois Tigeot 		if (NUM_L3_SLICES(dev) > 1) {
616477eb7f9SFrançois Tigeot 			ret = device_create_bin_file(dev->primary->kdev,
617477eb7f9SFrançois Tigeot 						     &dpf_attrs_1);
618477eb7f9SFrançois Tigeot 			if (ret)
619477eb7f9SFrançois Tigeot 				DRM_ERROR("l3 parity slice 1 setup failed\n");
620477eb7f9SFrançois Tigeot 		}
621477eb7f9SFrançois Tigeot 	}
622477eb7f9SFrançois Tigeot 
623477eb7f9SFrançois Tigeot 	ret = 0;
624*aee94f86SFrançois Tigeot 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
625477eb7f9SFrançois Tigeot 		ret = sysfs_create_files(&dev->primary->kdev->kobj, vlv_attrs);
626477eb7f9SFrançois Tigeot 	else if (INTEL_INFO(dev)->gen >= 6)
627477eb7f9SFrançois Tigeot 		ret = sysfs_create_files(&dev->primary->kdev->kobj, gen6_attrs);
628477eb7f9SFrançois Tigeot 	if (ret)
629477eb7f9SFrançois Tigeot 		DRM_ERROR("RPS sysfs setup failed\n");
630477eb7f9SFrançois Tigeot 
631477eb7f9SFrançois Tigeot 	ret = sysfs_create_bin_file(&dev->primary->kdev->kobj,
632477eb7f9SFrançois Tigeot 				    &error_state_attr);
633477eb7f9SFrançois Tigeot 	if (ret)
634477eb7f9SFrançois Tigeot 		DRM_ERROR("error_state sysfs setup failed\n");
635477eb7f9SFrançois Tigeot #endif
636477eb7f9SFrançois Tigeot }
637477eb7f9SFrançois Tigeot 
638477eb7f9SFrançois Tigeot void i915_teardown_sysfs(struct drm_device *dev)
639477eb7f9SFrançois Tigeot {
640477eb7f9SFrançois Tigeot #if 0
641477eb7f9SFrançois Tigeot 	sysfs_remove_bin_file(&dev->primary->kdev->kobj, &error_state_attr);
642*aee94f86SFrançois Tigeot 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
643477eb7f9SFrançois Tigeot 		sysfs_remove_files(&dev->primary->kdev->kobj, vlv_attrs);
644477eb7f9SFrançois Tigeot 	else
645477eb7f9SFrançois Tigeot 		sysfs_remove_files(&dev->primary->kdev->kobj, gen6_attrs);
646477eb7f9SFrançois Tigeot 	device_remove_bin_file(dev->primary->kdev,  &dpf_attrs_1);
647477eb7f9SFrançois Tigeot 	device_remove_bin_file(dev->primary->kdev,  &dpf_attrs);
648477eb7f9SFrançois Tigeot #ifdef CONFIG_PM
649477eb7f9SFrançois Tigeot 	sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6_attr_group);
650477eb7f9SFrançois Tigeot 	sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6p_attr_group);
651477eb7f9SFrançois Tigeot #endif
652477eb7f9SFrançois Tigeot #endif
653477eb7f9SFrançois Tigeot }
654