Message ID | 1436466554-24806-9-git-send-email-david.s.gordon@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Jul 09, 2015 at 07:29:09PM +0100, Dave Gordon wrote: > From: Alex Dai <yu.dai@intel.com> > > Allocate a GEM object to hold GuC log data. A debugfs interface > (i915_guc_log_dump) is provided to print out the log content. > > v2: > Add struct members at point of use [Chris Wilson] > > v4: > Rebased > > Issue: VIZ-4884 > Signed-off-by: Alex Dai <yu.dai@intel.com> > Signed-off-by: Dave Gordon <david.s.gordon@intel.com> Reviewed-by: Tom O'Rourke <Tom.O'Rourke@intel.com> > --- > drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++++++++ > drivers/gpu/drm/i915/i915_guc_submission.c | 46 ++++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/intel_guc.h | 1 + > 3 files changed, 76 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c > index 9ff5f17..13e37d1 100644 > --- a/drivers/gpu/drm/i915/i915_debugfs.c > +++ b/drivers/gpu/drm/i915/i915_debugfs.c > @@ -2397,6 +2397,34 @@ static int i915_guc_load_status_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; > @@ -5112,6 +5140,7 @@ static const struct drm_info_list i915_debugfs_list[] = { > {"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS}, > {"i915_gem_batch_pool", i915_gem_batch_pool_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_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c > index 70a0405..e9d46d6 100644 > --- a/drivers/gpu/drm/i915/i915_guc_submission.c > +++ b/drivers/gpu/drm/i915/i915_guc_submission.c > @@ -75,6 +75,47 @@ static void gem_release_guc_obj(struct drm_i915_gem_object *obj) > drm_gem_object_unreference(&obj->base); > } > > +static void guc_create_log(struct intel_guc *guc) > +{ > + struct drm_i915_private *dev_priv = guc_to_i915(guc); > + struct drm_i915_gem_object *obj; > + unsigned long offset; > + uint32_t size, flags; > + > + if (i915.guc_log_level < GUC_LOG_VERBOSITY_MIN) > + return; > + > + if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX) > + i915.guc_log_level = GUC_LOG_VERBOSITY_MAX; > + > + /* 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; > + > + obj = guc->log_obj; > + if (!obj) { > + obj = gem_allocate_guc_obj(dev_priv->dev, size); > + if (!obj) { > + /* logging will be off */ > + i915.guc_log_level = -1; > + return; > + } > + > + guc->log_obj = 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); [TOR:] How does the "log half full" interrupt get handled? > + > + offset = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; /* in pages */ > + guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; > +} > + > /* > * Set up the memory resources to be shared with the GuC. At this point, > * we require just one object that can be mapped through the GGTT. > @@ -99,6 +140,8 @@ int i915_guc_submission_init(struct drm_device *dev) > > ida_init(&guc->ctx_ids); > > + guc_create_log(guc); > + > return 0; > } > > @@ -107,6 +150,9 @@ void i915_guc_submission_fini(struct drm_device *dev) > struct drm_i915_private *dev_priv = dev->dev_private; > struct intel_guc *guc = &dev_priv->guc; > > + gem_release_guc_obj(dev_priv->guc.log_obj); > + guc->log_obj = NULL; > + > if (guc->ctx_pool_obj) > ida_destroy(&guc->ctx_ids); > gem_release_guc_obj(guc->ctx_pool_obj); > diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h > index be3cad8..5b51b05 100644 > --- a/drivers/gpu/drm/i915/intel_guc.h > +++ b/drivers/gpu/drm/i915/intel_guc.h > @@ -56,6 +56,7 @@ struct intel_guc { > struct intel_guc_fw guc_fw; > > uint32_t log_flags; > + struct drm_i915_gem_object *log_obj; > > struct drm_i915_gem_object *ctx_pool_obj; > struct ida ctx_ids; > -- > 1.9.1 >
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9ff5f17..13e37d1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2397,6 +2397,34 @@ static int i915_guc_load_status_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; @@ -5112,6 +5140,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS}, {"i915_gem_batch_pool", i915_gem_batch_pool_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_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 70a0405..e9d46d6 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -75,6 +75,47 @@ static void gem_release_guc_obj(struct drm_i915_gem_object *obj) drm_gem_object_unreference(&obj->base); } +static void guc_create_log(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct drm_i915_gem_object *obj; + unsigned long offset; + uint32_t size, flags; + + if (i915.guc_log_level < GUC_LOG_VERBOSITY_MIN) + return; + + if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX) + i915.guc_log_level = GUC_LOG_VERBOSITY_MAX; + + /* 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; + + obj = guc->log_obj; + if (!obj) { + obj = gem_allocate_guc_obj(dev_priv->dev, size); + if (!obj) { + /* logging will be off */ + i915.guc_log_level = -1; + return; + } + + guc->log_obj = 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); + + offset = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; /* in pages */ + guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; +} + /* * Set up the memory resources to be shared with the GuC. At this point, * we require just one object that can be mapped through the GGTT. @@ -99,6 +140,8 @@ int i915_guc_submission_init(struct drm_device *dev) ida_init(&guc->ctx_ids); + guc_create_log(guc); + return 0; } @@ -107,6 +150,9 @@ void i915_guc_submission_fini(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc *guc = &dev_priv->guc; + gem_release_guc_obj(dev_priv->guc.log_obj); + guc->log_obj = NULL; + if (guc->ctx_pool_obj) ida_destroy(&guc->ctx_ids); gem_release_guc_obj(guc->ctx_pool_obj); diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index be3cad8..5b51b05 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -56,6 +56,7 @@ struct intel_guc { struct intel_guc_fw guc_fw; uint32_t log_flags; + struct drm_i915_gem_object *log_obj; struct drm_i915_gem_object *ctx_pool_obj; struct ida ctx_ids;