@@ -262,6 +262,9 @@ static int slpc_reset(struct intel_guc_slpc *slpc)
if (wait_for(slpc_is_running(slpc), SLPC_RESET_TIMEOUT_MS)) {
drm_err(&i915->drm, "SLPC not enabled! State = %s\n",
slpc_get_state_string(slpc));
+
+ intel_klog_error_capture(guc_to_gt(guc),
+ (intel_engine_mask_t) ~0U);
return -EIO;
}
}
@@ -1969,3 +1969,100 @@ void i915_disable_error_state(struct drm_i915_private *i915, int err)
i915->gpu_error.first_error = ERR_PTR(err);
spin_unlock_irq(&i915->gpu_error.lock);
}
+
+void intel_klog_error_capture(struct intel_gt *gt,
+ intel_engine_mask_t engine_mask)
+{
+ struct drm_i915_private *i915 = gt->i915;
+ struct i915_gpu_coredump *error;
+ intel_wakeref_t wakeref;
+ size_t buf_size = PAGE_SIZE * 128;
+ size_t pos_err;
+ char *buf, *ptr, *next;
+
+ error = READ_ONCE(i915->gpu_error.first_error);
+ if (error) {
+ drm_err(&i915->drm, "Clearing existing error capture first...\n");
+ i915_reset_error_state(i915);
+ }
+
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref)
+ error = i915_gpu_coredump(gt, engine_mask);
+
+ if (IS_ERR(error)) {
+ drm_err(&i915->drm, "Failed to capture error capture: %ld!\n", PTR_ERR(error));
+ return;
+ }
+
+ buf = kvmalloc(buf_size, GFP_KERNEL);
+ if (!buf) {
+ drm_err(&i915->drm, "Failed to allocate buffer for error capture!\n");
+ return;
+ }
+
+ drm_info(&i915->drm, "Dumping i915 error capture...\n");
+
+ /* Largest string length safe to print via dmesg */
+# define MAX_CHUNK 800
+
+ pos_err = 0;
+ while (1) {
+ ssize_t got = i915_gpu_coredump_copy_to_buffer(error, buf, pos_err, buf_size - 1);
+ if (got <= 0)
+ break;
+
+ buf[got] = 0;
+ pos_err += got;
+
+ ptr = buf;
+ while (got > 0) {
+ size_t count;
+ char tag[2];
+
+ next = strnchr(ptr, got, '\n');
+ if (next) {
+ count = next - ptr;
+ *next = 0;
+ tag[0] = '>';
+ tag[1] = '<';
+ } else {
+ count = got;
+ tag[0] = '}';
+ tag[1] = '{';
+ }
+
+ if (count > MAX_CHUNK) {
+ size_t pos;
+ char *ptr2 = ptr;
+
+ for (pos = MAX_CHUNK; pos < count; pos += MAX_CHUNK) {
+ char chr = ptr[pos];
+ ptr[pos] = 0;
+ drm_info(&i915->drm, "Capture }%s{\n", ptr2);
+ ptr[pos] = chr;
+ ptr2 = ptr + pos;
+ }
+
+ if (ptr2 < (ptr + count))
+ drm_info(&i915->drm, "Capture %c%s%c\n", tag[0], ptr2, tag[1]);
+ else if (tag[0] == '>')
+ drm_info(&i915->drm, "Capture ><\n");
+ } else
+ drm_info(&i915->drm, "Capture %c%s%c\n", tag[0], ptr, tag[1]);
+
+ ptr = next;
+ got -= count;
+ if (next) {
+ ptr++;
+ got--;
+ }
+ }
+
+ if (got)
+ drm_info(&i915->drm, "Got %zd bytes remaining!\n", got);
+ }
+
+ kvfree(buf);
+
+ drm_info(&i915->drm, "Dumped %zd bytes\n", pos_err);
+}
@@ -214,6 +214,9 @@ struct drm_i915_error_state_buf {
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+void intel_klog_error_capture(struct intel_gt *gt,
+ intel_engine_mask_t engine_mask);
+
__printf(2, 3)
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
From: Matthew Brost <matthew.brost@intel.com> --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 3 + drivers/gpu/drm/i915/i915_gpu_error.c | 97 +++++++++++++++++++++ drivers/gpu/drm/i915/i915_gpu_error.h | 3 + 3 files changed, 103 insertions(+)