diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gpu_error.c | 111 |
2 files changed, 115 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 89ad2b203e0a..cef08d0918d3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -584,6 +584,10 @@ struct drm_i915_error_state { u32 *active_bo_count, *pinned_bo_count; u32 vm_count; + + struct intel_guc guc; + struct i915_guc_client execbuf_client; + struct i915_guc_client preempt_client; }; struct intel_connector; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 23ccac54e463..8273f73d5f78 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -361,6 +361,101 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m, } } +static void i915_guc_firmware_info(struct drm_i915_error_state_buf *m, + struct drm_i915_private *dev_priv, + struct intel_guc_fw *guc_fw) +{ + err_printf(m, "GuC firmware status:\n"); + err_printf(m, "\tpath: %s\n", + guc_fw->guc_fw_path); + err_printf(m, "\tfetch: %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status)); + err_printf(m, "\tload: %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); + err_printf(m, "\tversion wanted: %d.%d\n", + guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted); + err_printf(m, "\tversion found: %d.%d\n", + guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found); +} + +static void i915_guc_action_info(struct drm_i915_error_state_buf *m, + struct drm_i915_private *dev_priv, + struct intel_guc *guc) +{ + struct intel_engine_cs *engine; + u64 total = 0, preempts = 0; + int i; + + err_printf(m, "GuC action status:\n"); + err_printf(m, "\ttotal action count: %llu\n", guc->action_count); + err_printf(m, "\tlast action command: 0x%x\n", guc->action_cmd); + err_printf(m, "\tlast action status: 0x%x\n", guc->action_status); + + err_printf(m, "\taction failure count: %u\n", guc->action_fail_count); + err_printf(m, "\tlast failed action: 0x%x\n", guc->action_fail_cmd); + err_printf(m, "\tlast failed status: 0x%x\n", guc->action_fail_status); + err_printf(m, "\tlast error code: %d\n", guc->action_err); + + err_printf(m, "GuC submissions:\n"); + for_each_engine(engine, dev_priv, i) { + err_printf(m, "\t%-24s: %10llu, last %-8s 0x%08x %9d\n", + engine->name, guc->submissions[i], "seqno", + guc->last_seqno[i], guc->last_seqno[i]); + err_printf(m, "\t%-24s: %10u, last %-8s 0x%08x %9d\n", + " preemptions", guc->preemptions[i], "preempt", + guc->last_preempt[i], guc->last_preempt[i]); + total += guc->submissions[i]; + preempts += guc->preemptions[i]; + } + err_printf(m, "\t%s: %10llu\n", "Total regular", total); + err_printf(m, "\t%s: %10llu\n", " preempts", preempts); +} + +static void i915_guc_client_info(struct drm_i915_error_state_buf *m, + struct drm_i915_private *dev_priv, + struct i915_guc_client *client) +{ + struct intel_engine_cs *engine; + uint64_t tot = 0; + uint32_t i; + + err_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n", + client->priority, client->ctx_index, client->proc_desc_offset); + err_printf(m, "\tDoorbell id %d, offset: 0x%x, cookie 0x%x\n", + client->doorbell_id, client->doorbell_offset, + client->doorbell_cookie); + err_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", + client->wq_size, client->wq_offset, client->wq_tail); + + err_printf(m, "\tFailed to queue: %u\n", client->q_fail); + err_printf(m, "\tFailed doorbell: %u\n", client->b_fail); + err_printf(m, "\tLast submission result: %d\n", client->retcode); + + for_each_engine(engine, dev_priv, i) { + err_printf(m, "\tSubmissions: %llu %s\n", + client->submissions[i], + engine->name); + tot += client->submissions[i]; + } + err_printf(m, "\tTotal: %llu\n", tot); +} + +static void i915_guc_error_state(struct drm_i915_error_state_buf *m, + struct drm_i915_private *dev_priv, + struct drm_i915_error_state *error) +{ + struct intel_guc *guc = &error->guc; + + i915_guc_firmware_info(m, dev_priv, &guc->guc_fw); + i915_guc_action_info(m, dev_priv, guc); + + err_printf(m, "GuC execbuf client @ %p:\n", guc->execbuf_client); + i915_guc_client_info(m, dev_priv, &error->execbuf_client); + + err_printf(m, "GuC preempt client @ %p:\n", guc->preempt_client); + i915_guc_client_info(m, dev_priv, &error->preempt_client); +} + void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) { va_list args; @@ -470,6 +565,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if (INTEL_INFO(dev)->gen == 7) err_printf(m, "ERR_INT: 0x%08x\n", error->err_int); + if (HAS_GUC_UCODE(dev) || HAS_GUC_SCHED(dev)) + i915_guc_error_state(m, dev_priv, error); + for (i = 0; i < ARRAY_SIZE(error->ring); i++) i915_ring_error_state(m, dev, error, i); @@ -1437,6 +1535,18 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, i915_get_extra_instdone(dev, error->extra_instdone); } +/* Capture information about GuC loading and submission, where enabled */ +static void i915_capture_guc_state(struct drm_i915_private *dev_priv, + struct drm_i915_error_state *error) +{ + /* Just copy the state of the device for now */ + error->guc = dev_priv->guc; + if (error->guc.execbuf_client) + error->execbuf_client = *error->guc.execbuf_client; + if (error->guc.preempt_client) + error->preempt_client = *error->guc.preempt_client; +} + static void i915_error_capture_msg(struct drm_device *dev, struct drm_i915_error_state *error, u32 engine_mask, @@ -1504,6 +1614,7 @@ void i915_capture_error_state(struct drm_device *dev, u32 engine_mask, i915_capture_gen_state(dev_priv, error); i915_capture_reg_state(dev_priv, error); + i915_capture_guc_state(dev_priv, error); i915_gem_capture_buffers(dev_priv, error); i915_gem_record_fences(dev, error); i915_gem_record_rings(dev, error); |