All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-gfx] [PATCH 1/2] drm/i915/guc: Provide mmio list to be saved/restored on engine reset
@ 2019-12-12 18:43 Fernando Pacheco
  2019-12-12 18:43 ` [Intel-gfx] [PATCH 2/2] HAX: force enable_guc=2 and WA i915#571 Fernando Pacheco
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Fernando Pacheco @ 2019-12-12 18:43 UTC (permalink / raw)
  To: intel-gfx

The driver must provide GuC with a list of mmio registers
that should be saved/restored during a GuC-based engine reset.
We provide a minimal set of registers that should get things
working and extend as needed.

v2: rebase and comment to explain why mmio list is kept sorted

Signed-off-by: Fernando Pacheco <fernando.pacheco@intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_workarounds.c   | 25 +++--
 .../gpu/drm/i915/gt/intel_workarounds_types.h |  1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c    | 96 ++++++++++++++++++-
 3 files changed, 114 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 195ccf7db272..866d4a7ba0ea 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -148,29 +148,37 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
 }
 
 static void wa_add(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
-		   u32 val, u32 read_mask)
+		   u32 val, u32 read_mask, bool masked_bits)
 {
 	struct i915_wa wa = {
 		.reg  = reg,
 		.mask = mask,
 		.val  = val,
 		.read = read_mask,
+		.masked_bits = masked_bits,
 	};
 
 	_wa_add(wal, &wa);
 }
 
+static void
+__wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
+		     u32 val, bool masked_bits)
+{
+	wa_add(wal, reg, mask, val, mask, masked_bits);
+}
+
 static void
 wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
 		   u32 val)
 {
-	wa_add(wal, reg, mask, val, mask);
+	__wa_write_masked_or(wal, reg, mask, val, false);
 }
 
 static void
 wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 {
-	wa_write_masked_or(wal, reg, val, _MASKED_BIT_ENABLE(val));
+	__wa_write_masked_or(wal, reg, val, _MASKED_BIT_ENABLE(val), true);
 }
 
 static void
@@ -186,13 +194,16 @@ wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 }
 
 #define WA_SET_BIT_MASKED(addr, mask) \
-	wa_write_masked_or(wal, (addr), (mask), _MASKED_BIT_ENABLE(mask))
+	__wa_write_masked_or(wal, (addr), (mask), \
+			     _MASKED_BIT_ENABLE(mask), true)
 
 #define WA_CLR_BIT_MASKED(addr, mask) \
-	wa_write_masked_or(wal, (addr), (mask), _MASKED_BIT_DISABLE(mask))
+	__wa_write_masked_or(wal, (addr), (mask), \
+			     _MASKED_BIT_DISABLE(mask), true)
 
 #define WA_SET_FIELD_MASKED(addr, mask, value) \
-	wa_write_masked_or(wal, (addr), (mask), _MASKED_FIELD((mask), (value)))
+	__wa_write_masked_or(wal, (addr), (mask), \
+			     _MASKED_FIELD((mask), (value)), true)
 
 static void gen8_ctx_workarounds_init(struct intel_engine_cs *engine,
 				      struct i915_wa_list *wal)
@@ -592,7 +603,7 @@ static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine,
 	 */
 	wa_add(wal, FF_MODE2, FF_MODE2_TDS_TIMER_MASK, val,
 	       IS_TGL_REVID(engine->i915, TGL_REVID_A0, TGL_REVID_A0) ? 0 :
-			    FF_MODE2_TDS_TIMER_MASK);
+			    FF_MODE2_TDS_TIMER_MASK, false);
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
index e27ab1b710b3..a43d5f968f2d 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
@@ -16,6 +16,7 @@ struct i915_wa {
 	u32		mask;
 	u32		val;
 	u32		read;
+	bool		masked_bits;
 };
 
 struct i915_wa_list {
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index 101728006ae9..3fea13fc2b1a 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -3,6 +3,8 @@
  * Copyright © 2014-2019 Intel Corporation
  */
 
+#include <linux/bsearch.h>
+
 #include "gt/intel_gt.h"
 #include "intel_guc_ads.h"
 #include "intel_uc.h"
@@ -16,6 +18,9 @@
  * its internal state for sleep.
  */
 
+static void guc_mmio_reg_state_init(struct guc_mmio_reg_state *reg_state,
+				    struct intel_engine_cs *engine);
+
 static void guc_policy_init(struct guc_policy *policy)
 {
 	policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US;
@@ -67,12 +72,19 @@ struct __guc_ads_blob {
 
 static void __guc_ads_init(struct intel_guc *guc)
 {
-	struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
+	struct intel_gt *gt = guc_to_gt(guc);
+	struct drm_i915_private *dev_priv = gt->i915;
 	struct __guc_ads_blob *blob = guc->ads_blob;
 	const u32 skipped_size = LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	u32 base;
 	u8 engine_class;
 
+	/* GuC mmio save/restore list */
+	for_each_engine(engine, gt, id)
+		guc_mmio_reg_state_init(&blob->reg_state, engine);
+
 	/* GuC scheduling policies */
 	guc_policies_init(&blob->policies);
 
@@ -170,3 +182,85 @@ void intel_guc_ads_reset(struct intel_guc *guc)
 		return;
 	__guc_ads_init(guc);
 }
+
+static int guc_mmio_reg_cmp(const void *a, const void *b)
+{
+	const struct guc_mmio_reg *ra = a;
+	const struct guc_mmio_reg *rb = b;
+
+	return (int)ra->offset - (int)rb->offset;
+}
+
+static void guc_mmio_reg_add(struct guc_mmio_regset *regset,
+			     u32 offset, u32 flags)
+{
+	u32 count = regset->number_of_registers;
+	struct guc_mmio_reg reg = {
+		.offset = offset,
+		.flags = flags,
+	};
+	struct guc_mmio_reg *slot;
+
+	GEM_BUG_ON(count >= GUC_REGSET_MAX_REGISTERS);
+
+	/*
+	 * The mmio list is built using separate lists within the driver.
+	 * It's possible that at some point we may attempt to add the same
+	 * register more than once. Do not consider this an error; silently
+	 * move on if the register is already in the list.
+	 */
+	if (bsearch(&reg, regset->registers, count,
+		    sizeof(reg), guc_mmio_reg_cmp))
+		return;
+
+	slot = &regset->registers[count];
+	regset->number_of_registers++;
+	*slot = reg;
+
+	while (slot-- > regset->registers) {
+		GEM_BUG_ON(slot[0].offset == slot[1].offset);
+		if (slot[1].offset > slot[0].offset)
+			break;
+
+		swap(slot[1], slot[0]);
+	}
+}
+
+#define GUC_MMIO_REG_ADD(regset, reg, masked) \
+	guc_mmio_reg_add(regset, \
+			 i915_mmio_reg_offset((reg)), \
+			 (masked) ? GUC_REGSET_MASKED : 0)
+
+static void guc_mmio_regset_init(struct guc_mmio_regset *regset,
+				 struct intel_engine_cs *engine)
+{
+	const u32 base = engine->mmio_base;
+	struct i915_wa_list *wal = &engine->wa_list;
+	struct i915_wa *wa;
+	unsigned int i;
+
+	GUC_MMIO_REG_ADD(regset, RING_MODE_GEN7(base), true);
+	GUC_MMIO_REG_ADD(regset, RING_HWS_PGA(base), false);
+	GUC_MMIO_REG_ADD(regset, RING_IMR(base), false);
+
+	for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
+		GUC_MMIO_REG_ADD(regset, wa->reg, wa->masked_bits);
+
+	/* Be extra paranoid and include all whitelist registers. */
+	for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++)
+		GUC_MMIO_REG_ADD(regset,
+				 RING_FORCE_TO_NONPRIV(base, i),
+				 false);
+}
+
+static void guc_mmio_reg_state_init(struct guc_mmio_reg_state *reg_state,
+				    struct intel_engine_cs *engine)
+{
+	struct guc_mmio_regset *regset;
+
+	GEM_BUG_ON(engine->class >= GUC_MAX_ENGINE_CLASSES);
+	GEM_BUG_ON(engine->instance >= GUC_MAX_INSTANCES_PER_CLASS);
+	regset = &reg_state->engine_reg[engine->class][engine->instance];
+
+	guc_mmio_regset_init(regset, engine);
+}
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 7+ messages in thread
* [Intel-gfx] [PATCH 1/2] drm/i915/guc: Provide mmio list to be saved/restored on engine reset
@ 2019-11-22 17:46 ` Fernando Pacheco
  0 siblings, 0 replies; 7+ messages in thread
