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 | 1 + drivers/gpu/drm/i915/intel_guc_loader.c | 64 ++++++++++++++++++++++++++++++++- 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f12bbee..0ce1e23 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2387,6 +2387,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; @@ -4855,6 +4883,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 6760b9a..24b94da 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2504,6 +2504,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 9ad2e27..95e4eb7 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -54,6 +54,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); @@ -188,3 +189,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 641fd14..54572f7 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; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index c784d64..d1fd11e 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -46,6 +46,12 @@ * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM. * + * Firmware log: + * Firmware log is enabled by setting i915.guc_log_level to non-negative level. + * Log data is printed out via reading debugfs i915_guc_log_dump. Reading from + * i915_guc_load_status will print out firmware loading status and scratch + * registers value. + * */ #define I915_SKL_GUC_UCODE "i915/skl_guc_ver1.bin" @@ -53,6 +59,10 @@ MODULE_FIRMWARE(I915_SKL_GUC_UCODE); #define I915_BXT_GUC_UCODE "i915/bxt_guc_ver1.bin" MODULE_FIRMWARE(I915_BXT_GUC_UCODE); +#define GUC_LOG_DPC_PAGES 3 +#define GUC_LOG_ISR_PAGES 3 +#define GUC_LOG_CRASH_PAGES 1 + /** * intel_guc_allocate_gem_obj() - Allocate gem object for GuC usage * @dev: drm device @@ -211,6 +221,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]; @@ -234,7 +289,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) { @@ -479,6 +536,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); -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx