|
@@ -30,6 +30,8 @@
|
|
|
#include <generated/utsrelease.h>
|
|
|
#include <linux/stop_machine.h>
|
|
|
#include <linux/zlib.h>
|
|
|
+#include <drm/drm_print.h>
|
|
|
+
|
|
|
#include "i915_drv.h"
|
|
|
|
|
|
static const char *engine_str(int engine)
|
|
@@ -175,6 +177,21 @@ static void i915_error_puts(struct drm_i915_error_state_buf *e,
|
|
|
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
|
|
|
#define err_puts(e, s) i915_error_puts(e, s)
|
|
|
|
|
|
+static void __i915_printfn_error(struct drm_printer *p, struct va_format *vaf)
|
|
|
+{
|
|
|
+ i915_error_vprintf(p->arg, vaf->fmt, *vaf->va);
|
|
|
+}
|
|
|
+
|
|
|
+static inline struct drm_printer
|
|
|
+i915_error_printer(struct drm_i915_error_state_buf *e)
|
|
|
+{
|
|
|
+ struct drm_printer p = {
|
|
|
+ .printfn = __i915_printfn_error,
|
|
|
+ .arg = e,
|
|
|
+ };
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_DRM_I915_COMPRESS_ERROR
|
|
|
|
|
|
struct compress {
|
|
@@ -589,6 +606,20 @@ static void err_print_pciid(struct drm_i915_error_state_buf *m,
|
|
|
pdev->subsystem_device);
|
|
|
}
|
|
|
|
|
|
+static void err_print_uc(struct drm_i915_error_state_buf *m,
|
|
|
+ const struct i915_error_uc *error_uc)
|
|
|
+{
|
|
|
+ struct drm_printer p = i915_error_printer(m);
|
|
|
+ const struct i915_gpu_state *error =
|
|
|
+ container_of(error_uc, typeof(*error), uc);
|
|
|
+
|
|
|
+ if (!error->device_info.has_guc)
|
|
|
+ return;
|
|
|
+
|
|
|
+ intel_uc_fw_dump(&error_uc->guc_fw, &p);
|
|
|
+ intel_uc_fw_dump(&error_uc->huc_fw, &p);
|
|
|
+}
|
|
|
+
|
|
|
int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
|
|
const struct i915_gpu_state *error)
|
|
|
{
|
|
@@ -773,6 +804,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
|
|
|
|
|
err_print_capabilities(m, &error->device_info);
|
|
|
err_print_params(m, &error->params);
|
|
|
+ err_print_uc(m, &error->uc);
|
|
|
|
|
|
if (m->bytes == 0 && m->err)
|
|
|
return m->err;
|
|
@@ -831,6 +863,14 @@ static __always_inline void free_param(const char *type, void *x)
|
|
|
kfree(*(void **)x);
|
|
|
}
|
|
|
|
|
|
+static void cleanup_uc_state(struct i915_gpu_state *error)
|
|
|
+{
|
|
|
+ struct i915_error_uc *error_uc = &error->uc;
|
|
|
+
|
|
|
+ kfree(error_uc->guc_fw.path);
|
|
|
+ kfree(error_uc->huc_fw.path);
|
|
|
+}
|
|
|
+
|
|
|
void __i915_gpu_state_free(struct kref *error_ref)
|
|
|
{
|
|
|
struct i915_gpu_state *error =
|
|
@@ -870,6 +910,8 @@ void __i915_gpu_state_free(struct kref *error_ref)
|
|
|
I915_PARAMS_FOR_EACH(FREE);
|
|
|
#undef FREE
|
|
|
|
|
|
+ cleanup_uc_state(error);
|
|
|
+
|
|
|
kfree(error);
|
|
|
}
|
|
|
|
|
@@ -1559,6 +1601,26 @@ static void i915_capture_pinned_buffers(struct drm_i915_private *dev_priv,
|
|
|
error->pinned_bo = bo;
|
|
|
}
|
|
|
|
|
|
+static void capture_uc_state(struct i915_gpu_state *error)
|
|
|
+{
|
|
|
+ struct drm_i915_private *i915 = error->i915;
|
|
|
+ struct i915_error_uc *error_uc = &error->uc;
|
|
|
+
|
|
|
+ /* Capturing uC state won't be useful if there is no GuC */
|
|
|
+ if (!error->device_info.has_guc)
|
|
|
+ return;
|
|
|
+
|
|
|
+ error_uc->guc_fw = i915->guc.fw;
|
|
|
+ error_uc->huc_fw = i915->huc.fw;
|
|
|
+
|
|
|
+ /* Non-default firmware paths will be specified by the modparam.
|
|
|
+ * As modparams are generally accesible from the userspace make
|
|
|
+ * explicit copies of the firmware paths.
|
|
|
+ */
|
|
|
+ error_uc->guc_fw.path = kstrdup(i915->guc.fw.path, GFP_ATOMIC);
|
|
|
+ error_uc->huc_fw.path = kstrdup(i915->huc.fw.path, GFP_ATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
static void i915_gem_capture_guc_log_buffer(struct drm_i915_private *dev_priv,
|
|
|
struct i915_gpu_state *error)
|
|
|
{
|
|
@@ -1710,6 +1772,8 @@ static int capture(void *data)
|
|
|
I915_PARAMS_FOR_EACH(DUP);
|
|
|
#undef DUP
|
|
|
|
|
|
+ capture_uc_state(error);
|
|
|
+
|
|
|
i915_capture_gen_state(error->i915, error);
|
|
|
i915_capture_reg_state(error->i915, error);
|
|
|
i915_gem_record_fences(error->i915, error);
|