From: Fernando Pacheco @ 2019-11-22 17:46 UTC (permalink / raw)
  To: intel-gfx

The driver must provide GuC with a list of mmio registers
that should be saved/restored during a GuC-based engine reset.
We provide a minimal set of registers that should get things
working and extend as needed.

The mmio list is built using separate lists within the driver.
It's possible that at some point we may attempt to add the same
register more than once. Do not consider this an error; silently
move on if the register is already in the list.

Signed-off-by: Fernando Pacheco <fernando.pacheco@intel.com>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_workarounds.c   | 23 +++--
 .../gpu/drm/i915/gt/intel_workarounds_types.h |  1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c    | 90 ++++++++++++++++++-
 3 files changed, 107 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 226bd4cccb48..964d6fe8bf5c 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -147,23 +147,31 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
 }
 
 static void
-wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
-		   u32 val)
+__wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
+		     u32 val, bool masked_bits)
 {
 	struct i915_wa wa = {
 		.reg  = reg,
 		.mask = mask,
 		.val  = val,
 		.read = mask,
+		.masked_bits = masked_bits,
 	};
 
 	_wa_add(wal, &wa);
 }
 
+static void
+wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
+		   u32 val)
+{
+	__wa_write_masked_or(wal, reg, mask, val, false);
+}
+
 static void
 wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 {
-	wa_write_masked_or(wal, reg, val, _MASKED_BIT_ENABLE(val));
+	__wa_write_masked_or(wal, reg, val, _MASKED_BIT_ENABLE(val), true);
 }
 
 static void
