18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright © 2012 Intel Corporation
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next
128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
138c2ecf20Sopenharmony_ci * Software.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
218c2ecf20Sopenharmony_ci * IN THE SOFTWARE.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Authors:
248c2ecf20Sopenharmony_ci *    Ben Widawsky <ben@bwidawsk.net>
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include <linux/device.h>
298c2ecf20Sopenharmony_ci#include <linux/module.h>
308c2ecf20Sopenharmony_ci#include <linux/stat.h>
318c2ecf20Sopenharmony_ci#include <linux/sysfs.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include "gt/intel_rc6.h"
348c2ecf20Sopenharmony_ci#include "gt/intel_rps.h"
358c2ecf20Sopenharmony_ci#include "gt/sysfs_engines.h"
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include "i915_drv.h"
388c2ecf20Sopenharmony_ci#include "i915_sysfs.h"
398c2ecf20Sopenharmony_ci#include "intel_pm.h"
408c2ecf20Sopenharmony_ci#include "intel_sideband.h"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	struct drm_minor *minor = dev_get_drvdata(kdev);
458c2ecf20Sopenharmony_ci	return to_i915(minor->dev);
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
498c2ecf20Sopenharmony_cistatic u32 calc_residency(struct drm_i915_private *dev_priv,
508c2ecf20Sopenharmony_ci			  i915_reg_t reg)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	intel_wakeref_t wakeref;
538c2ecf20Sopenharmony_ci	u64 res = 0;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
568c2ecf20Sopenharmony_ci		res = intel_rc6_residency_us(&dev_priv->gt.rc6, reg);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	return DIV_ROUND_CLOSEST_ULL(res, 1000);
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic ssize_t
628c2ecf20Sopenharmony_cishow_rc6_mask(struct device *kdev, struct device_attribute *attr, char *buf)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
658c2ecf20Sopenharmony_ci	unsigned int mask;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	mask = 0;
688c2ecf20Sopenharmony_ci	if (HAS_RC6(dev_priv))
698c2ecf20Sopenharmony_ci		mask |= BIT(0);
708c2ecf20Sopenharmony_ci	if (HAS_RC6p(dev_priv))
718c2ecf20Sopenharmony_ci		mask |= BIT(1);
728c2ecf20Sopenharmony_ci	if (HAS_RC6pp(dev_priv))
738c2ecf20Sopenharmony_ci		mask |= BIT(2);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%x\n", mask);
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic ssize_t
798c2ecf20Sopenharmony_cishow_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
828c2ecf20Sopenharmony_ci	u32 rc6_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6);
838c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%u\n", rc6_residency);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic ssize_t
878c2ecf20Sopenharmony_cishow_rc6p_ms(struct device *kdev, struct device_attribute *attr, char *buf)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
908c2ecf20Sopenharmony_ci	u32 rc6p_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6p);
918c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%u\n", rc6p_residency);
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic ssize_t
958c2ecf20Sopenharmony_cishow_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
988c2ecf20Sopenharmony_ci	u32 rc6pp_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6pp);
998c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%u\n", rc6pp_residency);
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic ssize_t
1038c2ecf20Sopenharmony_cishow_media_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
1068c2ecf20Sopenharmony_ci	u32 rc6_residency = calc_residency(dev_priv, VLV_GT_MEDIA_RC6);
1078c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%u\n", rc6_residency);
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL);
1118c2ecf20Sopenharmony_cistatic DEVICE_ATTR(rc6_residency_ms, S_IRUGO, show_rc6_ms, NULL);
1128c2ecf20Sopenharmony_cistatic DEVICE_ATTR(rc6p_residency_ms, S_IRUGO, show_rc6p_ms, NULL);
1138c2ecf20Sopenharmony_cistatic DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL);
1148c2ecf20Sopenharmony_cistatic DEVICE_ATTR(media_rc6_residency_ms, S_IRUGO, show_media_rc6_ms, NULL);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic struct attribute *rc6_attrs[] = {
1178c2ecf20Sopenharmony_ci	&dev_attr_rc6_enable.attr,
1188c2ecf20Sopenharmony_ci	&dev_attr_rc6_residency_ms.attr,
1198c2ecf20Sopenharmony_ci	NULL
1208c2ecf20Sopenharmony_ci};
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic const struct attribute_group rc6_attr_group = {
1238c2ecf20Sopenharmony_ci	.name = power_group_name,
1248c2ecf20Sopenharmony_ci	.attrs =  rc6_attrs
1258c2ecf20Sopenharmony_ci};
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic struct attribute *rc6p_attrs[] = {
1288c2ecf20Sopenharmony_ci	&dev_attr_rc6p_residency_ms.attr,
1298c2ecf20Sopenharmony_ci	&dev_attr_rc6pp_residency_ms.attr,
1308c2ecf20Sopenharmony_ci	NULL
1318c2ecf20Sopenharmony_ci};
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic const struct attribute_group rc6p_attr_group = {
1348c2ecf20Sopenharmony_ci	.name = power_group_name,
1358c2ecf20Sopenharmony_ci	.attrs =  rc6p_attrs
1368c2ecf20Sopenharmony_ci};
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic struct attribute *media_rc6_attrs[] = {
1398c2ecf20Sopenharmony_ci	&dev_attr_media_rc6_residency_ms.attr,
1408c2ecf20Sopenharmony_ci	NULL
1418c2ecf20Sopenharmony_ci};
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic const struct attribute_group media_rc6_attr_group = {
1448c2ecf20Sopenharmony_ci	.name = power_group_name,
1458c2ecf20Sopenharmony_ci	.attrs =  media_rc6_attrs
1468c2ecf20Sopenharmony_ci};
1478c2ecf20Sopenharmony_ci#endif
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistatic int l3_access_valid(struct drm_i915_private *i915, loff_t offset)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	if (!HAS_L3_DPF(i915))
1528c2ecf20Sopenharmony_ci		return -EPERM;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	if (!IS_ALIGNED(offset, sizeof(u32)))
1558c2ecf20Sopenharmony_ci		return -EINVAL;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	if (offset >= GEN7_L3LOG_SIZE)
1588c2ecf20Sopenharmony_ci		return -ENXIO;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	return 0;
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic ssize_t
1648c2ecf20Sopenharmony_cii915_l3_read(struct file *filp, struct kobject *kobj,
1658c2ecf20Sopenharmony_ci	     struct bin_attribute *attr, char *buf,
1668c2ecf20Sopenharmony_ci	     loff_t offset, size_t count)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct device *kdev = kobj_to_dev(kobj);
1698c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
1708c2ecf20Sopenharmony_ci	int slice = (int)(uintptr_t)attr->private;
1718c2ecf20Sopenharmony_ci	int ret;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	ret = l3_access_valid(i915, offset);
1748c2ecf20Sopenharmony_ci	if (ret)
1758c2ecf20Sopenharmony_ci		return ret;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	count = round_down(count, sizeof(u32));
1788c2ecf20Sopenharmony_ci	count = min_t(size_t, GEN7_L3LOG_SIZE - offset, count);
1798c2ecf20Sopenharmony_ci	memset(buf, 0, count);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	spin_lock(&i915->gem.contexts.lock);
1828c2ecf20Sopenharmony_ci	if (i915->l3_parity.remap_info[slice])
1838c2ecf20Sopenharmony_ci		memcpy(buf,
1848c2ecf20Sopenharmony_ci		       i915->l3_parity.remap_info[slice] + offset / sizeof(u32),
1858c2ecf20Sopenharmony_ci		       count);
1868c2ecf20Sopenharmony_ci	spin_unlock(&i915->gem.contexts.lock);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	return count;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistatic ssize_t
1928c2ecf20Sopenharmony_cii915_l3_write(struct file *filp, struct kobject *kobj,
1938c2ecf20Sopenharmony_ci	      struct bin_attribute *attr, char *buf,
1948c2ecf20Sopenharmony_ci	      loff_t offset, size_t count)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	struct device *kdev = kobj_to_dev(kobj);
1978c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
1988c2ecf20Sopenharmony_ci	int slice = (int)(uintptr_t)attr->private;
1998c2ecf20Sopenharmony_ci	u32 *remap_info, *freeme = NULL;
2008c2ecf20Sopenharmony_ci	struct i915_gem_context *ctx;
2018c2ecf20Sopenharmony_ci	int ret;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	ret = l3_access_valid(i915, offset);
2048c2ecf20Sopenharmony_ci	if (ret)
2058c2ecf20Sopenharmony_ci		return ret;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	if (count < sizeof(u32))
2088c2ecf20Sopenharmony_ci		return -EINVAL;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	remap_info = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
2118c2ecf20Sopenharmony_ci	if (!remap_info)
2128c2ecf20Sopenharmony_ci		return -ENOMEM;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	spin_lock(&i915->gem.contexts.lock);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	if (i915->l3_parity.remap_info[slice]) {
2178c2ecf20Sopenharmony_ci		freeme = remap_info;
2188c2ecf20Sopenharmony_ci		remap_info = i915->l3_parity.remap_info[slice];
2198c2ecf20Sopenharmony_ci	} else {
2208c2ecf20Sopenharmony_ci		i915->l3_parity.remap_info[slice] = remap_info;
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	count = round_down(count, sizeof(u32));
2248c2ecf20Sopenharmony_ci	memcpy(remap_info + offset / sizeof(u32), buf, count);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	/* NB: We defer the remapping until we switch to the context */
2278c2ecf20Sopenharmony_ci	list_for_each_entry(ctx, &i915->gem.contexts.list, link)
2288c2ecf20Sopenharmony_ci		ctx->remap_slice |= BIT(slice);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	spin_unlock(&i915->gem.contexts.lock);
2318c2ecf20Sopenharmony_ci	kfree(freeme);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	/*
2348c2ecf20Sopenharmony_ci	 * TODO: Ideally we really want a GPU reset here to make sure errors
2358c2ecf20Sopenharmony_ci	 * aren't propagated. Since I cannot find a stable way to reset the GPU
2368c2ecf20Sopenharmony_ci	 * at this point it is left as a TODO.
2378c2ecf20Sopenharmony_ci	*/
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	return count;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic const struct bin_attribute dpf_attrs = {
2438c2ecf20Sopenharmony_ci	.attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)},
2448c2ecf20Sopenharmony_ci	.size = GEN7_L3LOG_SIZE,
2458c2ecf20Sopenharmony_ci	.read = i915_l3_read,
2468c2ecf20Sopenharmony_ci	.write = i915_l3_write,
2478c2ecf20Sopenharmony_ci	.mmap = NULL,
2488c2ecf20Sopenharmony_ci	.private = (void *)0
2498c2ecf20Sopenharmony_ci};
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic const struct bin_attribute dpf_attrs_1 = {
2528c2ecf20Sopenharmony_ci	.attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)},
2538c2ecf20Sopenharmony_ci	.size = GEN7_L3LOG_SIZE,
2548c2ecf20Sopenharmony_ci	.read = i915_l3_read,
2558c2ecf20Sopenharmony_ci	.write = i915_l3_write,
2568c2ecf20Sopenharmony_ci	.mmap = NULL,
2578c2ecf20Sopenharmony_ci	.private = (void *)1
2588c2ecf20Sopenharmony_ci};
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic ssize_t gt_act_freq_mhz_show(struct device *kdev,
2618c2ecf20Sopenharmony_ci				    struct device_attribute *attr, char *buf)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
2648c2ecf20Sopenharmony_ci	struct intel_rps *rps = &i915->gt.rps;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n",
2678c2ecf20Sopenharmony_ci			intel_rps_read_actual_frequency(rps));
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic ssize_t gt_cur_freq_mhz_show(struct device *kdev,
2718c2ecf20Sopenharmony_ci				    struct device_attribute *attr, char *buf)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
2748c2ecf20Sopenharmony_ci	struct intel_rps *rps = &i915->gt.rps;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n",
2778c2ecf20Sopenharmony_ci			intel_gpu_freq(rps, rps->cur_freq));
2788c2ecf20Sopenharmony_ci}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
2838c2ecf20Sopenharmony_ci	struct intel_rps *rps = &i915->gt.rps;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n",
2868c2ecf20Sopenharmony_ci			intel_gpu_freq(rps, rps->boost_freq));
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_cistatic ssize_t gt_boost_freq_mhz_store(struct device *kdev,
2908c2ecf20Sopenharmony_ci				       struct device_attribute *attr,
2918c2ecf20Sopenharmony_ci				       const char *buf, size_t count)
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
2948c2ecf20Sopenharmony_ci	struct intel_rps *rps = &dev_priv->gt.rps;
2958c2ecf20Sopenharmony_ci	bool boost = false;
2968c2ecf20Sopenharmony_ci	ssize_t ret;
2978c2ecf20Sopenharmony_ci	u32 val;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	ret = kstrtou32(buf, 0, &val);
3008c2ecf20Sopenharmony_ci	if (ret)
3018c2ecf20Sopenharmony_ci		return ret;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	/* Validate against (static) hardware limits */
3048c2ecf20Sopenharmony_ci	val = intel_freq_opcode(rps, val);
3058c2ecf20Sopenharmony_ci	if (val < rps->min_freq || val > rps->max_freq)
3068c2ecf20Sopenharmony_ci		return -EINVAL;
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	mutex_lock(&rps->lock);
3098c2ecf20Sopenharmony_ci	if (val != rps->boost_freq) {
3108c2ecf20Sopenharmony_ci		rps->boost_freq = val;
3118c2ecf20Sopenharmony_ci		boost = atomic_read(&rps->num_waiters);
3128c2ecf20Sopenharmony_ci	}
3138c2ecf20Sopenharmony_ci	mutex_unlock(&rps->lock);
3148c2ecf20Sopenharmony_ci	if (boost)
3158c2ecf20Sopenharmony_ci		schedule_work(&rps->work);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	return count;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
3218c2ecf20Sopenharmony_ci				     struct device_attribute *attr, char *buf)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
3248c2ecf20Sopenharmony_ci	struct intel_rps *rps = &dev_priv->gt.rps;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n",
3278c2ecf20Sopenharmony_ci			intel_gpu_freq(rps, rps->efficient_freq));
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
3338c2ecf20Sopenharmony_ci	struct intel_rps *rps = &dev_priv->gt.rps;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n",
3368c2ecf20Sopenharmony_ci			intel_gpu_freq(rps, rps->max_freq_softlimit));
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic ssize_t gt_max_freq_mhz_store(struct device *kdev,
3408c2ecf20Sopenharmony_ci				     struct device_attribute *attr,
3418c2ecf20Sopenharmony_ci				     const char *buf, size_t count)
3428c2ecf20Sopenharmony_ci{
3438c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
3448c2ecf20Sopenharmony_ci	struct intel_rps *rps = &dev_priv->gt.rps;
3458c2ecf20Sopenharmony_ci	ssize_t ret;
3468c2ecf20Sopenharmony_ci	u32 val;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	ret = kstrtou32(buf, 0, &val);
3498c2ecf20Sopenharmony_ci	if (ret)
3508c2ecf20Sopenharmony_ci		return ret;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	mutex_lock(&rps->lock);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	val = intel_freq_opcode(rps, val);
3558c2ecf20Sopenharmony_ci	if (val < rps->min_freq ||
3568c2ecf20Sopenharmony_ci	    val > rps->max_freq ||
3578c2ecf20Sopenharmony_ci	    val < rps->min_freq_softlimit) {
3588c2ecf20Sopenharmony_ci		ret = -EINVAL;
3598c2ecf20Sopenharmony_ci		goto unlock;
3608c2ecf20Sopenharmony_ci	}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	if (val > rps->rp0_freq)
3638c2ecf20Sopenharmony_ci		DRM_DEBUG("User requested overclocking to %d\n",
3648c2ecf20Sopenharmony_ci			  intel_gpu_freq(rps, val));
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	rps->max_freq_softlimit = val;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	val = clamp_t(int, rps->cur_freq,
3698c2ecf20Sopenharmony_ci		      rps->min_freq_softlimit,
3708c2ecf20Sopenharmony_ci		      rps->max_freq_softlimit);
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	/*
3738c2ecf20Sopenharmony_ci	 * We still need *_set_rps to process the new max_delay and
3748c2ecf20Sopenharmony_ci	 * update the interrupt limits and PMINTRMSK even though
3758c2ecf20Sopenharmony_ci	 * frequency request may be unchanged.
3768c2ecf20Sopenharmony_ci	 */
3778c2ecf20Sopenharmony_ci	intel_rps_set(rps, val);
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ciunlock:
3808c2ecf20Sopenharmony_ci	mutex_unlock(&rps->lock);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	return ret ?: count;
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_cistatic ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
3888c2ecf20Sopenharmony_ci	struct intel_rps *rps = &dev_priv->gt.rps;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n",
3918c2ecf20Sopenharmony_ci			intel_gpu_freq(rps, rps->min_freq_softlimit));
3928c2ecf20Sopenharmony_ci}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_cistatic ssize_t gt_min_freq_mhz_store(struct device *kdev,
3958c2ecf20Sopenharmony_ci				     struct device_attribute *attr,
3968c2ecf20Sopenharmony_ci				     const char *buf, size_t count)
3978c2ecf20Sopenharmony_ci{
3988c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
3998c2ecf20Sopenharmony_ci	struct intel_rps *rps = &dev_priv->gt.rps;
4008c2ecf20Sopenharmony_ci	ssize_t ret;
4018c2ecf20Sopenharmony_ci	u32 val;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	ret = kstrtou32(buf, 0, &val);
4048c2ecf20Sopenharmony_ci	if (ret)
4058c2ecf20Sopenharmony_ci		return ret;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	mutex_lock(&rps->lock);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	val = intel_freq_opcode(rps, val);
4108c2ecf20Sopenharmony_ci	if (val < rps->min_freq ||
4118c2ecf20Sopenharmony_ci	    val > rps->max_freq ||
4128c2ecf20Sopenharmony_ci	    val > rps->max_freq_softlimit) {
4138c2ecf20Sopenharmony_ci		ret = -EINVAL;
4148c2ecf20Sopenharmony_ci		goto unlock;
4158c2ecf20Sopenharmony_ci	}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	rps->min_freq_softlimit = val;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	val = clamp_t(int, rps->cur_freq,
4208c2ecf20Sopenharmony_ci		      rps->min_freq_softlimit,
4218c2ecf20Sopenharmony_ci		      rps->max_freq_softlimit);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	/*
4248c2ecf20Sopenharmony_ci	 * We still need *_set_rps to process the new min_delay and
4258c2ecf20Sopenharmony_ci	 * update the interrupt limits and PMINTRMSK even though
4268c2ecf20Sopenharmony_ci	 * frequency request may be unchanged.
4278c2ecf20Sopenharmony_ci	 */
4288c2ecf20Sopenharmony_ci	intel_rps_set(rps, val);
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ciunlock:
4318c2ecf20Sopenharmony_ci	mutex_unlock(&rps->lock);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	return ret ?: count;
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(gt_act_freq_mhz);
4378c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(gt_cur_freq_mhz);
4388c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(gt_boost_freq_mhz);
4398c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(gt_max_freq_mhz);
4408c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(gt_min_freq_mhz);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_cistatic ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf);
4458c2ecf20Sopenharmony_cistatic DEVICE_ATTR(gt_RP0_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
4468c2ecf20Sopenharmony_cistatic DEVICE_ATTR(gt_RP1_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
4478c2ecf20Sopenharmony_cistatic DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL);
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci/* For now we have a static number of RP states */
4508c2ecf20Sopenharmony_cistatic ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
4538c2ecf20Sopenharmony_ci	struct intel_rps *rps = &dev_priv->gt.rps;
4548c2ecf20Sopenharmony_ci	u32 val;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	if (attr == &dev_attr_gt_RP0_freq_mhz)
4578c2ecf20Sopenharmony_ci		val = intel_gpu_freq(rps, rps->rp0_freq);
4588c2ecf20Sopenharmony_ci	else if (attr == &dev_attr_gt_RP1_freq_mhz)
4598c2ecf20Sopenharmony_ci		val = intel_gpu_freq(rps, rps->rp1_freq);
4608c2ecf20Sopenharmony_ci	else if (attr == &dev_attr_gt_RPn_freq_mhz)
4618c2ecf20Sopenharmony_ci		val = intel_gpu_freq(rps, rps->min_freq);
4628c2ecf20Sopenharmony_ci	else
4638c2ecf20Sopenharmony_ci		BUG();
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n", val);
4668c2ecf20Sopenharmony_ci}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_cistatic const struct attribute * const gen6_attrs[] = {
4698c2ecf20Sopenharmony_ci	&dev_attr_gt_act_freq_mhz.attr,
4708c2ecf20Sopenharmony_ci	&dev_attr_gt_cur_freq_mhz.attr,
4718c2ecf20Sopenharmony_ci	&dev_attr_gt_boost_freq_mhz.attr,
4728c2ecf20Sopenharmony_ci	&dev_attr_gt_max_freq_mhz.attr,
4738c2ecf20Sopenharmony_ci	&dev_attr_gt_min_freq_mhz.attr,
4748c2ecf20Sopenharmony_ci	&dev_attr_gt_RP0_freq_mhz.attr,
4758c2ecf20Sopenharmony_ci	&dev_attr_gt_RP1_freq_mhz.attr,
4768c2ecf20Sopenharmony_ci	&dev_attr_gt_RPn_freq_mhz.attr,
4778c2ecf20Sopenharmony_ci	NULL,
4788c2ecf20Sopenharmony_ci};
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistatic const struct attribute * const vlv_attrs[] = {
4818c2ecf20Sopenharmony_ci	&dev_attr_gt_act_freq_mhz.attr,
4828c2ecf20Sopenharmony_ci	&dev_attr_gt_cur_freq_mhz.attr,
4838c2ecf20Sopenharmony_ci	&dev_attr_gt_boost_freq_mhz.attr,
4848c2ecf20Sopenharmony_ci	&dev_attr_gt_max_freq_mhz.attr,
4858c2ecf20Sopenharmony_ci	&dev_attr_gt_min_freq_mhz.attr,
4868c2ecf20Sopenharmony_ci	&dev_attr_gt_RP0_freq_mhz.attr,
4878c2ecf20Sopenharmony_ci	&dev_attr_gt_RP1_freq_mhz.attr,
4888c2ecf20Sopenharmony_ci	&dev_attr_gt_RPn_freq_mhz.attr,
4898c2ecf20Sopenharmony_ci	&dev_attr_vlv_rpe_freq_mhz.attr,
4908c2ecf20Sopenharmony_ci	NULL,
4918c2ecf20Sopenharmony_ci};
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_cistatic ssize_t error_state_read(struct file *filp, struct kobject *kobj,
4968c2ecf20Sopenharmony_ci				struct bin_attribute *attr, char *buf,
4978c2ecf20Sopenharmony_ci				loff_t off, size_t count)
4988c2ecf20Sopenharmony_ci{
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	struct device *kdev = kobj_to_dev(kobj);
5018c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
5028c2ecf20Sopenharmony_ci	struct i915_gpu_coredump *gpu;
5038c2ecf20Sopenharmony_ci	ssize_t ret = 0;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	/*
5068c2ecf20Sopenharmony_ci	 * FIXME: Concurrent clients triggering resets and reading + clearing
5078c2ecf20Sopenharmony_ci	 * dumps can cause inconsistent sysfs reads when a user calls in with a
5088c2ecf20Sopenharmony_ci	 * non-zero offset to complete a prior partial read but the
5098c2ecf20Sopenharmony_ci	 * gpu_coredump has been cleared or replaced.
5108c2ecf20Sopenharmony_ci	 */
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	gpu = i915_first_error_state(i915);
5138c2ecf20Sopenharmony_ci	if (IS_ERR(gpu)) {
5148c2ecf20Sopenharmony_ci		ret = PTR_ERR(gpu);
5158c2ecf20Sopenharmony_ci	} else if (gpu) {
5168c2ecf20Sopenharmony_ci		ret = i915_gpu_coredump_copy_to_buffer(gpu, buf, off, count);
5178c2ecf20Sopenharmony_ci		i915_gpu_coredump_put(gpu);
5188c2ecf20Sopenharmony_ci	} else {
5198c2ecf20Sopenharmony_ci		const char *str = "No error state collected\n";
5208c2ecf20Sopenharmony_ci		size_t len = strlen(str);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci		if (off < len) {
5238c2ecf20Sopenharmony_ci			ret = min_t(size_t, count, len - off);
5248c2ecf20Sopenharmony_ci			memcpy(buf, str + off, ret);
5258c2ecf20Sopenharmony_ci		}
5268c2ecf20Sopenharmony_ci	}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	return ret;
5298c2ecf20Sopenharmony_ci}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_cistatic ssize_t error_state_write(struct file *file, struct kobject *kobj,
5328c2ecf20Sopenharmony_ci				 struct bin_attribute *attr, char *buf,
5338c2ecf20Sopenharmony_ci				 loff_t off, size_t count)
5348c2ecf20Sopenharmony_ci{
5358c2ecf20Sopenharmony_ci	struct device *kdev = kobj_to_dev(kobj);
5368c2ecf20Sopenharmony_ci	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	drm_dbg(&dev_priv->drm, "Resetting error state\n");
5398c2ecf20Sopenharmony_ci	i915_reset_error_state(dev_priv);
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	return count;
5428c2ecf20Sopenharmony_ci}
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_cistatic const struct bin_attribute error_state_attr = {
5458c2ecf20Sopenharmony_ci	.attr.name = "error",
5468c2ecf20Sopenharmony_ci	.attr.mode = S_IRUSR | S_IWUSR,
5478c2ecf20Sopenharmony_ci	.size = 0,
5488c2ecf20Sopenharmony_ci	.read = error_state_read,
5498c2ecf20Sopenharmony_ci	.write = error_state_write,
5508c2ecf20Sopenharmony_ci};
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_cistatic void i915_setup_error_capture(struct device *kdev)
5538c2ecf20Sopenharmony_ci{
5548c2ecf20Sopenharmony_ci	if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr))
5558c2ecf20Sopenharmony_ci		DRM_ERROR("error_state sysfs setup failed\n");
5568c2ecf20Sopenharmony_ci}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_cistatic void i915_teardown_error_capture(struct device *kdev)
5598c2ecf20Sopenharmony_ci{
5608c2ecf20Sopenharmony_ci	sysfs_remove_bin_file(&kdev->kobj, &error_state_attr);
5618c2ecf20Sopenharmony_ci}
5628c2ecf20Sopenharmony_ci#else
5638c2ecf20Sopenharmony_cistatic void i915_setup_error_capture(struct device *kdev) {}
5648c2ecf20Sopenharmony_cistatic void i915_teardown_error_capture(struct device *kdev) {}
5658c2ecf20Sopenharmony_ci#endif
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_civoid i915_setup_sysfs(struct drm_i915_private *dev_priv)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	struct device *kdev = dev_priv->drm.primary->kdev;
5708c2ecf20Sopenharmony_ci	int ret;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
5738c2ecf20Sopenharmony_ci	if (HAS_RC6(dev_priv)) {
5748c2ecf20Sopenharmony_ci		ret = sysfs_merge_group(&kdev->kobj,
5758c2ecf20Sopenharmony_ci					&rc6_attr_group);
5768c2ecf20Sopenharmony_ci		if (ret)
5778c2ecf20Sopenharmony_ci			drm_err(&dev_priv->drm,
5788c2ecf20Sopenharmony_ci				"RC6 residency sysfs setup failed\n");
5798c2ecf20Sopenharmony_ci	}
5808c2ecf20Sopenharmony_ci	if (HAS_RC6p(dev_priv)) {
5818c2ecf20Sopenharmony_ci		ret = sysfs_merge_group(&kdev->kobj,
5828c2ecf20Sopenharmony_ci					&rc6p_attr_group);
5838c2ecf20Sopenharmony_ci		if (ret)
5848c2ecf20Sopenharmony_ci			drm_err(&dev_priv->drm,
5858c2ecf20Sopenharmony_ci				"RC6p residency sysfs setup failed\n");
5868c2ecf20Sopenharmony_ci	}
5878c2ecf20Sopenharmony_ci	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
5888c2ecf20Sopenharmony_ci		ret = sysfs_merge_group(&kdev->kobj,
5898c2ecf20Sopenharmony_ci					&media_rc6_attr_group);
5908c2ecf20Sopenharmony_ci		if (ret)
5918c2ecf20Sopenharmony_ci			drm_err(&dev_priv->drm,
5928c2ecf20Sopenharmony_ci				"Media RC6 residency sysfs setup failed\n");
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci#endif
5958c2ecf20Sopenharmony_ci	if (HAS_L3_DPF(dev_priv)) {
5968c2ecf20Sopenharmony_ci		ret = device_create_bin_file(kdev, &dpf_attrs);
5978c2ecf20Sopenharmony_ci		if (ret)
5988c2ecf20Sopenharmony_ci			drm_err(&dev_priv->drm,
5998c2ecf20Sopenharmony_ci				"l3 parity sysfs setup failed\n");
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci		if (NUM_L3_SLICES(dev_priv) > 1) {
6028c2ecf20Sopenharmony_ci			ret = device_create_bin_file(kdev,
6038c2ecf20Sopenharmony_ci						     &dpf_attrs_1);
6048c2ecf20Sopenharmony_ci			if (ret)
6058c2ecf20Sopenharmony_ci				drm_err(&dev_priv->drm,
6068c2ecf20Sopenharmony_ci					"l3 parity slice 1 setup failed\n");
6078c2ecf20Sopenharmony_ci		}
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	ret = 0;
6118c2ecf20Sopenharmony_ci	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
6128c2ecf20Sopenharmony_ci		ret = sysfs_create_files(&kdev->kobj, vlv_attrs);
6138c2ecf20Sopenharmony_ci	else if (INTEL_GEN(dev_priv) >= 6)
6148c2ecf20Sopenharmony_ci		ret = sysfs_create_files(&kdev->kobj, gen6_attrs);
6158c2ecf20Sopenharmony_ci	if (ret)
6168c2ecf20Sopenharmony_ci		drm_err(&dev_priv->drm, "RPS sysfs setup failed\n");
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	i915_setup_error_capture(kdev);
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	intel_engines_add_sysfs(dev_priv);
6218c2ecf20Sopenharmony_ci}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_civoid i915_teardown_sysfs(struct drm_i915_private *dev_priv)
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci	struct device *kdev = dev_priv->drm.primary->kdev;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	i915_teardown_error_capture(kdev);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
6308c2ecf20Sopenharmony_ci		sysfs_remove_files(&kdev->kobj, vlv_attrs);
6318c2ecf20Sopenharmony_ci	else
6328c2ecf20Sopenharmony_ci		sysfs_remove_files(&kdev->kobj, gen6_attrs);
6338c2ecf20Sopenharmony_ci	device_remove_bin_file(kdev,  &dpf_attrs_1);
6348c2ecf20Sopenharmony_ci	device_remove_bin_file(kdev,  &dpf_attrs);
6358c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
6368c2ecf20Sopenharmony_ci	sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group);
6378c2ecf20Sopenharmony_ci	sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group);
6388c2ecf20Sopenharmony_ci#endif
6398c2ecf20Sopenharmony_ci}
640