0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <linux/device.h>
0029 #include <linux/module.h>
0030 #include <linux/stat.h>
0031 #include <linux/sysfs.h>
0032
0033 #include "gt/intel_gt_regs.h"
0034 #include "gt/intel_rc6.h"
0035 #include "gt/intel_rps.h"
0036 #include "gt/sysfs_engines.h"
0037
0038 #include "i915_drv.h"
0039 #include "i915_sysfs.h"
0040 #include "intel_pm.h"
0041
0042 struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
0043 {
0044 struct drm_minor *minor = dev_get_drvdata(kdev);
0045 return to_i915(minor->dev);
0046 }
0047
0048 static int l3_access_valid(struct drm_i915_private *i915, loff_t offset)
0049 {
0050 if (!HAS_L3_DPF(i915))
0051 return -EPERM;
0052
0053 if (!IS_ALIGNED(offset, sizeof(u32)))
0054 return -EINVAL;
0055
0056 if (offset >= GEN7_L3LOG_SIZE)
0057 return -ENXIO;
0058
0059 return 0;
0060 }
0061
0062 static ssize_t
0063 i915_l3_read(struct file *filp, struct kobject *kobj,
0064 struct bin_attribute *attr, char *buf,
0065 loff_t offset, size_t count)
0066 {
0067 struct device *kdev = kobj_to_dev(kobj);
0068 struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
0069 int slice = (int)(uintptr_t)attr->private;
0070 int ret;
0071
0072 ret = l3_access_valid(i915, offset);
0073 if (ret)
0074 return ret;
0075
0076 count = round_down(count, sizeof(u32));
0077 count = min_t(size_t, GEN7_L3LOG_SIZE - offset, count);
0078 memset(buf, 0, count);
0079
0080 spin_lock(&i915->gem.contexts.lock);
0081 if (i915->l3_parity.remap_info[slice])
0082 memcpy(buf,
0083 i915->l3_parity.remap_info[slice] + offset / sizeof(u32),
0084 count);
0085 spin_unlock(&i915->gem.contexts.lock);
0086
0087 return count;
0088 }
0089
0090 static ssize_t
0091 i915_l3_write(struct file *filp, struct kobject *kobj,
0092 struct bin_attribute *attr, char *buf,
0093 loff_t offset, size_t count)
0094 {
0095 struct device *kdev = kobj_to_dev(kobj);
0096 struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
0097 int slice = (int)(uintptr_t)attr->private;
0098 u32 *remap_info, *freeme = NULL;
0099 struct i915_gem_context *ctx;
0100 int ret;
0101
0102 ret = l3_access_valid(i915, offset);
0103 if (ret)
0104 return ret;
0105
0106 if (count < sizeof(u32))
0107 return -EINVAL;
0108
0109 remap_info = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
0110 if (!remap_info)
0111 return -ENOMEM;
0112
0113 spin_lock(&i915->gem.contexts.lock);
0114
0115 if (i915->l3_parity.remap_info[slice]) {
0116 freeme = remap_info;
0117 remap_info = i915->l3_parity.remap_info[slice];
0118 } else {
0119 i915->l3_parity.remap_info[slice] = remap_info;
0120 }
0121
0122 count = round_down(count, sizeof(u32));
0123 memcpy(remap_info + offset / sizeof(u32), buf, count);
0124
0125
0126 list_for_each_entry(ctx, &i915->gem.contexts.list, link)
0127 ctx->remap_slice |= BIT(slice);
0128
0129 spin_unlock(&i915->gem.contexts.lock);
0130 kfree(freeme);
0131
0132
0133
0134
0135
0136
0137
0138 return count;
0139 }
0140
0141 static const struct bin_attribute dpf_attrs = {
0142 .attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)},
0143 .size = GEN7_L3LOG_SIZE,
0144 .read = i915_l3_read,
0145 .write = i915_l3_write,
0146 .mmap = NULL,
0147 .private = (void *)0
0148 };
0149
0150 static const struct bin_attribute dpf_attrs_1 = {
0151 .attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)},
0152 .size = GEN7_L3LOG_SIZE,
0153 .read = i915_l3_read,
0154 .write = i915_l3_write,
0155 .mmap = NULL,
0156 .private = (void *)1
0157 };
0158
0159 #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
0160
0161 static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
0162 struct bin_attribute *attr, char *buf,
0163 loff_t off, size_t count)
0164 {
0165
0166 struct device *kdev = kobj_to_dev(kobj);
0167 struct drm_i915_private *i915 = kdev_minor_to_i915(kdev);
0168 struct i915_gpu_coredump *gpu;
0169 ssize_t ret = 0;
0170
0171
0172
0173
0174
0175
0176
0177
0178 gpu = i915_first_error_state(i915);
0179 if (IS_ERR(gpu)) {
0180 ret = PTR_ERR(gpu);
0181 } else if (gpu) {
0182 ret = i915_gpu_coredump_copy_to_buffer(gpu, buf, off, count);
0183 i915_gpu_coredump_put(gpu);
0184 } else {
0185 const char *str = "No error state collected\n";
0186 size_t len = strlen(str);
0187
0188 if (off < len) {
0189 ret = min_t(size_t, count, len - off);
0190 memcpy(buf, str + off, ret);
0191 }
0192 }
0193
0194 return ret;
0195 }
0196
0197 static ssize_t error_state_write(struct file *file, struct kobject *kobj,
0198 struct bin_attribute *attr, char *buf,
0199 loff_t off, size_t count)
0200 {
0201 struct device *kdev = kobj_to_dev(kobj);
0202 struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
0203
0204 drm_dbg(&dev_priv->drm, "Resetting error state\n");
0205 i915_reset_error_state(dev_priv);
0206
0207 return count;
0208 }
0209
0210 static const struct bin_attribute error_state_attr = {
0211 .attr.name = "error",
0212 .attr.mode = S_IRUSR | S_IWUSR,
0213 .size = 0,
0214 .read = error_state_read,
0215 .write = error_state_write,
0216 };
0217
0218 static void i915_setup_error_capture(struct device *kdev)
0219 {
0220 if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr))
0221 DRM_ERROR("error_state sysfs setup failed\n");
0222 }
0223
0224 static void i915_teardown_error_capture(struct device *kdev)
0225 {
0226 sysfs_remove_bin_file(&kdev->kobj, &error_state_attr);
0227 }
0228 #else
0229 static void i915_setup_error_capture(struct device *kdev) {}
0230 static void i915_teardown_error_capture(struct device *kdev) {}
0231 #endif
0232
0233 void i915_setup_sysfs(struct drm_i915_private *dev_priv)
0234 {
0235 struct device *kdev = dev_priv->drm.primary->kdev;
0236 int ret;
0237
0238 if (HAS_L3_DPF(dev_priv)) {
0239 ret = device_create_bin_file(kdev, &dpf_attrs);
0240 if (ret)
0241 drm_err(&dev_priv->drm,
0242 "l3 parity sysfs setup failed\n");
0243
0244 if (NUM_L3_SLICES(dev_priv) > 1) {
0245 ret = device_create_bin_file(kdev,
0246 &dpf_attrs_1);
0247 if (ret)
0248 drm_err(&dev_priv->drm,
0249 "l3 parity slice 1 setup failed\n");
0250 }
0251 }
0252
0253 dev_priv->sysfs_gt = kobject_create_and_add("gt", &kdev->kobj);
0254 if (!dev_priv->sysfs_gt)
0255 drm_warn(&dev_priv->drm,
0256 "failed to register GT sysfs directory\n");
0257
0258 i915_setup_error_capture(kdev);
0259
0260 intel_engines_add_sysfs(dev_priv);
0261 }
0262
0263 void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
0264 {
0265 struct device *kdev = dev_priv->drm.primary->kdev;
0266
0267 i915_teardown_error_capture(kdev);
0268
0269 device_remove_bin_file(kdev, &dpf_attrs_1);
0270 device_remove_bin_file(kdev, &dpf_attrs);
0271
0272 kobject_put(dev_priv->sysfs_gt);
0273 }