xref: /openbmc/linux/drivers/gpu/drm/i915/i915_sysfs.c (revision 46ddf194776500e132693dd2c11b28a971070cc0)
10136db58SBen Widawsky /*
20136db58SBen Widawsky  * Copyright © 2012 Intel Corporation
30136db58SBen Widawsky  *
40136db58SBen Widawsky  * Permission is hereby granted, free of charge, to any person obtaining a
50136db58SBen Widawsky  * copy of this software and associated documentation files (the "Software"),
60136db58SBen Widawsky  * to deal in the Software without restriction, including without limitation
70136db58SBen Widawsky  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
80136db58SBen Widawsky  * and/or sell copies of the Software, and to permit persons to whom the
90136db58SBen Widawsky  * Software is furnished to do so, subject to the following conditions:
100136db58SBen Widawsky  *
110136db58SBen Widawsky  * The above copyright notice and this permission notice (including the next
120136db58SBen Widawsky  * paragraph) shall be included in all copies or substantial portions of the
130136db58SBen Widawsky  * Software.
140136db58SBen Widawsky  *
150136db58SBen Widawsky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
160136db58SBen Widawsky  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
170136db58SBen Widawsky  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
180136db58SBen Widawsky  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
190136db58SBen Widawsky  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
200136db58SBen Widawsky  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
210136db58SBen Widawsky  * IN THE SOFTWARE.
220136db58SBen Widawsky  *
230136db58SBen Widawsky  * Authors:
240136db58SBen Widawsky  *    Ben Widawsky <ben@bwidawsk.net>
250136db58SBen Widawsky  *
260136db58SBen Widawsky  */
270136db58SBen Widawsky 
280136db58SBen Widawsky #include <linux/device.h>
290136db58SBen Widawsky #include <linux/module.h>
300136db58SBen Widawsky #include <linux/stat.h>
310136db58SBen Widawsky #include <linux/sysfs.h>
3284bc7581SBen Widawsky #include "intel_drv.h"
330136db58SBen Widawsky #include "i915_drv.h"
340136db58SBen Widawsky 
355ab3633dSHunt Xu #ifdef CONFIG_PM
360136db58SBen Widawsky static u32 calc_residency(struct drm_device *dev, const u32 reg)
370136db58SBen Widawsky {
380136db58SBen Widawsky 	struct drm_i915_private *dev_priv = dev->dev_private;
390136db58SBen Widawsky 	u64 raw_time; /* 32b value may overflow during fixed point math */
400136db58SBen Widawsky 
410136db58SBen Widawsky 	if (!intel_enable_rc6(dev))
420136db58SBen Widawsky 		return 0;
430136db58SBen Widawsky 
44a85d4bcbSBen Widawsky 	raw_time = I915_READ(reg) * 128ULL;
45a85d4bcbSBen Widawsky 	return DIV_ROUND_UP_ULL(raw_time, 100000);
460136db58SBen Widawsky }
470136db58SBen Widawsky 
480136db58SBen Widawsky static ssize_t
49dbdfd8e9SBen Widawsky show_rc6_mask(struct device *kdev, struct device_attribute *attr, char *buf)
500136db58SBen Widawsky {
51dbdfd8e9SBen Widawsky 	struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
520136db58SBen Widawsky 	return snprintf(buf, PAGE_SIZE, "%x", intel_enable_rc6(dminor->dev));
530136db58SBen Widawsky }
540136db58SBen Widawsky 
550136db58SBen Widawsky static ssize_t
56dbdfd8e9SBen Widawsky show_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf)
570136db58SBen Widawsky {
58dbdfd8e9SBen Widawsky 	struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
590136db58SBen Widawsky 	u32 rc6_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6);
600136db58SBen Widawsky 	return snprintf(buf, PAGE_SIZE, "%u", rc6_residency);
610136db58SBen Widawsky }
620136db58SBen Widawsky 
630136db58SBen Widawsky static ssize_t
64dbdfd8e9SBen Widawsky show_rc6p_ms(struct device *kdev, struct device_attribute *attr, char *buf)
650136db58SBen Widawsky {
66dbdfd8e9SBen Widawsky 	struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
670136db58SBen Widawsky 	u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p);
680136db58SBen Widawsky 	return snprintf(buf, PAGE_SIZE, "%u", rc6p_residency);
690136db58SBen Widawsky }
700136db58SBen Widawsky 
710136db58SBen Widawsky static ssize_t
72dbdfd8e9SBen Widawsky show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf)
730136db58SBen Widawsky {
74dbdfd8e9SBen Widawsky 	struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
750136db58SBen Widawsky 	u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp);
760136db58SBen Widawsky 	return snprintf(buf, PAGE_SIZE, "%u", rc6pp_residency);
770136db58SBen Widawsky }
780136db58SBen Widawsky 
790136db58SBen Widawsky static DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL);
800136db58SBen Widawsky static DEVICE_ATTR(rc6_residency_ms, S_IRUGO, show_rc6_ms, NULL);
810136db58SBen Widawsky static DEVICE_ATTR(rc6p_residency_ms, S_IRUGO, show_rc6p_ms, NULL);
820136db58SBen Widawsky static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL);
830136db58SBen Widawsky 
840136db58SBen Widawsky static struct attribute *rc6_attrs[] = {
850136db58SBen Widawsky 	&dev_attr_rc6_enable.attr,
860136db58SBen Widawsky 	&dev_attr_rc6_residency_ms.attr,
870136db58SBen Widawsky 	&dev_attr_rc6p_residency_ms.attr,
880136db58SBen Widawsky 	&dev_attr_rc6pp_residency_ms.attr,
890136db58SBen Widawsky 	NULL
900136db58SBen Widawsky };
910136db58SBen Widawsky 
920136db58SBen Widawsky static struct attribute_group rc6_attr_group = {
930136db58SBen Widawsky 	.name = power_group_name,
940136db58SBen Widawsky 	.attrs =  rc6_attrs
950136db58SBen Widawsky };
968c3f929bSBen Widawsky #endif
970136db58SBen Widawsky 
9884bc7581SBen Widawsky static int l3_access_valid(struct drm_device *dev, loff_t offset)
9984bc7581SBen Widawsky {
10084bc7581SBen Widawsky 	if (!IS_IVYBRIDGE(dev))
10184bc7581SBen Widawsky 		return -EPERM;
10284bc7581SBen Widawsky 
10384bc7581SBen Widawsky 	if (offset % 4 != 0)
10484bc7581SBen Widawsky 		return -EINVAL;
10584bc7581SBen Widawsky 
10684bc7581SBen Widawsky 	if (offset >= GEN7_L3LOG_SIZE)
10784bc7581SBen Widawsky 		return -ENXIO;
10884bc7581SBen Widawsky 
10984bc7581SBen Widawsky 	return 0;
11084bc7581SBen Widawsky }
11184bc7581SBen Widawsky 
11284bc7581SBen Widawsky static ssize_t
11384bc7581SBen Widawsky i915_l3_read(struct file *filp, struct kobject *kobj,
11484bc7581SBen Widawsky 	     struct bin_attribute *attr, char *buf,
11584bc7581SBen Widawsky 	     loff_t offset, size_t count)
11684bc7581SBen Widawsky {
11784bc7581SBen Widawsky 	struct device *dev = container_of(kobj, struct device, kobj);
11884bc7581SBen Widawsky 	struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
11984bc7581SBen Widawsky 	struct drm_device *drm_dev = dminor->dev;
12084bc7581SBen Widawsky 	struct drm_i915_private *dev_priv = drm_dev->dev_private;
12184bc7581SBen Widawsky 	uint32_t misccpctl;
12284bc7581SBen Widawsky 	int i, ret;
12384bc7581SBen Widawsky 
12484bc7581SBen Widawsky 	ret = l3_access_valid(drm_dev, offset);
12584bc7581SBen Widawsky 	if (ret)
12684bc7581SBen Widawsky 		return ret;
12784bc7581SBen Widawsky 
12884bc7581SBen Widawsky 	ret = i915_mutex_lock_interruptible(drm_dev);
12984bc7581SBen Widawsky 	if (ret)
13084bc7581SBen Widawsky 		return ret;
13184bc7581SBen Widawsky 
13284bc7581SBen Widawsky 	misccpctl = I915_READ(GEN7_MISCCPCTL);
13384bc7581SBen Widawsky 	I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
13484bc7581SBen Widawsky 
13584bc7581SBen Widawsky 	for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4)
13684bc7581SBen Widawsky 		*((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + i);
13784bc7581SBen Widawsky 
13884bc7581SBen Widawsky 	I915_WRITE(GEN7_MISCCPCTL, misccpctl);
13984bc7581SBen Widawsky 
14084bc7581SBen Widawsky 	mutex_unlock(&drm_dev->struct_mutex);
14184bc7581SBen Widawsky 
14284bc7581SBen Widawsky 	return i - offset;
14384bc7581SBen Widawsky }
14484bc7581SBen Widawsky 
14584bc7581SBen Widawsky static ssize_t
14684bc7581SBen Widawsky i915_l3_write(struct file *filp, struct kobject *kobj,
14784bc7581SBen Widawsky 	      struct bin_attribute *attr, char *buf,
14884bc7581SBen Widawsky 	      loff_t offset, size_t count)
14984bc7581SBen Widawsky {
15084bc7581SBen Widawsky 	struct device *dev = container_of(kobj, struct device, kobj);
15184bc7581SBen Widawsky 	struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
15284bc7581SBen Widawsky 	struct drm_device *drm_dev = dminor->dev;
15384bc7581SBen Widawsky 	struct drm_i915_private *dev_priv = drm_dev->dev_private;
15484bc7581SBen Widawsky 	u32 *temp = NULL; /* Just here to make handling failures easy */
15584bc7581SBen Widawsky 	int ret;
15684bc7581SBen Widawsky 
15784bc7581SBen Widawsky 	ret = l3_access_valid(drm_dev, offset);
15884bc7581SBen Widawsky 	if (ret)
15984bc7581SBen Widawsky 		return ret;
16084bc7581SBen Widawsky 
16184bc7581SBen Widawsky 	ret = i915_mutex_lock_interruptible(drm_dev);
16284bc7581SBen Widawsky 	if (ret)
16384bc7581SBen Widawsky 		return ret;
16484bc7581SBen Widawsky 
16584bc7581SBen Widawsky 	if (!dev_priv->mm.l3_remap_info) {
16684bc7581SBen Widawsky 		temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
16784bc7581SBen Widawsky 		if (!temp) {
16884bc7581SBen Widawsky 			mutex_unlock(&drm_dev->struct_mutex);
16984bc7581SBen Widawsky 			return -ENOMEM;
17084bc7581SBen Widawsky 		}
17184bc7581SBen Widawsky 	}
17284bc7581SBen Widawsky 
17384bc7581SBen Widawsky 	ret = i915_gpu_idle(drm_dev);
17484bc7581SBen Widawsky 	if (ret) {
17584bc7581SBen Widawsky 		kfree(temp);
17684bc7581SBen Widawsky 		mutex_unlock(&drm_dev->struct_mutex);
17784bc7581SBen Widawsky 		return ret;
17884bc7581SBen Widawsky 	}
17984bc7581SBen Widawsky 
18084bc7581SBen Widawsky 	/* TODO: Ideally we really want a GPU reset here to make sure errors
18184bc7581SBen Widawsky 	 * aren't propagated. Since I cannot find a stable way to reset the GPU
18284bc7581SBen Widawsky 	 * at this point it is left as a TODO.
18384bc7581SBen Widawsky 	*/
18484bc7581SBen Widawsky 	if (temp)
18584bc7581SBen Widawsky 		dev_priv->mm.l3_remap_info = temp;
18684bc7581SBen Widawsky 
18784bc7581SBen Widawsky 	memcpy(dev_priv->mm.l3_remap_info + (offset/4),
18884bc7581SBen Widawsky 	       buf + (offset/4),
18984bc7581SBen Widawsky 	       count);
19084bc7581SBen Widawsky 
19184bc7581SBen Widawsky 	i915_gem_l3_remap(drm_dev);
19284bc7581SBen Widawsky 
19384bc7581SBen Widawsky 	mutex_unlock(&drm_dev->struct_mutex);
19484bc7581SBen Widawsky 
19584bc7581SBen Widawsky 	return count;
19684bc7581SBen Widawsky }
19784bc7581SBen Widawsky 
19884bc7581SBen Widawsky static struct bin_attribute dpf_attrs = {
19984bc7581SBen Widawsky 	.attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)},
20084bc7581SBen Widawsky 	.size = GEN7_L3LOG_SIZE,
20184bc7581SBen Widawsky 	.read = i915_l3_read,
20284bc7581SBen Widawsky 	.write = i915_l3_write,
20384bc7581SBen Widawsky 	.mmap = NULL
20484bc7581SBen Widawsky };
20584bc7581SBen Widawsky 
206df6eedc8SBen Widawsky static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
207df6eedc8SBen Widawsky 				    struct device_attribute *attr, char *buf)
208df6eedc8SBen Widawsky {
209df6eedc8SBen Widawsky 	struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
210df6eedc8SBen Widawsky 	struct drm_device *dev = minor->dev;
211df6eedc8SBen Widawsky 	struct drm_i915_private *dev_priv = dev->dev_private;
212df6eedc8SBen Widawsky 	int ret;
213df6eedc8SBen Widawsky 
214df6eedc8SBen Widawsky 	ret = i915_mutex_lock_interruptible(dev);
215df6eedc8SBen Widawsky 	if (ret)
216df6eedc8SBen Widawsky 		return ret;
217df6eedc8SBen Widawsky 
218df6eedc8SBen Widawsky 	ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
219df6eedc8SBen Widawsky 	mutex_unlock(&dev->struct_mutex);
220df6eedc8SBen Widawsky 
221df6eedc8SBen Widawsky 	return snprintf(buf, PAGE_SIZE, "%d", ret);
222df6eedc8SBen Widawsky }
223df6eedc8SBen Widawsky 
224df6eedc8SBen Widawsky static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
225df6eedc8SBen Widawsky {
226df6eedc8SBen Widawsky 	struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
227df6eedc8SBen Widawsky 	struct drm_device *dev = minor->dev;
228df6eedc8SBen Widawsky 	struct drm_i915_private *dev_priv = dev->dev_private;
229df6eedc8SBen Widawsky 	int ret;
230df6eedc8SBen Widawsky 
231df6eedc8SBen Widawsky 	ret = i915_mutex_lock_interruptible(dev);
232df6eedc8SBen Widawsky 	if (ret)
233df6eedc8SBen Widawsky 		return ret;
234df6eedc8SBen Widawsky 
235df6eedc8SBen Widawsky 	ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
236df6eedc8SBen Widawsky 	mutex_unlock(&dev->struct_mutex);
237df6eedc8SBen Widawsky 
238df6eedc8SBen Widawsky 	return snprintf(buf, PAGE_SIZE, "%d", ret);
239df6eedc8SBen Widawsky }
240df6eedc8SBen Widawsky 
241*46ddf194SBen Widawsky static ssize_t gt_max_freq_mhz_store(struct device *kdev,
242*46ddf194SBen Widawsky 				     struct device_attribute *attr,
243*46ddf194SBen Widawsky 				     const char *buf, size_t count)
244*46ddf194SBen Widawsky {
245*46ddf194SBen Widawsky 	struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
246*46ddf194SBen Widawsky 	struct drm_device *dev = minor->dev;
247*46ddf194SBen Widawsky 	struct drm_i915_private *dev_priv = dev->dev_private;
248*46ddf194SBen Widawsky 	u32 val, rp_state_cap, hw_max, hw_min;
249*46ddf194SBen Widawsky 	ssize_t ret;
250*46ddf194SBen Widawsky 
251*46ddf194SBen Widawsky 	ret = kstrtou32(buf, 0, &val);
252*46ddf194SBen Widawsky 	if (ret)
253*46ddf194SBen Widawsky 		return ret;
254*46ddf194SBen Widawsky 
255*46ddf194SBen Widawsky 	val /= GT_FREQUENCY_MULTIPLIER;
256*46ddf194SBen Widawsky 
257*46ddf194SBen Widawsky 	ret = mutex_lock_interruptible(&dev->struct_mutex);
258*46ddf194SBen Widawsky 	if (ret)
259*46ddf194SBen Widawsky 		return ret;
260*46ddf194SBen Widawsky 
261*46ddf194SBen Widawsky 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
262*46ddf194SBen Widawsky 	hw_max = (rp_state_cap & 0xff);
263*46ddf194SBen Widawsky 	hw_min = ((rp_state_cap & 0xff0000) >> 16);
264*46ddf194SBen Widawsky 
265*46ddf194SBen Widawsky 	if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) {
266*46ddf194SBen Widawsky 		mutex_unlock(&dev->struct_mutex);
267*46ddf194SBen Widawsky 		return -EINVAL;
268*46ddf194SBen Widawsky 	}
269*46ddf194SBen Widawsky 
270*46ddf194SBen Widawsky 	if (dev_priv->rps.cur_delay > val)
271*46ddf194SBen Widawsky 		gen6_set_rps(dev_priv->dev, val);
272*46ddf194SBen Widawsky 
273*46ddf194SBen Widawsky 	dev_priv->rps.max_delay = val;
274*46ddf194SBen Widawsky 
275*46ddf194SBen Widawsky 	mutex_unlock(&dev->struct_mutex);
276*46ddf194SBen Widawsky 
277*46ddf194SBen Widawsky 	return count;
278*46ddf194SBen Widawsky }
279*46ddf194SBen Widawsky 
280df6eedc8SBen Widawsky static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
281df6eedc8SBen Widawsky {
282df6eedc8SBen Widawsky 	struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
283df6eedc8SBen Widawsky 	struct drm_device *dev = minor->dev;
284df6eedc8SBen Widawsky 	struct drm_i915_private *dev_priv = dev->dev_private;
285df6eedc8SBen Widawsky 	int ret;
286df6eedc8SBen Widawsky 
287df6eedc8SBen Widawsky 	ret = i915_mutex_lock_interruptible(dev);
288df6eedc8SBen Widawsky 	if (ret)
289df6eedc8SBen Widawsky 		return ret;
290df6eedc8SBen Widawsky 
291df6eedc8SBen Widawsky 	ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
292df6eedc8SBen Widawsky 	mutex_unlock(&dev->struct_mutex);
293df6eedc8SBen Widawsky 
294df6eedc8SBen Widawsky 	return snprintf(buf, PAGE_SIZE, "%d", ret);
295df6eedc8SBen Widawsky }
296df6eedc8SBen Widawsky 
297*46ddf194SBen Widawsky static ssize_t gt_min_freq_mhz_store(struct device *kdev,
298*46ddf194SBen Widawsky 				     struct device_attribute *attr,
299*46ddf194SBen Widawsky 				     const char *buf, size_t count)
300*46ddf194SBen Widawsky {
301*46ddf194SBen Widawsky 	struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev);
302*46ddf194SBen Widawsky 	struct drm_device *dev = minor->dev;
303*46ddf194SBen Widawsky 	struct drm_i915_private *dev_priv = dev->dev_private;
304*46ddf194SBen Widawsky 	u32 val, rp_state_cap, hw_max, hw_min;
305*46ddf194SBen Widawsky 	ssize_t ret;
306*46ddf194SBen Widawsky 
307*46ddf194SBen Widawsky 	ret = kstrtou32(buf, 0, &val);
308*46ddf194SBen Widawsky 	if (ret)
309*46ddf194SBen Widawsky 		return ret;
310*46ddf194SBen Widawsky 
311*46ddf194SBen Widawsky 	val /= GT_FREQUENCY_MULTIPLIER;
312*46ddf194SBen Widawsky 
313*46ddf194SBen Widawsky 	ret = mutex_lock_interruptible(&dev->struct_mutex);
314*46ddf194SBen Widawsky 	if (ret)
315*46ddf194SBen Widawsky 		return ret;
316*46ddf194SBen Widawsky 
317*46ddf194SBen Widawsky 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
318*46ddf194SBen Widawsky 	hw_max = (rp_state_cap & 0xff);
319*46ddf194SBen Widawsky 	hw_min = ((rp_state_cap & 0xff0000) >> 16);
320*46ddf194SBen Widawsky 
321*46ddf194SBen Widawsky 	if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
322*46ddf194SBen Widawsky 		mutex_unlock(&dev->struct_mutex);
323*46ddf194SBen Widawsky 		return -EINVAL;
324*46ddf194SBen Widawsky 	}
325*46ddf194SBen Widawsky 
326*46ddf194SBen Widawsky 	if (dev_priv->rps.cur_delay < val)
327*46ddf194SBen Widawsky 		gen6_set_rps(dev_priv->dev, val);
328*46ddf194SBen Widawsky 
329*46ddf194SBen Widawsky 	dev_priv->rps.min_delay = val;
330*46ddf194SBen Widawsky 
331*46ddf194SBen Widawsky 	mutex_unlock(&dev->struct_mutex);
332*46ddf194SBen Widawsky 
333*46ddf194SBen Widawsky 	return count;
334*46ddf194SBen Widawsky 
335*46ddf194SBen Widawsky }
336*46ddf194SBen Widawsky 
337df6eedc8SBen Widawsky static DEVICE_ATTR(gt_cur_freq_mhz, S_IRUGO, gt_cur_freq_mhz_show, NULL);
338*46ddf194SBen Widawsky static DEVICE_ATTR(gt_max_freq_mhz, S_IRUGO | S_IWUSR, gt_max_freq_mhz_show, gt_max_freq_mhz_store);
339*46ddf194SBen Widawsky static DEVICE_ATTR(gt_min_freq_mhz, S_IRUGO | S_IWUSR, gt_min_freq_mhz_show, gt_min_freq_mhz_store);
340df6eedc8SBen Widawsky 
341df6eedc8SBen Widawsky static const struct attribute *gen6_attrs[] = {
342df6eedc8SBen Widawsky 	&dev_attr_gt_cur_freq_mhz.attr,
343df6eedc8SBen Widawsky 	&dev_attr_gt_max_freq_mhz.attr,
344df6eedc8SBen Widawsky 	&dev_attr_gt_min_freq_mhz.attr,
345df6eedc8SBen Widawsky 	NULL,
346df6eedc8SBen Widawsky };
347df6eedc8SBen Widawsky 
3480136db58SBen Widawsky void i915_setup_sysfs(struct drm_device *dev)
3490136db58SBen Widawsky {
3500136db58SBen Widawsky 	int ret;
3510136db58SBen Widawsky 
3528c3f929bSBen Widawsky #ifdef CONFIG_PM
353112abd29SDaniel Vetter 	if (INTEL_INFO(dev)->gen >= 6) {
354112abd29SDaniel Vetter 		ret = sysfs_merge_group(&dev->primary->kdev.kobj,
355112abd29SDaniel Vetter 					&rc6_attr_group);
3560136db58SBen Widawsky 		if (ret)
35784bc7581SBen Widawsky 			DRM_ERROR("RC6 residency sysfs setup failed\n");
358112abd29SDaniel Vetter 	}
3598c3f929bSBen Widawsky #endif
360e1ef7cc2SBen Widawsky 	if (HAS_L3_GPU_CACHE(dev)) {
36184bc7581SBen Widawsky 		ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs);
36284bc7581SBen Widawsky 		if (ret)
36384bc7581SBen Widawsky 			DRM_ERROR("l3 parity sysfs setup failed\n");
3640136db58SBen Widawsky 	}
365df6eedc8SBen Widawsky 
366df6eedc8SBen Widawsky 	if (INTEL_INFO(dev)->gen >= 6) {
367df6eedc8SBen Widawsky 		ret = sysfs_create_files(&dev->primary->kdev.kobj, gen6_attrs);
368df6eedc8SBen Widawsky 		if (ret)
369df6eedc8SBen Widawsky 			DRM_ERROR("gen6 sysfs setup failed\n");
370df6eedc8SBen Widawsky 	}
371112abd29SDaniel Vetter }
3720136db58SBen Widawsky 
3730136db58SBen Widawsky void i915_teardown_sysfs(struct drm_device *dev)
3740136db58SBen Widawsky {
375df6eedc8SBen Widawsky 	sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs);
37684bc7581SBen Widawsky 	device_remove_bin_file(&dev->primary->kdev,  &dpf_attrs);
3770136db58SBen Widawsky 	sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
3780136db58SBen Widawsky }
379