From: Alex Dai <yu.dai@xxxxxxxxx> Allocate a gem obj to hold GuC log data. Also a debugfs interface (i915_guc_log_dump) is provided to print out the log content. Issue: VIZ-4884 Signed-off-by: Alex Dai <yu.dai@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_params.c | 5 +++ drivers/gpu/drm/i915/intel_guc.h | 3 +- drivers/gpu/drm/i915/intel_guc_loader.c | 60 +++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_guc_scheduler.c | 9 ++--- 6 files changed, 99 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 59ad3fc..42d3df8 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2310,6 +2310,34 @@ static int i915_guc_info(struct seq_file *m, void *data) return 0; } +static int i915_guc_log_dump(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *log_obj = dev_priv->guc.log_obj; + u32 *log; + int i = 0, pg; + + if (!log_obj) + return 0; + + for (pg = 0; pg < log_obj->base.size / PAGE_SIZE; pg++) { + log = kmap_atomic(i915_gem_object_get_page(log_obj, pg)); + + for (i = 0; i < PAGE_SIZE / sizeof(u32); i += 4) + seq_printf(m, "0x%08x 0x%08x 0x%08x 0x%08x\n", + *(log + i), *(log + i + 1), + *(log + i + 2), *(log + i + 3)); + + kunmap_atomic(log); + } + + seq_putc(m, '\n'); + + return 0; +} + static int i915_edp_psr_status(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; @@ -4734,6 +4762,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_gem_batch_pool", i915_gem_batch_pool_info, 0}, {"i915_guc_info", i915_guc_info, 0}, {"i915_guc_load_status", i915_guc_load_status_info, 0}, + {"i915_guc_log_dump", i915_guc_log_dump, 0}, {"i915_frequency_info", i915_frequency_info, 0}, {"i915_hangcheck_info", i915_hangcheck_info, 0}, {"i915_drpc_info", i915_drpc_info, 0}, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ba5da95..5fde3fc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2477,6 +2477,7 @@ struct i915_params { bool disable_display; bool disable_vtd_wa; bool enable_guc_scheduling; + unsigned int guc_log_level; int use_mmio_flip; int mmio_debug; bool verbose_state_checks; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index a4743ed..4877130 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -53,6 +53,7 @@ struct i915_params i915 __read_mostly = { .verbose_state_checks = 1, .nuclear_pageflip = 0, .enable_guc_scheduling = false, + .guc_log_level = 0, }; module_param_named(modeset, i915.modeset, int, 0400); @@ -182,3 +183,7 @@ MODULE_PARM_DESC(nuclear_pageflip, module_param_named(enable_guc_scheduling, i915.enable_guc_scheduling, bool, 0400); MODULE_PARM_DESC(enable_guc_scheduling, "Enable GuC scheduling (default:false)"); + +module_param_named(guc_log_level, i915.guc_log_level, int, 0400); +MODULE_PARM_DESC(guc_log_level, + "GuC firmware logging level (0:disabled, 1~4:enabled)"); diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index e20c332..3c41483 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -62,6 +62,7 @@ struct intel_guc { spinlock_t host2guc_lock; struct drm_i915_gem_object *ctx_pool_obj; + struct drm_i915_gem_object *log_obj; struct i915_guc_client *execbuf_client; @@ -170,7 +171,7 @@ int guc_scheduler_init(struct drm_device *dev); void guc_scheduler_fini(struct drm_device *dev); int guc_scheduler_enable(struct drm_device *dev); void guc_scheduler_disable(struct drm_device *dev); -bool sanitize_enable_guc_scheduling(struct drm_device *dev); +void sanitize_enable_guc_scheduling(struct drm_device *dev); /* intel_guc_client.c */ struct i915_guc_client* diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 58e1e33..7c33cc5 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -30,6 +30,10 @@ MODULE_FIRMWARE(I915_GUC_UCODE_GEN8); MODULE_FIRMWARE(I915_GUC_UCODE_GEN9); +#define GUC_LOG_DPC_PAGES 3 +#define GUC_LOG_ISR_PAGES 3 +#define GUC_LOG_CRASH_PAGES 1 + struct drm_i915_gem_object * intel_guc_allocate_gem_obj(struct drm_device *dev, u32 size) { @@ -152,6 +156,51 @@ static u32 get_core_family(struct drm_device *dev) } } +static void create_guc_log(struct intel_guc *guc, u32 *params) +{ + struct drm_i915_private *dev_priv = + container_of(guc, struct drm_i915_private, guc); + struct drm_i915_gem_object *obj; + u32 flags, size; + + /* The first page is to save log buffer state. Allocate one + * extra page for others in case for overlap */ + size = (1 + GUC_LOG_DPC_PAGES + 1 + + GUC_LOG_ISR_PAGES + 1 + + GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT; + + if (!guc->log_obj) { + obj = intel_guc_allocate_gem_obj(dev_priv->dev, size); + if (!obj) { + /* logging will be off */ + *(params + GUC_CTL_LOG_PARAMS) = 0; + i915.guc_log_level = 0; + return; + } + + guc->log_obj = obj; + } + else + obj = guc->log_obj; + + /* each allocated unit is a page */ + flags = GUC_LOG_VALID | GUC_LOG_NOTIFY_ON_HALF_FULL | + (GUC_LOG_DPC_PAGES << GUC_LOG_DPC_SHIFT) | + (GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) | + (GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT); + + size = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; /* in pages */ + flags |= size << GUC_LOG_BUF_ADDR_SHIFT; + + *(params + GUC_CTL_LOG_PARAMS) = flags; + + i915.guc_log_level--; + if (i915.guc_log_level > GUC_LOG_VERBOSITY_ULTRA) + i915.guc_log_level = GUC_LOG_VERBOSITY_ULTRA; + + *(params + GUC_CTL_DEBUG) |= i915.guc_log_level; +} + static void set_guc_init_params(struct drm_i915_private *dev_priv) { u32 params[GUC_CTL_MAX_DWORDS]; @@ -175,7 +224,9 @@ static void set_guc_init_params(struct drm_i915_private *dev_priv) params[GUC_CTL_FEATURE] |= GUC_CTL_DISABLE_SCHEDULER | GUC_CTL_VCS2_ENABLED; - /* XXX: Set up log buffer */ + /* Set up log buffer */ + if (i915.guc_log_level > 0) + create_guc_log(&dev_priv->guc, params); /* If GuC scheduling is enabled, setup params here. */ if (i915.enable_guc_scheduling) { @@ -299,7 +350,7 @@ int intel_guc_load_ucode(struct drm_device *dev, bool wait) struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw; int err; - i915.enable_guc_scheduling = sanitize_enable_guc_scheduling(dev); + sanitize_enable_guc_scheduling(dev); DRM_DEBUG_DRIVER("GuC: wait %d, fetch status %d, load status %d\n", wait, guc_fw->uc_fw_fetch_status, guc_fw->uc_fw_load_status); @@ -401,6 +452,11 @@ void intel_guc_ucode_fini(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_uc_fw *guc_fw = &dev_priv->guc.guc_fw; + if (dev_priv->guc.log_obj) { + intel_guc_release_gem_obj(dev_priv->guc.log_obj); + dev_priv->guc.log_obj = NULL; + } + guc_scheduler_fini(dev); intel_uc_fw_fini(dev, guc_fw); diff --git a/drivers/gpu/drm/i915/intel_guc_scheduler.c b/drivers/gpu/drm/i915/intel_guc_scheduler.c index c0b7231..ea1ff28 100644 --- a/drivers/gpu/drm/i915/intel_guc_scheduler.c +++ b/drivers/gpu/drm/i915/intel_guc_scheduler.c @@ -155,11 +155,10 @@ void guc_scheduler_disable(struct drm_device *dev) } } -bool sanitize_enable_guc_scheduling(struct drm_device *dev) +void sanitize_enable_guc_scheduling(struct drm_device *dev) { - if (!HAS_GUC_UCODE(dev) || !HAS_GUC_SCHED(dev)) - return false; - - return i915.enable_execlists && i915.enable_guc_scheduling; + if (!HAS_GUC_UCODE(dev) || !HAS_GUC_SCHED(dev) || + !i915.enable_execlists) + i915.enable_guc_scheduling = false; } -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx