Message ID | 1434393394-21002-11-git-send-email-david.s.gordon@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, Jun 15, 2015 at 07:36:28PM +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. > > Issue: VIZ-4884 > Signed-off-by: Alex Dai <yu.dai@intel.com> > Signed-off-by: Dave Gordon <david.s.gordon@intel.com> > --- > drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++++++++ > drivers/gpu/drm/i915/i915_guc_submission.c | 43 ++++++++++++++++++++++++++++ > 2 files changed, 72 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c > index c52a745..b0aa4af 100644 > --- a/drivers/gpu/drm/i915/i915_debugfs.c > +++ b/drivers/gpu/drm/i915/i915_debugfs.c > @@ -2388,6 +2388,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)); Coherency? You don't mention in the changelong how you expect this to be used. Do you have some parser that polls the debugfs for changes? If this is likely to become API, use a context parameter instead to return a handle to the log bo. > + > + 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'); You already have a newline at the end. -Chris
On 06/15/2015 07:36 PM, 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. > > Issue: VIZ-4884 > Signed-off-by: Alex Dai <yu.dai@intel.com> > Signed-off-by: Dave Gordon <david.s.gordon@intel.com> > --- > drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++++++++ > drivers/gpu/drm/i915/i915_guc_submission.c | 43 ++++++++++++++++++++++++++++ > 2 files changed, 72 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c > index c52a745..b0aa4af 100644 > --- a/drivers/gpu/drm/i915/i915_debugfs.c > +++ b/drivers/gpu/drm/i915/i915_debugfs.c > @@ -2388,6 +2388,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); > + } This doesn't look performance critical, but you could also use sg_miter_ family of functions/macros to iterate and kmap sg list pages. I did not bother figuring out what kind of smarts i915_gem_object_get_page does, but it is not likely it can beat sg_miter_ for efficiency. Regards, Tvrtko
On Tue, Jun 16, 2015 at 10:26:40AM +0100, Tvrtko Ursulin wrote: > > On 06/15/2015 07:36 PM, 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. > > > >Issue: VIZ-4884 > >Signed-off-by: Alex Dai <yu.dai@intel.com> > >Signed-off-by: Dave Gordon <david.s.gordon@intel.com> > >--- > > drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++++++++ > > drivers/gpu/drm/i915/i915_guc_submission.c | 43 ++++++++++++++++++++++++++++ > > 2 files changed, 72 insertions(+) > > > >diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c > >index c52a745..b0aa4af 100644 > >--- a/drivers/gpu/drm/i915/i915_debugfs.c > >+++ b/drivers/gpu/drm/i915/i915_debugfs.c > >@@ -2388,6 +2388,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); > >+ } > > This doesn't look performance critical, but you could also use > sg_miter_ family of functions/macros to iterate and kmap sg list > pages. I did not bother figuring out what kind of smarts > i915_gem_object_get_page does, but it is not likely it can beat > sg_miter_ for efficiency. It does. I have patches to replace more uses of sg_page_iter because it is the slow point in many functions. -Chris
On 06/16/2015 12:40 PM, Chris Wilson wrote: > On Tue, Jun 16, 2015 at 10:26:40AM +0100, Tvrtko Ursulin wrote: >> >> On 06/15/2015 07:36 PM, 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. >>> >>> Issue: VIZ-4884 >>> Signed-off-by: Alex Dai <yu.dai@intel.com> >>> Signed-off-by: Dave Gordon <david.s.gordon@intel.com> >>> --- >>> drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++++++++++++++++ >>> drivers/gpu/drm/i915/i915_guc_submission.c | 43 ++++++++++++++++++++++++++++ >>> 2 files changed, 72 insertions(+) >>> >>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c >>> index c52a745..b0aa4af 100644 >>> --- a/drivers/gpu/drm/i915/i915_debugfs.c >>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c >>> @@ -2388,6 +2388,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); >>> + } >> >> This doesn't look performance critical, but you could also use >> sg_miter_ family of functions/macros to iterate and kmap sg list >> pages. I did not bother figuring out what kind of smarts >> i915_gem_object_get_page does, but it is not likely it can beat >> sg_miter_ for efficiency. > > It does. I have patches to replace more uses of sg_page_iter because it > is the slow point in many functions. Oh wow, so a "3rd party" random access iterator, used in sequential mode over a naturally sequential data structure, beats the native sequential iterator for performance? Amazing. :) Regards, Tvrtko
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index c52a745..b0aa4af 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2388,6 +2388,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; @@ -5083,6 +5111,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 273cf38..4efb73a 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. @@ -104,6 +145,8 @@ int i915_guc_submission_init(struct drm_device *dev) memset(guc->doorbell_bitmap, 0, sizeof(guc->doorbell_bitmap)); guc->db_cacheline = 0; + guc_create_log(guc); + return 0; }