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