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 | 66 +++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_guc_scheduler.c | 9 ++-- 6 files changed, 105 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ec10ca0..1618410 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2323,6 +2323,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; @@ -4747,6 +4775,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 28a448a..c2d88d9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2498,6 +2498,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 4ed2d6a..e47e648 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; @@ -177,7 +178,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 dafab32..3a33618 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_GUC_UCODE_GEN8 "i915/guc_gen8.bin" @@ -53,6 +59,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 + /** * 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) { @@ -357,7 +414,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); @@ -467,6 +524,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