[Intel-gfx] [PATCH 2/2] drm/i915/bdw: Extract workaround registers data from golden render state

Arun Siluvery arun.siluvery at linux.intel.com
Wed Aug 20 16:19:18 CEST 2014


Workarounds are applied using golden render state and they are placed
at the beginning of this batch buffer. They are essentially register updates
and we use this fact to extract them and generate a list of WAs applied.
This list is also exported via debugfs file and it is used to validate their
status before and after a test condition (eg reset, suspend/resume etc)
This patch is only required to support testing.

Signed-off-by: Arun Siluvery <arun.siluvery at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c          | 35 +++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h              | 14 ++++++++
 drivers/gpu/drm/i915/i915_gem_render_state.c | 51 ++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d42db6b..c1d4e6b 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2451,20 +2451,54 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
 		seq_printf(m, " dpll_md: 0x%08x\n", pll->hw_state.dpll_md);
 		seq_printf(m, " fp0:     0x%08x\n", pll->hw_state.fp0);
 		seq_printf(m, " fp1:     0x%08x\n", pll->hw_state.fp1);
 		seq_printf(m, " wrpll:   0x%08x\n", pll->hw_state.wrpll);
 	}
 	drm_modeset_unlock_all(dev);
 
 	return 0;
 }
 
+static int intel_wa_registers(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+	int ret;
+
+	if (!IS_BROADWELL(dev)) {
+		DRM_DEBUG_DRIVER("Workaround table not available\n");
+		return -EINVAL;
+	}
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	intel_runtime_pm_get(dev_priv);
+
+	seq_printf(m, "Workarounds applied: %d\n", dev_priv->num_wa_regs);
+	for (i = 0; i < dev_priv->num_wa_regs; ++i) {
+		if (dev_priv->intel_wa_regs[i].addr)
+			seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n",
+				   dev_priv->intel_wa_regs[i].addr,
+				   dev_priv->intel_wa_regs[i].value,
+				   dev_priv->intel_wa_regs[i].mask);
+	}
+
+	intel_runtime_pm_put(dev_priv);
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
 struct pipe_crc_info {
 	const char *name;
 	struct drm_device *dev;
 	enum pipe pipe;
 };
 
 static int i915_dp_mst_info(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
@@ -3980,20 +4014,21 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_llc", i915_llc, 0},
 	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 	{"i915_sink_crc_eDP1", i915_sink_crc, 0},
 	{"i915_energy_uJ", i915_energy_uJ, 0},
 	{"i915_pc8_status", i915_pc8_status, 0},
 	{"i915_power_domain_info", i915_power_domain_info, 0},
 	{"i915_display_info", i915_display_info, 0},
 	{"i915_semaphore_status", i915_semaphore_status, 0},
 	{"i915_shared_dplls_info", i915_shared_dplls_info, 0},
 	{"i915_dp_mst_info", i915_dp_mst_info, 0},
+	{"intel_wa_registers", intel_wa_registers, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
 static const struct i915_debugfs_files {
 	const char *name;
 	const struct file_operations *fops;
 } i915_debugfs_files[] = {
 	{"i915_wedged", &i915_wedged_fops},
 	{"i915_max_freq", &i915_max_freq_fops},
 	{"i915_min_freq", &i915_min_freq_fops},
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index bcf79f0..2fc34bd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1546,20 +1546,34 @@ struct drm_i915_private {
 	wait_queue_head_t pending_flip_queue;
 
 #ifdef CONFIG_DEBUG_FS
 	struct intel_pipe_crc pipe_crc[I915_MAX_PIPES];
 #endif
 
 	int num_shared_dpll;
 	struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
 	int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
 
+	/*
+	 * workarounds are currently applied using golden render state
+	 * and the exact count is known only after parsing its content;
+	 * this patch is mainly for i-g-t so use a fixed number for now.
+	 */
+#define I915_MAX_WA_REGS  16
+	struct {
+		u32 addr;
+		u32 value;
+		/* bitmask representing WA bits */
+		u32 mask;
+	} intel_wa_regs[I915_MAX_WA_REGS];
+	u32 num_wa_regs;
+
 	/* Reclocking support */
 	bool render_reclock_avail;
 	bool lvds_downclock_avail;
 	/* indicates the reduced downclock for LVDS*/
 	int lvds_downclock;
 
 	struct i915_frontbuffer_tracking fb_tracking;
 
 	u16 orig_clock;
 
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c
index e60be3f..ef37122 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.c
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.c
@@ -120,20 +120,65 @@ static int render_state_setup(struct render_state *so)
 		return ret;
 
 	if (rodata->reloc[reloc_index] != -1) {
 		DRM_ERROR("only %d relocs resolved\n", reloc_index);
 		return -EINVAL;
 	}
 
 	return 0;
 }
 
+static int bdw_init_workarounds_data(struct render_state *so,
+				    struct intel_engine_cs *ring)
+{
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	const struct intel_renderstate_rodata *rodata = so->rodata;
+	unsigned int i = 0;
+	int ret = 0;
+
+	dev_priv->num_wa_regs = 0;
+
+	while (i < rodata->batch_items) {
+		u32 addr, value, mask;
+		u32 s = rodata->batch[i];
+
+		/*
+		 * Workarounds are placed at the beginning of
+		 * golden render state and they are essentially
+		 * register updates
+		 */
+		if (s != MI_LOAD_REGISTER_IMM(1)) {
+			ret = -EINVAL;
+			break;
+		}
+
+		addr = rodata->batch[i + 1];
+		mask = rodata->batch[i + 2] & 0xFFFF;
+		value = I915_READ(addr) | mask;
+
+		dev_priv->intel_wa_regs[dev_priv->num_wa_regs].addr = addr;
+		dev_priv->intel_wa_regs[dev_priv->num_wa_regs].value = value;
+		dev_priv->intel_wa_regs[dev_priv->num_wa_regs].mask = mask;
+
+		i += 3;
+		dev_priv->num_wa_regs++;
+	}
+
+	if (dev_priv->num_wa_regs > I915_MAX_WA_REGS)
+		dev_priv->num_wa_regs = I915_MAX_WA_REGS;
+
+	DRM_DEBUG_DRIVER("No. of workarounds found in render state: %d\n",
+			 dev_priv->num_wa_regs);
+
+	return ret;
+}
+
 static void render_state_fini(struct render_state *so)
 {
 	i915_gem_object_ggtt_unpin(so->obj);
 	drm_gem_object_unreference(&so->obj->base);
 }
 
 int i915_gem_render_state_init(struct intel_engine_cs *ring)
 {
 	struct render_state so;
 	int ret;
@@ -156,14 +201,20 @@ int i915_gem_render_state_init(struct intel_engine_cs *ring)
 					so.ggtt_offset,
 					so.rodata->batch_items * 4,
 					I915_DISPATCH_SECURE);
 	if (ret)
 		goto out;
 
 	i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), ring);
 
 	ret = __i915_add_request(ring, NULL, so.obj, NULL);
 	/* __i915_add_request moves object to inactive if it fails */
+
+	if (!ret) {
+		if (bdw_init_workarounds_data(&so, ring))
+			DRM_DEBUG_DRIVER("Workarounds data not found !!\n");
+	}
+
 out:
 	render_state_fini(&so);
 	return ret;
 }
-- 
2.0.4




More information about the Intel-gfx mailing list