summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_uncore.c
diff options
context:
space:
mode:
authorOscar Mateo <oscar.mateo@intel.com>2018-12-13 09:15:22 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2018-12-13 10:07:56 +0000
commitf513ac76530c2769ebf6e8954c45f39c6985cfb6 (patch)
tree85e97e66c1242060fbca0442cc5b825da76355c8 /drivers/gpu/drm/i915/intel_uncore.c
parent57b19d55189bacc9408519cd7ab5ade6ca2d4ac5 (diff)
drm/i915/icl: Mind the SFC units when resetting VD or VEBox engines
SFC (Scaler & Format Converter) units are shared between VD and VEBoxes. They also happen to have separate reset bits. So, whenever we want to reset one or more of the media engines, we have to make sure the SFCs do not change owner in the process and, if this owner happens to be one of the engines being reset, we need to reset the SFC as well. This happens in 4 steps: 1) Tell the engine that a software reset is going to happen. The engine will then try to force lock the SFC (if currently locked, it will remain so; if currently unlocked, it will ignore this and all new lock requests). 2) Poll the ack bit to make sure the hardware has received the forced lock from the driver. Once this bit is set, it indicates SFC status (lock or unlock) will not change anymore (until we tell the engine it is safe to unlock again). 3) Check the usage bit to see if the SFC has ended up being locked to the engine we want to reset. If this is the case, we have to reset the SFC as well. 4) Unlock all the SFCs once the reset sequence is completed. Obviously, if we are resetting the whole GPU, we don't have to worry about all of this. BSpec: 10989 BSpec: 10990 BSpec: 10954 BSpec: 10955 BSpec: 10956 BSpec: 19212 Signed-off-by: Tomasz Lis <tomasz.lis@intel.com> Signed-off-by: Oscar Mateo <oscar.mateo@intel.com> Signed-off-by: Michel Thierry <michel.thierry@intel.com> Cc: Michel Thierry <michel.thierry@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20181213091522.2926-4-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/intel_uncore.c')
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c115
1 files changed, 110 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index ec6dde2e59eb..5800f0ce2c57 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1931,6 +1931,103 @@ static int gen6_reset_engines(struct drm_i915_private *dev_priv,
return gen6_hw_domain_reset(dev_priv, hw_mask);
}
+static u32 gen11_lock_sfc(struct drm_i915_private *dev_priv,
+ struct intel_engine_cs *engine)
+{
+ u8 vdbox_sfc_access = INTEL_INFO(dev_priv)->vdbox_sfc_access;
+ i915_reg_t sfc_forced_lock, sfc_forced_lock_ack;
+ u32 sfc_forced_lock_bit, sfc_forced_lock_ack_bit;
+ i915_reg_t sfc_usage;
+ u32 sfc_usage_bit;
+ u32 sfc_reset_bit;
+
+ switch (engine->class) {
+ case VIDEO_DECODE_CLASS:
+ if ((BIT(engine->instance) & vdbox_sfc_access) == 0)
+ return 0;
+
+ sfc_forced_lock = GEN11_VCS_SFC_FORCED_LOCK(engine);
+ sfc_forced_lock_bit = GEN11_VCS_SFC_FORCED_LOCK_BIT;
+
+ sfc_forced_lock_ack = GEN11_VCS_SFC_LOCK_STATUS(engine);
+ sfc_forced_lock_ack_bit = GEN11_VCS_SFC_LOCK_ACK_BIT;
+
+ sfc_usage = GEN11_VCS_SFC_LOCK_STATUS(engine);
+ sfc_usage_bit = GEN11_VCS_SFC_USAGE_BIT;
+ sfc_reset_bit = GEN11_VCS_SFC_RESET_BIT(engine->instance);
+ break;
+
+ case VIDEO_ENHANCEMENT_CLASS:
+ sfc_forced_lock = GEN11_VECS_SFC_FORCED_LOCK(engine);
+ sfc_forced_lock_bit = GEN11_VECS_SFC_FORCED_LOCK_BIT;
+
+ sfc_forced_lock_ack = GEN11_VECS_SFC_LOCK_ACK(engine);
+ sfc_forced_lock_ack_bit = GEN11_VECS_SFC_LOCK_ACK_BIT;
+
+ sfc_usage = GEN11_VECS_SFC_USAGE(engine);
+ sfc_usage_bit = GEN11_VECS_SFC_USAGE_BIT;
+ sfc_reset_bit = GEN11_VECS_SFC_RESET_BIT(engine->instance);
+ break;
+
+ default:
+ return 0;
+ }
+
+ /*
+ * Tell the engine that a software reset is going to happen. The engine
+ * will then try to force lock the SFC (if currently locked, it will
+ * remain so until we tell the engine it is safe to unlock; if currently
+ * unlocked, it will ignore this and all new lock requests). If SFC
+ * ends up being locked to the engine we want to reset, we have to reset
+ * it as well (we will unlock it once the reset sequence is completed).
+ */
+ I915_WRITE_FW(sfc_forced_lock,
+ I915_READ_FW(sfc_forced_lock) | sfc_forced_lock_bit);
+
+ if (__intel_wait_for_register_fw(dev_priv,
+ sfc_forced_lock_ack,
+ sfc_forced_lock_ack_bit,
+ sfc_forced_lock_ack_bit,
+ 1000, 0, NULL)) {
+ DRM_DEBUG_DRIVER("Wait for SFC forced lock ack failed\n");
+ return 0;
+ }
+
+ if (I915_READ_FW(sfc_usage) & sfc_usage_bit)
+ return sfc_reset_bit;
+
+ return 0;
+}
+
+static void gen11_unlock_sfc(struct drm_i915_private *dev_priv,
+ struct intel_engine_cs *engine)
+{
+ u8 vdbox_sfc_access = INTEL_INFO(dev_priv)->vdbox_sfc_access;
+ i915_reg_t sfc_forced_lock;
+ u32 sfc_forced_lock_bit;
+
+ switch (engine->class) {
+ case VIDEO_DECODE_CLASS:
+ if ((BIT(engine->instance) & vdbox_sfc_access) == 0)
+ return;
+
+ sfc_forced_lock = GEN11_VCS_SFC_FORCED_LOCK(engine);
+ sfc_forced_lock_bit = GEN11_VCS_SFC_FORCED_LOCK_BIT;
+ break;
+
+ case VIDEO_ENHANCEMENT_CLASS:
+ sfc_forced_lock = GEN11_VECS_SFC_FORCED_LOCK(engine);
+ sfc_forced_lock_bit = GEN11_VECS_SFC_FORCED_LOCK_BIT;
+ break;
+
+ default:
+ return;
+ }
+
+ I915_WRITE_FW(sfc_forced_lock,
+ I915_READ_FW(sfc_forced_lock) & ~sfc_forced_lock_bit);
+}
+
/**
* gen11_reset_engines - reset individual engines
* @dev_priv: i915 device
@@ -1947,7 +2044,6 @@ static int gen6_reset_engines(struct drm_i915_private *dev_priv,
static int gen11_reset_engines(struct drm_i915_private *dev_priv,
unsigned int engine_mask)
{
- struct intel_engine_cs *engine;
const u32 hw_engine_mask[I915_NUM_ENGINES] = {
[RCS] = GEN11_GRDOM_RENDER,
[BCS] = GEN11_GRDOM_BLT,
@@ -1958,21 +2054,30 @@ static int gen11_reset_engines(struct drm_i915_private *dev_priv,
[VECS] = GEN11_GRDOM_VECS,
[VECS2] = GEN11_GRDOM_VECS2,
};
+ struct intel_engine_cs *engine;
+ unsigned int tmp;
u32 hw_mask;
+ int ret;
BUILD_BUG_ON(VECS2 + 1 != I915_NUM_ENGINES);
if (engine_mask == ALL_ENGINES) {
hw_mask = GEN11_GRDOM_FULL;
} else {
- unsigned int tmp;
-
hw_mask = 0;
- for_each_engine_masked(engine, dev_priv, engine_mask, tmp)
+ for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
hw_mask |= hw_engine_mask[engine->id];
+ hw_mask |= gen11_lock_sfc(dev_priv, engine);
+ }
}
- return gen6_hw_domain_reset(dev_priv, hw_mask);
+ ret = gen6_hw_domain_reset(dev_priv, hw_mask);
+
+ if (engine_mask != ALL_ENGINES)
+ for_each_engine_masked(engine, dev_priv, engine_mask, tmp)
+ gen11_unlock_sfc(dev_priv, engine);
+
+ return ret;
}
/**