| From 76f8e27cd3b6f23dcf858f9adc0179cfd98cefb8 Mon Sep 17 00:00:00 2001 |
| From: Mika Kuoppala <mika.kuoppala@linux.intel.com> |
| Date: Thu, 6 Jun 2013 17:38:54 +0300 |
| Subject: drm/i915: add error_state sysfs entry |
| |
| As getting error state doesn't anymore require big kmallocs, |
| make error state accessible also from sysfs. |
| |
| v2: - error state clearing (Chris Wilson) |
| - user hint, proper access mode bits and name (Daniel Vetter) |
| |
| v3: release resources in proper order (Chris Wilson) |
| |
| Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com> |
| Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> |
| [danvet: Apply Chris' s/error_state/error/ bikeshed on the sysfs |
| name. Also update the dmesg message, spotted by Chris.] |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| |
| (cherry picked from commit ef86ddced720fddc3835558447a7f594d3609c73) |
| (cherry picked from drm-intel-next-queued) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/gpu/drm/i915/i915_irq.c | 3 +- |
| drivers/gpu/drm/i915/i915_sysfs.c | 71 +++++++++++++++++++++++++++++++++++++++ |
| 2 files changed, 72 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c |
| index a53d1d3040eb..7564063ecc70 100644 |
| --- a/drivers/gpu/drm/i915/i915_irq.c |
| +++ b/drivers/gpu/drm/i915/i915_irq.c |
| @@ -1955,8 +1955,7 @@ static void i915_capture_error_state(struct drm_device *dev) |
| } |
| |
| DRM_INFO("capturing error event; look for more information in " |
| - "/sys/kernel/debug/dri/%d/i915_error_state\n", |
| - dev->primary->index); |
| + "/sys/class/drm/card%d/error\n", dev->primary->index); |
| |
| kref_init(&error->ref); |
| error->eir = I915_READ(EIR); |
| diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c |
| index 6875b5654c63..a777e7f3b0df 100644 |
| --- a/drivers/gpu/drm/i915/i915_sysfs.c |
| +++ b/drivers/gpu/drm/i915/i915_sysfs.c |
| @@ -409,6 +409,71 @@ static const struct attribute *gen6_attrs[] = { |
| NULL, |
| }; |
| |
| +static ssize_t error_state_read(struct file *filp, struct kobject *kobj, |
| + struct bin_attribute *attr, char *buf, |
| + loff_t off, size_t count) |
| +{ |
| + |
| + struct device *kdev = container_of(kobj, struct device, kobj); |
| + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); |
| + struct drm_device *dev = minor->dev; |
| + struct i915_error_state_file_priv error_priv; |
| + struct drm_i915_error_state_buf error_str; |
| + ssize_t ret_count = 0; |
| + int ret; |
| + |
| + memset(&error_priv, 0, sizeof(error_priv)); |
| + |
| + ret = i915_error_state_buf_init(&error_str, count, off); |
| + if (ret) |
| + return ret; |
| + |
| + error_priv.dev = dev; |
| + i915_error_state_get(dev, &error_priv); |
| + |
| + ret = i915_error_state_to_str(&error_str, &error_priv); |
| + if (ret) |
| + goto out; |
| + |
| + ret_count = count < error_str.bytes ? count : error_str.bytes; |
| + |
| + memcpy(buf, error_str.buf, ret_count); |
| +out: |
| + i915_error_state_put(&error_priv); |
| + i915_error_state_buf_release(&error_str); |
| + |
| + return ret ?: ret_count; |
| +} |
| + |
| +static ssize_t error_state_write(struct file *file, struct kobject *kobj, |
| + struct bin_attribute *attr, char *buf, |
| + loff_t off, size_t count) |
| +{ |
| + struct device *kdev = container_of(kobj, struct device, kobj); |
| + struct drm_minor *minor = container_of(kdev, struct drm_minor, kdev); |
| + struct drm_device *dev = minor->dev; |
| + int ret; |
| + |
| + DRM_DEBUG_DRIVER("Resetting error state\n"); |
| + |
| + ret = mutex_lock_interruptible(&dev->struct_mutex); |
| + if (ret) |
| + return ret; |
| + |
| + i915_destroy_error_state(dev); |
| + mutex_unlock(&dev->struct_mutex); |
| + |
| + return count; |
| +} |
| + |
| +static struct bin_attribute error_state_attr = { |
| + .attr.name = "error", |
| + .attr.mode = S_IRUSR | S_IWUSR, |
| + .size = 0, |
| + .read = error_state_read, |
| + .write = error_state_write, |
| +}; |
| + |
| void i915_setup_sysfs(struct drm_device *dev) |
| { |
| int ret; |
| @@ -432,10 +497,16 @@ void i915_setup_sysfs(struct drm_device *dev) |
| if (ret) |
| DRM_ERROR("gen6 sysfs setup failed\n"); |
| } |
| + |
| + ret = sysfs_create_bin_file(&dev->primary->kdev.kobj, |
| + &error_state_attr); |
| + if (ret) |
| + DRM_ERROR("error_state sysfs setup failed\n"); |
| } |
| |
| void i915_teardown_sysfs(struct drm_device *dev) |
| { |
| + sysfs_remove_bin_file(&dev->primary->kdev.kobj, &error_state_attr); |
| sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs); |
| device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); |
| #ifdef CONFIG_PM |
| -- |
| 1.8.5.rc3 |
| |