[Intel-gfx] [PATCH 15/18] drm/i915: Enable GuC firmware log
yu.dai at intel.com
yu.dai at intel.com
Thu Mar 26 12:41:22 PDT 2015
From: Alex Dai <yu.dai at intel.com>
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 at intel.com>
---
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
More information about the Intel-gfx
mailing list