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> 3256c5098fSChris Wilson 330d6419e9SMatt Roper #include "gt/intel_gt_regs.h" 34c1132367SAndi Shyti #include "gt/intel_rc6.h" 353e7abf81SAndi Shyti #include "gt/intel_rps.h" 364ec76dbeSChris Wilson #include "gt/sysfs_engines.h" 37c1132367SAndi Shyti 380136db58SBen Widawsky #include "i915_drv.h" 39be68261dSJani Nikula #include "i915_sysfs.h" 40ecbb5fb7SJani Nikula #include "intel_pm.h" 410136db58SBen Widawsky 42*b770bcfaSAndi Shyti struct drm_i915_private *kdev_minor_to_i915(struct device *kdev) 43c49d13eeSDavid Weinehall { 44694c2828SDavid Weinehall struct drm_minor *minor = dev_get_drvdata(kdev); 45694c2828SDavid Weinehall return to_i915(minor->dev); 46c49d13eeSDavid Weinehall } 4714c8d110SDave Airlie 485ab3633dSHunt Xu #ifdef CONFIG_PM 49694c2828SDavid Weinehall static u32 calc_residency(struct drm_i915_private *dev_priv, 50f0f59a00SVille Syrjälä i915_reg_t reg) 510136db58SBen Widawsky { 5248d1c812SChris Wilson intel_wakeref_t wakeref; 53d4225a53SChris Wilson u64 res = 0; 5436cc8b96STvrtko Ursulin 55c447ff7dSDaniele Ceraolo Spurio with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref) 562cbc876dSMichał Winiarski res = intel_rc6_residency_us(&to_gt(dev_priv)->rc6, reg); 5736cc8b96STvrtko Ursulin 5836cc8b96STvrtko Ursulin return DIV_ROUND_CLOSEST_ULL(res, 1000); 590136db58SBen Widawsky } 600136db58SBen Widawsky 61177f30c6SYueHaibing static ssize_t rc6_enable_show(struct device *kdev, 62177f30c6SYueHaibing struct device_attribute *attr, char *buf) 630136db58SBen Widawsky { 64fb6db0f5SChris Wilson struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 65fb6db0f5SChris Wilson unsigned int mask; 66fb6db0f5SChris Wilson 67fb6db0f5SChris Wilson mask = 0; 68fb6db0f5SChris Wilson if (HAS_RC6(dev_priv)) 69fb6db0f5SChris Wilson mask |= BIT(0); 70fb6db0f5SChris Wilson if (HAS_RC6p(dev_priv)) 71fb6db0f5SChris Wilson mask |= BIT(1); 72fb6db0f5SChris Wilson if (HAS_RC6pp(dev_priv)) 73fb6db0f5SChris Wilson mask |= BIT(2); 74fb6db0f5SChris Wilson 7511cda496SXuezhi Zhang return sysfs_emit(buf, "%x\n", mask); 760136db58SBen Widawsky } 770136db58SBen Widawsky 78177f30c6SYueHaibing static ssize_t rc6_residency_ms_show(struct device *kdev, 79177f30c6SYueHaibing struct device_attribute *attr, char *buf) 800136db58SBen Widawsky { 81694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 82694c2828SDavid Weinehall u32 rc6_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6); 8311cda496SXuezhi Zhang return sysfs_emit(buf, "%u\n", rc6_residency); 840136db58SBen Widawsky } 850136db58SBen Widawsky 86177f30c6SYueHaibing static ssize_t rc6p_residency_ms_show(struct device *kdev, 87177f30c6SYueHaibing struct device_attribute *attr, char *buf) 880136db58SBen Widawsky { 89694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 90694c2828SDavid Weinehall u32 rc6p_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6p); 9111cda496SXuezhi Zhang return sysfs_emit(buf, "%u\n", rc6p_residency); 920136db58SBen Widawsky } 930136db58SBen Widawsky 94177f30c6SYueHaibing static ssize_t rc6pp_residency_ms_show(struct device *kdev, 95177f30c6SYueHaibing struct device_attribute *attr, char *buf) 960136db58SBen Widawsky { 97694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 98694c2828SDavid Weinehall u32 rc6pp_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6pp); 9911cda496SXuezhi Zhang return sysfs_emit(buf, "%u\n", rc6pp_residency); 1000136db58SBen Widawsky } 1010136db58SBen Widawsky 102177f30c6SYueHaibing static ssize_t media_rc6_residency_ms_show(struct device *kdev, 103177f30c6SYueHaibing struct device_attribute *attr, char *buf) 104626ad6f3SVille Syrjälä { 105694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 106694c2828SDavid Weinehall u32 rc6_residency = calc_residency(dev_priv, VLV_GT_MEDIA_RC6); 10711cda496SXuezhi Zhang return sysfs_emit(buf, "%u\n", rc6_residency); 108626ad6f3SVille Syrjälä } 109626ad6f3SVille Syrjälä 110177f30c6SYueHaibing static DEVICE_ATTR_RO(rc6_enable); 111177f30c6SYueHaibing static DEVICE_ATTR_RO(rc6_residency_ms); 112177f30c6SYueHaibing static DEVICE_ATTR_RO(rc6p_residency_ms); 113177f30c6SYueHaibing static DEVICE_ATTR_RO(rc6pp_residency_ms); 114177f30c6SYueHaibing static DEVICE_ATTR_RO(media_rc6_residency_ms); 1150136db58SBen Widawsky 1160136db58SBen Widawsky static struct attribute *rc6_attrs[] = { 1170136db58SBen Widawsky &dev_attr_rc6_enable.attr, 1180136db58SBen Widawsky &dev_attr_rc6_residency_ms.attr, 1190136db58SBen Widawsky NULL 1200136db58SBen Widawsky }; 1210136db58SBen Widawsky 1220a7a0986SArvind Yadav static const struct attribute_group rc6_attr_group = { 1230136db58SBen Widawsky .name = power_group_name, 1240136db58SBen Widawsky .attrs = rc6_attrs 1250136db58SBen Widawsky }; 12658abf1daSRodrigo Vivi 12758abf1daSRodrigo Vivi static struct attribute *rc6p_attrs[] = { 12858abf1daSRodrigo Vivi &dev_attr_rc6p_residency_ms.attr, 12958abf1daSRodrigo Vivi &dev_attr_rc6pp_residency_ms.attr, 13058abf1daSRodrigo Vivi NULL 13158abf1daSRodrigo Vivi }; 13258abf1daSRodrigo Vivi 1330a7a0986SArvind Yadav static const struct attribute_group rc6p_attr_group = { 13458abf1daSRodrigo Vivi .name = power_group_name, 13558abf1daSRodrigo Vivi .attrs = rc6p_attrs 13658abf1daSRodrigo Vivi }; 137626ad6f3SVille Syrjälä 138626ad6f3SVille Syrjälä static struct attribute *media_rc6_attrs[] = { 139626ad6f3SVille Syrjälä &dev_attr_media_rc6_residency_ms.attr, 140626ad6f3SVille Syrjälä NULL 141626ad6f3SVille Syrjälä }; 142626ad6f3SVille Syrjälä 1430a7a0986SArvind Yadav static const struct attribute_group media_rc6_attr_group = { 144626ad6f3SVille Syrjälä .name = power_group_name, 145626ad6f3SVille Syrjälä .attrs = media_rc6_attrs 146626ad6f3SVille Syrjälä }; 1478c3f929bSBen Widawsky #endif 1480136db58SBen Widawsky 149261ea7e2SChris Wilson static int l3_access_valid(struct drm_i915_private *i915, loff_t offset) 15084bc7581SBen Widawsky { 151261ea7e2SChris Wilson if (!HAS_L3_DPF(i915)) 15284bc7581SBen Widawsky return -EPERM; 15384bc7581SBen Widawsky 154261ea7e2SChris Wilson if (!IS_ALIGNED(offset, sizeof(u32))) 15584bc7581SBen Widawsky return -EINVAL; 15684bc7581SBen Widawsky 15784bc7581SBen Widawsky if (offset >= GEN7_L3LOG_SIZE) 15884bc7581SBen Widawsky return -ENXIO; 15984bc7581SBen Widawsky 16084bc7581SBen Widawsky return 0; 16184bc7581SBen Widawsky } 16284bc7581SBen Widawsky 16384bc7581SBen Widawsky static ssize_t 16484bc7581SBen Widawsky i915_l3_read(struct file *filp, struct kobject *kobj, 16584bc7581SBen Widawsky struct bin_attribute *attr, char *buf, 16684bc7581SBen Widawsky loff_t offset, size_t count) 16784bc7581SBen Widawsky { 168c49d13eeSDavid Weinehall struct device *kdev = kobj_to_dev(kobj); 169261ea7e2SChris Wilson struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 17035a85ac6SBen Widawsky int slice = (int)(uintptr_t)attr->private; 1713ccfd19dSBen Widawsky int ret; 17284bc7581SBen Widawsky 173261ea7e2SChris Wilson ret = l3_access_valid(i915, offset); 17484bc7581SBen Widawsky if (ret) 17584bc7581SBen Widawsky return ret; 17684bc7581SBen Widawsky 177261ea7e2SChris Wilson count = round_down(count, sizeof(u32)); 178e5ad4026SDan Carpenter count = min_t(size_t, GEN7_L3LOG_SIZE - offset, count); 1791c966dd2SBen Widawsky memset(buf, 0, count); 1801c966dd2SBen Widawsky 181a4e7ccdaSChris Wilson spin_lock(&i915->gem.contexts.lock); 182261ea7e2SChris Wilson if (i915->l3_parity.remap_info[slice]) 183261ea7e2SChris Wilson memcpy(buf, 184261ea7e2SChris Wilson i915->l3_parity.remap_info[slice] + offset / sizeof(u32), 185261ea7e2SChris Wilson count); 186a4e7ccdaSChris Wilson spin_unlock(&i915->gem.contexts.lock); 18784bc7581SBen Widawsky 1881c966dd2SBen Widawsky return count; 18984bc7581SBen Widawsky } 19084bc7581SBen Widawsky 19184bc7581SBen Widawsky static ssize_t 19284bc7581SBen Widawsky i915_l3_write(struct file *filp, struct kobject *kobj, 19384bc7581SBen Widawsky struct bin_attribute *attr, char *buf, 19484bc7581SBen Widawsky loff_t offset, size_t count) 19584bc7581SBen Widawsky { 196c49d13eeSDavid Weinehall struct device *kdev = kobj_to_dev(kobj); 197261ea7e2SChris Wilson struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 19835a85ac6SBen Widawsky int slice = (int)(uintptr_t)attr->private; 199a4e7ccdaSChris Wilson u32 *remap_info, *freeme = NULL; 200261ea7e2SChris Wilson struct i915_gem_context *ctx; 20184bc7581SBen Widawsky int ret; 20284bc7581SBen Widawsky 203261ea7e2SChris Wilson ret = l3_access_valid(i915, offset); 20484bc7581SBen Widawsky if (ret) 20584bc7581SBen Widawsky return ret; 20684bc7581SBen Widawsky 207261ea7e2SChris Wilson if (count < sizeof(u32)) 208261ea7e2SChris Wilson return -EINVAL; 209261ea7e2SChris Wilson 210a4e7ccdaSChris Wilson remap_info = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); 211a4e7ccdaSChris Wilson if (!remap_info) 212a4e7ccdaSChris Wilson return -ENOMEM; 21384bc7581SBen Widawsky 214a4e7ccdaSChris Wilson spin_lock(&i915->gem.contexts.lock); 215a4e7ccdaSChris Wilson 216a4e7ccdaSChris Wilson if (i915->l3_parity.remap_info[slice]) { 217a4e7ccdaSChris Wilson freeme = remap_info; 218a4e7ccdaSChris Wilson remap_info = i915->l3_parity.remap_info[slice]; 219a4e7ccdaSChris Wilson } else { 220a4e7ccdaSChris Wilson i915->l3_parity.remap_info[slice] = remap_info; 22184bc7581SBen Widawsky } 22284bc7581SBen Widawsky 223261ea7e2SChris Wilson count = round_down(count, sizeof(u32)); 224a4e7ccdaSChris Wilson memcpy(remap_info + offset / sizeof(u32), buf, count); 225261ea7e2SChris Wilson 226261ea7e2SChris Wilson /* NB: We defer the remapping until we switch to the context */ 227a4e7ccdaSChris Wilson list_for_each_entry(ctx, &i915->gem.contexts.list, link) 228261ea7e2SChris Wilson ctx->remap_slice |= BIT(slice); 229261ea7e2SChris Wilson 230a4e7ccdaSChris Wilson spin_unlock(&i915->gem.contexts.lock); 231a4e7ccdaSChris Wilson kfree(freeme); 232a4e7ccdaSChris Wilson 233261ea7e2SChris Wilson /* 234261ea7e2SChris Wilson * TODO: Ideally we really want a GPU reset here to make sure errors 23584bc7581SBen Widawsky * aren't propagated. Since I cannot find a stable way to reset the GPU 23684bc7581SBen Widawsky * at this point it is left as a TODO. 23784bc7581SBen Widawsky */ 23884bc7581SBen Widawsky 239a4e7ccdaSChris Wilson return count; 24084bc7581SBen Widawsky } 24184bc7581SBen Widawsky 24259f3da1eSBhumika Goyal static const struct bin_attribute dpf_attrs = { 24384bc7581SBen Widawsky .attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)}, 24484bc7581SBen Widawsky .size = GEN7_L3LOG_SIZE, 24584bc7581SBen Widawsky .read = i915_l3_read, 24684bc7581SBen Widawsky .write = i915_l3_write, 24735a85ac6SBen Widawsky .mmap = NULL, 24835a85ac6SBen Widawsky .private = (void *)0 24935a85ac6SBen Widawsky }; 25035a85ac6SBen Widawsky 25159f3da1eSBhumika Goyal static const struct bin_attribute dpf_attrs_1 = { 25235a85ac6SBen Widawsky .attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)}, 25335a85ac6SBen Widawsky .size = GEN7_L3LOG_SIZE, 25435a85ac6SBen Widawsky .read = i915_l3_read, 25535a85ac6SBen Widawsky .write = i915_l3_write, 25635a85ac6SBen Widawsky .mmap = NULL, 25735a85ac6SBen Widawsky .private = (void *)1 25884bc7581SBen Widawsky }; 25984bc7581SBen Widawsky 260c8c972ebSVille Syrjälä static ssize_t gt_act_freq_mhz_show(struct device *kdev, 261df6eedc8SBen Widawsky struct device_attribute *attr, char *buf) 262df6eedc8SBen Widawsky { 263e03512edSAndi Shyti struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 2642cbc876dSMichał Winiarski struct intel_rps *rps = &to_gt(i915)->rps; 265df6eedc8SBen Widawsky 26611cda496SXuezhi Zhang return sysfs_emit(buf, "%d\n", intel_rps_read_actual_frequency(rps)); 267c8c972ebSVille Syrjälä } 268c8c972ebSVille Syrjälä 269c8c972ebSVille Syrjälä static ssize_t gt_cur_freq_mhz_show(struct device *kdev, 270c8c972ebSVille Syrjälä struct device_attribute *attr, char *buf) 271c8c972ebSVille Syrjälä { 272e03512edSAndi Shyti struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 2732cbc876dSMichał Winiarski struct intel_rps *rps = &to_gt(i915)->rps; 274c8c972ebSVille Syrjälä 27541e5c17eSVinay Belgaumkar return sysfs_emit(buf, "%d\n", intel_rps_get_requested_frequency(rps)); 276df6eedc8SBen Widawsky } 277df6eedc8SBen Widawsky 27829ecd78dSChris Wilson static ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) 27929ecd78dSChris Wilson { 280e03512edSAndi Shyti struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 2812cbc876dSMichał Winiarski struct intel_rps *rps = &to_gt(i915)->rps; 28229ecd78dSChris Wilson 2831448d5c4SVinay Belgaumkar return sysfs_emit(buf, "%d\n", intel_rps_get_boost_frequency(rps)); 28429ecd78dSChris Wilson } 28529ecd78dSChris Wilson 28629ecd78dSChris Wilson static ssize_t gt_boost_freq_mhz_store(struct device *kdev, 28729ecd78dSChris Wilson struct device_attribute *attr, 28829ecd78dSChris Wilson const char *buf, size_t count) 28929ecd78dSChris Wilson { 290694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 2912cbc876dSMichał Winiarski struct intel_rps *rps = &to_gt(dev_priv)->rps; 29229ecd78dSChris Wilson ssize_t ret; 29359cd31f1SChris Wilson u32 val; 29429ecd78dSChris Wilson 29529ecd78dSChris Wilson ret = kstrtou32(buf, 0, &val); 29629ecd78dSChris Wilson if (ret) 29729ecd78dSChris Wilson return ret; 29829ecd78dSChris Wilson 2991448d5c4SVinay Belgaumkar ret = intel_rps_set_boost_frequency(rps, val); 30029ecd78dSChris Wilson 3011448d5c4SVinay Belgaumkar return ret ?: count; 30229ecd78dSChris Wilson } 30329ecd78dSChris Wilson 30497e4eed7SChris Wilson static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, 30597e4eed7SChris Wilson struct device_attribute *attr, char *buf) 30697e4eed7SChris Wilson { 307694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 3082cbc876dSMichał Winiarski struct intel_rps *rps = &to_gt(dev_priv)->rps; 30997e4eed7SChris Wilson 31011cda496SXuezhi Zhang return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->efficient_freq)); 31197e4eed7SChris Wilson } 31297e4eed7SChris Wilson 313df6eedc8SBen Widawsky static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) 314df6eedc8SBen Widawsky { 315694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 3162cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 31741e5c17eSVinay Belgaumkar struct intel_rps *rps = >->rps; 318df6eedc8SBen Widawsky 31941e5c17eSVinay Belgaumkar return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps)); 320df6eedc8SBen Widawsky } 321df6eedc8SBen Widawsky 32246ddf194SBen Widawsky static ssize_t gt_max_freq_mhz_store(struct device *kdev, 32346ddf194SBen Widawsky struct device_attribute *attr, 32446ddf194SBen Widawsky const char *buf, size_t count) 32546ddf194SBen Widawsky { 326694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 3272cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(dev_priv); 32841e5c17eSVinay Belgaumkar struct intel_rps *rps = >->rps; 32946ddf194SBen Widawsky ssize_t ret; 3303e7abf81SAndi Shyti u32 val; 33146ddf194SBen Widawsky 33246ddf194SBen Widawsky ret = kstrtou32(buf, 0, &val); 33346ddf194SBen Widawsky if (ret) 33446ddf194SBen Widawsky return ret; 33546ddf194SBen Widawsky 33641e5c17eSVinay Belgaumkar ret = intel_rps_set_max_frequency(rps, val); 337933bfb44SSagar Arun Kamble 3389fcee2f7SChris Wilson return ret ?: count; 33946ddf194SBen Widawsky } 34046ddf194SBen Widawsky 341df6eedc8SBen Widawsky static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) 342df6eedc8SBen Widawsky { 34341e5c17eSVinay Belgaumkar struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 3442cbc876dSMichał Winiarski struct intel_gt *gt = to_gt(i915); 34541e5c17eSVinay Belgaumkar struct intel_rps *rps = >->rps; 346df6eedc8SBen Widawsky 34741e5c17eSVinay Belgaumkar return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps)); 348df6eedc8SBen Widawsky } 349df6eedc8SBen Widawsky 35046ddf194SBen Widawsky static ssize_t gt_min_freq_mhz_store(struct device *kdev, 35146ddf194SBen Widawsky struct device_attribute *attr, 35246ddf194SBen Widawsky const char *buf, size_t count) 35346ddf194SBen Widawsky { 35441e5c17eSVinay Belgaumkar struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 3552cbc876dSMichał Winiarski struct intel_rps *rps = &to_gt(i915)->rps; 35646ddf194SBen Widawsky ssize_t ret; 3573e7abf81SAndi Shyti u32 val; 35846ddf194SBen Widawsky 35946ddf194SBen Widawsky ret = kstrtou32(buf, 0, &val); 36046ddf194SBen Widawsky if (ret) 36146ddf194SBen Widawsky return ret; 36246ddf194SBen Widawsky 36341e5c17eSVinay Belgaumkar ret = intel_rps_set_min_frequency(rps, val); 364933bfb44SSagar Arun Kamble 3659fcee2f7SChris Wilson return ret ?: count; 36646ddf194SBen Widawsky } 36746ddf194SBen Widawsky 368c828a892SJoe Perches static DEVICE_ATTR_RO(gt_act_freq_mhz); 369c828a892SJoe Perches static DEVICE_ATTR_RO(gt_cur_freq_mhz); 370b6b996b6SJoe Perches static DEVICE_ATTR_RW(gt_boost_freq_mhz); 371b6b996b6SJoe Perches static DEVICE_ATTR_RW(gt_max_freq_mhz); 372b6b996b6SJoe Perches static DEVICE_ATTR_RW(gt_min_freq_mhz); 373df6eedc8SBen Widawsky 374c828a892SJoe Perches static DEVICE_ATTR_RO(vlv_rpe_freq_mhz); 375ac6ae347SBen Widawsky 376ac6ae347SBen Widawsky static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf); 377ac6ae347SBen Widawsky static DEVICE_ATTR(gt_RP0_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); 378ac6ae347SBen Widawsky static DEVICE_ATTR(gt_RP1_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); 379ac6ae347SBen Widawsky static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); 380ac6ae347SBen Widawsky 381ac6ae347SBen Widawsky /* For now we have a static number of RP states */ 382ac6ae347SBen Widawsky static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) 383ac6ae347SBen Widawsky { 384694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 3852cbc876dSMichał Winiarski struct intel_rps *rps = &to_gt(dev_priv)->rps; 386bc4d91f6SAkash Goel u32 val; 387ac6ae347SBen Widawsky 388bc4d91f6SAkash Goel if (attr == &dev_attr_gt_RP0_freq_mhz) 38941e5c17eSVinay Belgaumkar val = intel_rps_get_rp0_frequency(rps); 390bc4d91f6SAkash Goel else if (attr == &dev_attr_gt_RP1_freq_mhz) 39141e5c17eSVinay Belgaumkar val = intel_rps_get_rp1_frequency(rps); 392bc4d91f6SAkash Goel else if (attr == &dev_attr_gt_RPn_freq_mhz) 39341e5c17eSVinay Belgaumkar val = intel_rps_get_rpn_frequency(rps); 39474c4f62bSDeepak S else 395ac6ae347SBen Widawsky BUG(); 396bc4d91f6SAkash Goel 39711cda496SXuezhi Zhang return sysfs_emit(buf, "%d\n", val); 398ac6ae347SBen Widawsky } 399ac6ae347SBen Widawsky 400e1215de8SJani Nikula static const struct attribute * const gen6_attrs[] = { 401c8c972ebSVille Syrjälä &dev_attr_gt_act_freq_mhz.attr, 402df6eedc8SBen Widawsky &dev_attr_gt_cur_freq_mhz.attr, 40329ecd78dSChris Wilson &dev_attr_gt_boost_freq_mhz.attr, 404df6eedc8SBen Widawsky &dev_attr_gt_max_freq_mhz.attr, 405df6eedc8SBen Widawsky &dev_attr_gt_min_freq_mhz.attr, 406ac6ae347SBen Widawsky &dev_attr_gt_RP0_freq_mhz.attr, 407ac6ae347SBen Widawsky &dev_attr_gt_RP1_freq_mhz.attr, 408ac6ae347SBen Widawsky &dev_attr_gt_RPn_freq_mhz.attr, 409df6eedc8SBen Widawsky NULL, 410df6eedc8SBen Widawsky }; 411df6eedc8SBen Widawsky 412e1215de8SJani Nikula static const struct attribute * const vlv_attrs[] = { 413c8c972ebSVille Syrjälä &dev_attr_gt_act_freq_mhz.attr, 41497e4eed7SChris Wilson &dev_attr_gt_cur_freq_mhz.attr, 41529ecd78dSChris Wilson &dev_attr_gt_boost_freq_mhz.attr, 41697e4eed7SChris Wilson &dev_attr_gt_max_freq_mhz.attr, 41797e4eed7SChris Wilson &dev_attr_gt_min_freq_mhz.attr, 41874c4f62bSDeepak S &dev_attr_gt_RP0_freq_mhz.attr, 41974c4f62bSDeepak S &dev_attr_gt_RP1_freq_mhz.attr, 42074c4f62bSDeepak S &dev_attr_gt_RPn_freq_mhz.attr, 42197e4eed7SChris Wilson &dev_attr_vlv_rpe_freq_mhz.attr, 42297e4eed7SChris Wilson NULL, 42397e4eed7SChris Wilson }; 42497e4eed7SChris Wilson 42598a2f411SChris Wilson #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) 42698a2f411SChris Wilson 427ef86ddceSMika Kuoppala static ssize_t error_state_read(struct file *filp, struct kobject *kobj, 428ef86ddceSMika Kuoppala struct bin_attribute *attr, char *buf, 429ef86ddceSMika Kuoppala loff_t off, size_t count) 430ef86ddceSMika Kuoppala { 431ef86ddceSMika Kuoppala 432657fb5fbSGeliang Tang struct device *kdev = kobj_to_dev(kobj); 4330e39037bSChris Wilson struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); 434742379c0SChris Wilson struct i915_gpu_coredump *gpu; 4355a4c6f1bSChris Wilson ssize_t ret; 436ef86ddceSMika Kuoppala 4370e39037bSChris Wilson gpu = i915_first_error_state(i915); 438e6154e4cSChris Wilson if (IS_ERR(gpu)) { 439e6154e4cSChris Wilson ret = PTR_ERR(gpu); 440e6154e4cSChris Wilson } else if (gpu) { 441742379c0SChris Wilson ret = i915_gpu_coredump_copy_to_buffer(gpu, buf, off, count); 442742379c0SChris Wilson i915_gpu_coredump_put(gpu); 4430e39037bSChris Wilson } else { 4440e39037bSChris Wilson const char *str = "No error state collected\n"; 4450e39037bSChris Wilson size_t len = strlen(str); 4460e39037bSChris Wilson 4470e39037bSChris Wilson ret = min_t(size_t, count, len - off); 4480e39037bSChris Wilson memcpy(buf, str + off, ret); 4490e39037bSChris Wilson } 450ef86ddceSMika Kuoppala 4515a4c6f1bSChris Wilson return ret; 452ef86ddceSMika Kuoppala } 453ef86ddceSMika Kuoppala 454ef86ddceSMika Kuoppala static ssize_t error_state_write(struct file *file, struct kobject *kobj, 455ef86ddceSMika Kuoppala struct bin_attribute *attr, char *buf, 456ef86ddceSMika Kuoppala loff_t off, size_t count) 457ef86ddceSMika Kuoppala { 458657fb5fbSGeliang Tang struct device *kdev = kobj_to_dev(kobj); 459694c2828SDavid Weinehall struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); 460ef86ddceSMika Kuoppala 46100376ccfSWambui Karuga drm_dbg(&dev_priv->drm, "Resetting error state\n"); 4625a4c6f1bSChris Wilson i915_reset_error_state(dev_priv); 463ef86ddceSMika Kuoppala 464ef86ddceSMika Kuoppala return count; 465ef86ddceSMika Kuoppala } 466ef86ddceSMika Kuoppala 46759f3da1eSBhumika Goyal static const struct bin_attribute error_state_attr = { 468ef86ddceSMika Kuoppala .attr.name = "error", 469ef86ddceSMika Kuoppala .attr.mode = S_IRUSR | S_IWUSR, 470ef86ddceSMika Kuoppala .size = 0, 471ef86ddceSMika Kuoppala .read = error_state_read, 472ef86ddceSMika Kuoppala .write = error_state_write, 473ef86ddceSMika Kuoppala }; 474ef86ddceSMika Kuoppala 47598a2f411SChris Wilson static void i915_setup_error_capture(struct device *kdev) 47698a2f411SChris Wilson { 47798a2f411SChris Wilson if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr)) 47898a2f411SChris Wilson DRM_ERROR("error_state sysfs setup failed\n"); 47998a2f411SChris Wilson } 48098a2f411SChris Wilson 48198a2f411SChris Wilson static void i915_teardown_error_capture(struct device *kdev) 48298a2f411SChris Wilson { 48398a2f411SChris Wilson sysfs_remove_bin_file(&kdev->kobj, &error_state_attr); 48498a2f411SChris Wilson } 48598a2f411SChris Wilson #else 48698a2f411SChris Wilson static void i915_setup_error_capture(struct device *kdev) {} 48798a2f411SChris Wilson static void i915_teardown_error_capture(struct device *kdev) {} 48898a2f411SChris Wilson #endif 48998a2f411SChris Wilson 490694c2828SDavid Weinehall void i915_setup_sysfs(struct drm_i915_private *dev_priv) 4910136db58SBen Widawsky { 492694c2828SDavid Weinehall struct device *kdev = dev_priv->drm.primary->kdev; 4930136db58SBen Widawsky int ret; 4940136db58SBen Widawsky 4958c3f929bSBen Widawsky #ifdef CONFIG_PM 496694c2828SDavid Weinehall if (HAS_RC6(dev_priv)) { 497694c2828SDavid Weinehall ret = sysfs_merge_group(&kdev->kobj, 498112abd29SDaniel Vetter &rc6_attr_group); 4990136db58SBen Widawsky if (ret) 50000376ccfSWambui Karuga drm_err(&dev_priv->drm, 50100376ccfSWambui Karuga "RC6 residency sysfs setup failed\n"); 502112abd29SDaniel Vetter } 503694c2828SDavid Weinehall if (HAS_RC6p(dev_priv)) { 504694c2828SDavid Weinehall ret = sysfs_merge_group(&kdev->kobj, 50558abf1daSRodrigo Vivi &rc6p_attr_group); 50658abf1daSRodrigo Vivi if (ret) 50700376ccfSWambui Karuga drm_err(&dev_priv->drm, 50800376ccfSWambui Karuga "RC6p residency sysfs setup failed\n"); 50958abf1daSRodrigo Vivi } 510694c2828SDavid Weinehall if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { 511694c2828SDavid Weinehall ret = sysfs_merge_group(&kdev->kobj, 512626ad6f3SVille Syrjälä &media_rc6_attr_group); 513626ad6f3SVille Syrjälä if (ret) 51400376ccfSWambui Karuga drm_err(&dev_priv->drm, 51500376ccfSWambui Karuga "Media RC6 residency sysfs setup failed\n"); 516626ad6f3SVille Syrjälä } 5178c3f929bSBen Widawsky #endif 518694c2828SDavid Weinehall if (HAS_L3_DPF(dev_priv)) { 519694c2828SDavid Weinehall ret = device_create_bin_file(kdev, &dpf_attrs); 52084bc7581SBen Widawsky if (ret) 52100376ccfSWambui Karuga drm_err(&dev_priv->drm, 52200376ccfSWambui Karuga "l3 parity sysfs setup failed\n"); 52335a85ac6SBen Widawsky 524694c2828SDavid Weinehall if (NUM_L3_SLICES(dev_priv) > 1) { 525694c2828SDavid Weinehall ret = device_create_bin_file(kdev, 52635a85ac6SBen Widawsky &dpf_attrs_1); 52735a85ac6SBen Widawsky if (ret) 52800376ccfSWambui Karuga drm_err(&dev_priv->drm, 52900376ccfSWambui Karuga "l3 parity slice 1 setup failed\n"); 53035a85ac6SBen Widawsky } 5310136db58SBen Widawsky } 532df6eedc8SBen Widawsky 53397e4eed7SChris Wilson ret = 0; 534694c2828SDavid Weinehall if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 535694c2828SDavid Weinehall ret = sysfs_create_files(&kdev->kobj, vlv_attrs); 536651e7d48SLucas De Marchi else if (GRAPHICS_VER(dev_priv) >= 6) 537694c2828SDavid Weinehall ret = sysfs_create_files(&kdev->kobj, gen6_attrs); 538df6eedc8SBen Widawsky if (ret) 53900376ccfSWambui Karuga drm_err(&dev_priv->drm, "RPS sysfs setup failed\n"); 540ef86ddceSMika Kuoppala 541*b770bcfaSAndi Shyti dev_priv->sysfs_gt = kobject_create_and_add("gt", &kdev->kobj); 542*b770bcfaSAndi Shyti if (!dev_priv->sysfs_gt) 543*b770bcfaSAndi Shyti drm_warn(&dev_priv->drm, 544*b770bcfaSAndi Shyti "failed to register GT sysfs directory\n"); 545*b770bcfaSAndi Shyti 54698a2f411SChris Wilson i915_setup_error_capture(kdev); 5474ec76dbeSChris Wilson 5484ec76dbeSChris Wilson intel_engines_add_sysfs(dev_priv); 549112abd29SDaniel Vetter } 5500136db58SBen Widawsky 551694c2828SDavid Weinehall void i915_teardown_sysfs(struct drm_i915_private *dev_priv) 5520136db58SBen Widawsky { 553694c2828SDavid Weinehall struct device *kdev = dev_priv->drm.primary->kdev; 554694c2828SDavid Weinehall 55598a2f411SChris Wilson i915_teardown_error_capture(kdev); 55698a2f411SChris Wilson 557694c2828SDavid Weinehall if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 558694c2828SDavid Weinehall sysfs_remove_files(&kdev->kobj, vlv_attrs); 55997e4eed7SChris Wilson else 560694c2828SDavid Weinehall sysfs_remove_files(&kdev->kobj, gen6_attrs); 561694c2828SDavid Weinehall device_remove_bin_file(kdev, &dpf_attrs_1); 562694c2828SDavid Weinehall device_remove_bin_file(kdev, &dpf_attrs); 563853c70e8SBen Widawsky #ifdef CONFIG_PM 564694c2828SDavid Weinehall sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group); 565694c2828SDavid Weinehall sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group); 566853c70e8SBen Widawsky #endif 5670136db58SBen Widawsky } 568