Message ID | 1540995854-9032-1-git-send-email-tomasz.lis@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v1,1/2] drm/i915/icl: Mind the SFC units when resetting VD or VEBox engines | expand |
Quoting Tomasz Lis (2018-10-31 14:24:13) > From: Oscar Mateo <oscar.mateo@intel.com> > > 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> > --- > drivers/gpu/drm/i915/i915_reg.h | 18 +++++++ > drivers/gpu/drm/i915/intel_uncore.c | 105 ++++++++++++++++++++++++++++++++++-- > 2 files changed, 119 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 8d089ef..7b4dffa 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -330,6 +330,24 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) > #define GEN11_GRDOM_MEDIA4 (1 << 8) > #define GEN11_GRDOM_VECS (1 << 13) > #define GEN11_GRDOM_VECS2 (1 << 14) > +#define GEN11_GRDOM_SFC0 (1 << 17) > +#define GEN11_GRDOM_SFC1 (1 << 18) > + > +#define GEN11_VCS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << ((instance) >> 1)) > +#define GEN11_VECS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << (instance)) > + > +#define GEN11_VCS_SFC_FORCED_LOCK(engine) _MMIO((engine)->mmio_base + 0x88C) > +#define GEN11_VCS_SFC_FORCED_LOCK_BIT (1 << 0) > +#define GEN11_VCS_SFC_LOCK_STATUS(engine) _MMIO((engine)->mmio_base + 0x890) > +#define GEN11_VCS_SFC_USAGE_BIT (1 << 0) > +#define GEN11_VCS_SFC_LOCK_ACK_BIT (1 << 1) > + > +#define GEN11_VECS_SFC_FORCED_LOCK(engine) _MMIO((engine)->mmio_base + 0x201C) > +#define GEN11_VECS_SFC_FORCED_LOCK_BIT (1 << 0) > +#define GEN11_VECS_SFC_LOCK_ACK(engine) _MMIO((engine)->mmio_base + 0x2018) > +#define GEN11_VECS_SFC_LOCK_ACK_BIT (1 << 0) > +#define GEN11_VECS_SFC_USAGE(engine) _MMIO((engine)->mmio_base + 0x2014) > +#define GEN11_VECS_SFC_USAGE_BIT (1 << 0) > > #define RING_PP_DIR_BASE(engine) _MMIO((engine)->mmio_base + 0x228) > #define RING_PP_DIR_BASE_READ(engine) _MMIO((engine)->mmio_base + 0x518) > diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c > index 9289515..481e70e 100644 > --- a/drivers/gpu/drm/i915/intel_uncore.c > +++ b/drivers/gpu/drm/i915/intel_uncore.c > @@ -1931,6 +1931,95 @@ 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; > + u32 sfc_forced_lock_bit; > + i915_reg_t sfc_forced_lock_ack; > + u32 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(sfc_forced_lock, I915_READ(sfc_forced_lock) | > + sfc_forced_lock_bit); > + > + if (intel_wait_for_register(dev_priv, > + sfc_forced_lock_ack, > + sfc_forced_lock_ack_bit, > + sfc_forced_lock_ack_bit, > + 500)) { Sleeping is not allowed. -Chris
Quoting Chris Wilson (2018-10-31 14:25:40) > Quoting Tomasz Lis (2018-10-31 14:24:13) > > From: Oscar Mateo <oscar.mateo@intel.com> > > > > 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> > > --- > > drivers/gpu/drm/i915/i915_reg.h | 18 +++++++ > > drivers/gpu/drm/i915/intel_uncore.c | 105 ++++++++++++++++++++++++++++++++++-- > > 2 files changed, 119 insertions(+), 4 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > > index 8d089ef..7b4dffa 100644 > > --- a/drivers/gpu/drm/i915/i915_reg.h > > +++ b/drivers/gpu/drm/i915/i915_reg.h > > @@ -330,6 +330,24 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) > > #define GEN11_GRDOM_MEDIA4 (1 << 8) > > #define GEN11_GRDOM_VECS (1 << 13) > > #define GEN11_GRDOM_VECS2 (1 << 14) > > +#define GEN11_GRDOM_SFC0 (1 << 17) > > +#define GEN11_GRDOM_SFC1 (1 << 18) > > + > > +#define GEN11_VCS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << ((instance) >> 1)) > > +#define GEN11_VECS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << (instance)) > > + > > +#define GEN11_VCS_SFC_FORCED_LOCK(engine) _MMIO((engine)->mmio_base + 0x88C) > > +#define GEN11_VCS_SFC_FORCED_LOCK_BIT (1 << 0) > > +#define GEN11_VCS_SFC_LOCK_STATUS(engine) _MMIO((engine)->mmio_base + 0x890) > > +#define GEN11_VCS_SFC_USAGE_BIT (1 << 0) > > +#define GEN11_VCS_SFC_LOCK_ACK_BIT (1 << 1) > > + > > +#define GEN11_VECS_SFC_FORCED_LOCK(engine) _MMIO((engine)->mmio_base + 0x201C) > > +#define GEN11_VECS_SFC_FORCED_LOCK_BIT (1 << 0) > > +#define GEN11_VECS_SFC_LOCK_ACK(engine) _MMIO((engine)->mmio_base + 0x2018) > > +#define GEN11_VECS_SFC_LOCK_ACK_BIT (1 << 0) > > +#define GEN11_VECS_SFC_USAGE(engine) _MMIO((engine)->mmio_base + 0x2014) > > +#define GEN11_VECS_SFC_USAGE_BIT (1 << 0) > > > > #define RING_PP_DIR_BASE(engine) _MMIO((engine)->mmio_base + 0x228) > > #define RING_PP_DIR_BASE_READ(engine) _MMIO((engine)->mmio_base + 0x518) > > diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c > > index 9289515..481e70e 100644 > > --- a/drivers/gpu/drm/i915/intel_uncore.c > > +++ b/drivers/gpu/drm/i915/intel_uncore.c > > @@ -1931,6 +1931,95 @@ 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; > > + u32 sfc_forced_lock_bit; > > + i915_reg_t sfc_forced_lock_ack; > > + u32 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(sfc_forced_lock, I915_READ(sfc_forced_lock) | > > + sfc_forced_lock_bit); > > + > > + if (intel_wait_for_register(dev_priv, > > + sfc_forced_lock_ack, > > + sfc_forced_lock_ack_bit, > > + sfc_forced_lock_ack_bit, > > + 500)) { > > Sleeping is not allowed. I guess you really should review the selftests first. -Chris
Tomasz Lis <tomasz.lis@intel.com> writes: > From: Oscar Mateo <oscar.mateo@intel.com> > > 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> > --- > drivers/gpu/drm/i915/i915_reg.h | 18 +++++++ > drivers/gpu/drm/i915/intel_uncore.c | 105 ++++++++++++++++++++++++++++++++++-- > 2 files changed, 119 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 8d089ef..7b4dffa 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -330,6 +330,24 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) > #define GEN11_GRDOM_MEDIA4 (1 << 8) > #define GEN11_GRDOM_VECS (1 << 13) > #define GEN11_GRDOM_VECS2 (1 << 14) > +#define GEN11_GRDOM_SFC0 (1 << 17) > +#define GEN11_GRDOM_SFC1 (1 << 18) > + > +#define GEN11_VCS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << ((instance) >> 1)) > +#define GEN11_VECS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << (instance)) > + > +#define GEN11_VCS_SFC_FORCED_LOCK(engine) _MMIO((engine)->mmio_base + 0x88C) > +#define GEN11_VCS_SFC_FORCED_LOCK_BIT (1 << 0) > +#define GEN11_VCS_SFC_LOCK_STATUS(engine) _MMIO((engine)->mmio_base + 0x890) > +#define GEN11_VCS_SFC_USAGE_BIT (1 << 0) > +#define GEN11_VCS_SFC_LOCK_ACK_BIT (1 << 1) > + > +#define GEN11_VECS_SFC_FORCED_LOCK(engine) _MMIO((engine)->mmio_base + 0x201C) > +#define GEN11_VECS_SFC_FORCED_LOCK_BIT (1 << 0) > +#define GEN11_VECS_SFC_LOCK_ACK(engine) _MMIO((engine)->mmio_base + 0x2018) > +#define GEN11_VECS_SFC_LOCK_ACK_BIT (1 << 0) > +#define GEN11_VECS_SFC_USAGE(engine) _MMIO((engine)->mmio_base + 0x2014) > +#define GEN11_VECS_SFC_USAGE_BIT (1 << 0) > > #define RING_PP_DIR_BASE(engine) _MMIO((engine)->mmio_base + 0x228) > #define RING_PP_DIR_BASE_READ(engine) _MMIO((engine)->mmio_base + 0x518) > diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c > index 9289515..481e70e 100644 > --- a/drivers/gpu/drm/i915/intel_uncore.c > +++ b/drivers/gpu/drm/i915/intel_uncore.c > @@ -1931,6 +1931,95 @@ 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; > + u32 sfc_forced_lock_bit; > + i915_reg_t sfc_forced_lock_ack; > + u32 sfc_forced_lock_ack_bit; > + i915_reg_t sfc_usage; > + u32 sfc_usage_bit; > + u32 sfc_reset_bit; > + You can save many lines here by grouping by type. -Mika > + 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(sfc_forced_lock, I915_READ(sfc_forced_lock) | > + sfc_forced_lock_bit); > + > + if (intel_wait_for_register(dev_priv, > + sfc_forced_lock_ack, > + sfc_forced_lock_ack_bit, > + sfc_forced_lock_ack_bit, > + 500)) { > + DRM_DEBUG_DRIVER("Wait for SFC forced lock ack failed\n"); > + return 0; > + } > + > + if ((I915_READ(sfc_usage) & sfc_usage_bit) == 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(sfc_forced_lock, (I915_READ(sfc_forced_lock) & > + ~sfc_forced_lock_bit)); > +} > + > /** > * gen11_reset_engines - reset individual engines > * @dev_priv: i915 device > @@ -1959,20 +2048,28 @@ static int gen11_reset_engines(struct drm_i915_private *dev_priv, > [VECS2] = GEN11_GRDOM_VECS2, > }; > u32 hw_mask; > + unsigned int tmp; > + 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; > } > > /** > -- > 2.7.4 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8d089ef..7b4dffa 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -330,6 +330,24 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define GEN11_GRDOM_MEDIA4 (1 << 8) #define GEN11_GRDOM_VECS (1 << 13) #define GEN11_GRDOM_VECS2 (1 << 14) +#define GEN11_GRDOM_SFC0 (1 << 17) +#define GEN11_GRDOM_SFC1 (1 << 18) + +#define GEN11_VCS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << ((instance) >> 1)) +#define GEN11_VECS_SFC_RESET_BIT(instance) (GEN11_GRDOM_SFC0 << (instance)) + +#define GEN11_VCS_SFC_FORCED_LOCK(engine) _MMIO((engine)->mmio_base + 0x88C) +#define GEN11_VCS_SFC_FORCED_LOCK_BIT (1 << 0) +#define GEN11_VCS_SFC_LOCK_STATUS(engine) _MMIO((engine)->mmio_base + 0x890) +#define GEN11_VCS_SFC_USAGE_BIT (1 << 0) +#define GEN11_VCS_SFC_LOCK_ACK_BIT (1 << 1) + +#define GEN11_VECS_SFC_FORCED_LOCK(engine) _MMIO((engine)->mmio_base + 0x201C) +#define GEN11_VECS_SFC_FORCED_LOCK_BIT (1 << 0) +#define GEN11_VECS_SFC_LOCK_ACK(engine) _MMIO((engine)->mmio_base + 0x2018) +#define GEN11_VECS_SFC_LOCK_ACK_BIT (1 << 0) +#define GEN11_VECS_SFC_USAGE(engine) _MMIO((engine)->mmio_base + 0x2014) +#define GEN11_VECS_SFC_USAGE_BIT (1 << 0) #define RING_PP_DIR_BASE(engine) _MMIO((engine)->mmio_base + 0x228) #define RING_PP_DIR_BASE_READ(engine) _MMIO((engine)->mmio_base + 0x518) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 9289515..481e70e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1931,6 +1931,95 @@ 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; + u32 sfc_forced_lock_bit; + i915_reg_t sfc_forced_lock_ack; + u32 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(sfc_forced_lock, I915_READ(sfc_forced_lock) | + sfc_forced_lock_bit); + + if (intel_wait_for_register(dev_priv, + sfc_forced_lock_ack, + sfc_forced_lock_ack_bit, + sfc_forced_lock_ack_bit, + 500)) { + DRM_DEBUG_DRIVER("Wait for SFC forced lock ack failed\n"); + return 0; + } + + if ((I915_READ(sfc_usage) & sfc_usage_bit) == 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(sfc_forced_lock, (I915_READ(sfc_forced_lock) & + ~sfc_forced_lock_bit)); +} + /** * gen11_reset_engines - reset individual engines * @dev_priv: i915 device @@ -1959,20 +2048,28 @@ static int gen11_reset_engines(struct drm_i915_private *dev_priv, [VECS2] = GEN11_GRDOM_VECS2, }; u32 hw_mask; + unsigned int tmp; + 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; } /**