@@ -179,13 +187,16 @@ wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 }
 
 #define WA_SET_BIT_MASKED(addr, mask) \
-	wa_write_masked_or(wal, (addr), (mask), _MASKED_BIT_ENABLE(mask))
+	__wa_write_masked_or(wal, (addr), (mask), \
+			     _MASKED_BIT_ENABLE(mask), true)
 
 #define WA_CLR_BIT_MASKED(addr, mask) \
-	wa_write_masked_or(wal, (addr), (mask), _MASKED_BIT_DISABLE(mask))
+	__wa_write_masked_or(wal, (addr), (mask), \
+			     _MASKED_BIT_DISABLE(mask), true)
 
 #define WA_SET_FIELD_MASKED(addr, mask, value) \
-	wa_write_masked_or(wal, (addr), (mask), _MASKED_FIELD((mask), (value)))
+	__wa_write_masked_or(wal, (addr), (mask), \
+			     _MASKED_FIELD((mask), (value)), true)
 
 static void gen8_ctx_workarounds_init(struct intel_engine_cs *engine,
 				      struct i915_wa_list *wal)
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
index e27ab1b710b3..a43d5f968f2d 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
@@ -16,6 +16,7 @@ struct i915_wa {
 	u32		mask;
 	u32		val;
 	u32		read;
+	bool		masked_bits;
 };
 
 struct i915_wa_list {
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index ca6674b8e00c..177cbfbb40e7 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -3,6 +3,8 @@
  * Copyright © 2014-2019 Intel Corporation
  */
 
+#include <linux/bsearch.h>
+
 #include "gt/intel_gt.h"
 #include "intel_guc_ads.h"
 #include "intel_uc.h"
@@ -16,6 +18,9 @@
  * its internal state for sleep.
  */
 
+static void guc_mmio_reg_state_init(struct guc_mmio_reg_state *reg_state,
+				    struct intel_engine_cs *engine);
+
 static void guc_policy_init(struct guc_policy *policy)
 {
 	policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US;
@@ -67,12 +72,19 @@ struct __guc_ads_blob {
 
 static void __guc_ads_init(struct intel_guc *guc)
 {
-	struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
+	struct intel_gt *gt = guc_to_gt(guc);
+	struct drm_i915_private *dev_priv = gt->i915;
 	struct __guc_ads_blob *blob = guc->ads_blob;
 	const u32 skipped_size = LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	u32 base;
 	u8 engine_class;
 
+	/* GuC mmio save/restore list */
+	for_each_engine(engine, gt, id)
+		guc_mmio_reg_state_init(&blob->reg_state, engine);
+
 	/* GuC scheduling policies */
 	guc_policies_init(&blob->policies);
 
@@ -182,3 +194,79 @@ void intel_guc_ads_reset(struct intel_guc *guc)
 		return;
 	__guc_ads_init(guc);
 }
+
+static int guc_mmio_reg_cmp(const void *a, const void *b)
+{
+	const struct guc_mmio_reg *ra = a;
+	const struct guc_mmio_reg *rb = b;
+
+	return (int)ra->offset - (int)rb->offset;
+}
+
+static void guc_mmio_reg_add(struct guc_mmio_regset *regset,
+			     u32 offset, u32 flags)
+{
+	u32 count = regset->number_of_registers;
+	struct guc_mmio_reg reg = {
+		.offset = offset,
+		.flags = flags,
+	};
+	struct guc_mmio_reg *slot;
+
+	GEM_BUG_ON(count >= GUC_REGSET_MAX_REGISTERS);
+
+	if (bsearch(&reg, regset->registers, count,
+		    sizeof(reg), guc_mmio_reg_cmp))
+		return;
+
+	slot = &regset->registers[count];
+	regset->number_of_registers++;
+	*slot = reg;
+
+	while (slot-- > regset->registers) {
+		GEM_BUG_ON(slot[0].offset == slot[1].offset);
+		if (slot[1].offset > slot[0].offset)
+			break;
+
+		swap(slot[1], slot[0]);
+	}
+}
+
+#define GUC_MMIO_REG_ADD(regset, reg, masked) \
+	guc_mmio_reg_add(regset, \
+			 i915_mmio_reg_offset((reg)), \
+			 (masked) ? GUC_REGSET_MASKED : 0)
+
+static void guc_mmio_regset_init(struct guc_mmio_regset *regset,
+				 struct intel_engine_cs *engine)
+{
+	const u32 base = engine->mmio_base;
+	struct i915_wa_list *wal = &engine->wa_list;
+	struct i915_wa *wa;
+	unsigned int i;
+
+	GUC_MMIO_REG_ADD(regset, RING_MODE_GEN7(base), true);
+	GUC_MMIO_REG_ADD(regset, RING_HWS_PGA(base), false);
+	GUC_MMIO_REG_ADD(regset, RING_IMR(base), false);
+
+	for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
+		GUC_MMIO_REG_ADD(regset, wa->reg, wa->masked_bits);
+
+	/* Be extra paranoid and include all whitelist registers. */
+	for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++)
+		GUC_MMIO_REG_ADD(regset,
+				 RING_FORCE_TO_NONPRIV(base, i),
+				 false);
+}
+
+static void guc_mmio_reg_state_init(struct guc_mmio_reg_state *reg_state,
+				    struct intel_engine_cs *engine)
+{
+	struct guc_mmio_regset *regset;
+
+	GEM_BUG_ON(engine->class >= GUC_MAX_ENGINE_CLASSES);
+	GEM_BUG_ON(engine->instance >= GUC_MAX_INSTANCES_PER_CLASS);
+	regset = &reg_state->engine_reg[engine->class][engine->instance];
+
+	guc_mmio_regset_init(regset, engine);
+}
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-12-18 23:31 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-12 18:43 [Intel-gfx] [PATCH 1/2] drm/i915/guc: Provide mmio list to be saved/restored on engine reset Fernando Pacheco
2019-12-12 18:43 ` [Intel-gfx] [PATCH 2/2] HAX: force enable_guc=2 and WA i915#571 Fernando Pacheco
2019-12-12 20:42 ` [Intel-gfx] ✓ Fi.CI.BAT: success for series starting with [1/2] drm/i915/guc: Provide mmio list to be saved/restored on engine reset Patchwork
2019-12-12 23:01 ` [Intel-gfx] [PATCH 1/2] " Tvrtko Ursulin
2019-12-18 23:31   ` Daniele Ceraolo Spurio
2019-12-13 12:40 ` [Intel-gfx] ✗ Fi.CI.IGT: failure for series starting with [1/2] " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2019-11-22 17:46 [Intel-gfx] [PATCH 1/2] " Fernando Pacheco
2019-11-22 17:46 ` Fernando Pacheco

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.