* [Intel-gfx] [PATCH 2/4] drm/i915/gt: Pass gt rather than uncore to lowest-level reads/writes
2022-11-22 20:33 [Intel-gfx] [PATCH 0/4] i915: dedicated MCR locking and hardware semaphore Matt Roper
2022-11-22 20:33 ` [Intel-gfx] [PATCH 1/4] drm/i915/gt: Correct kerneldoc for intel_gt_mcr_wait_for_reg() Matt Roper
@ 2022-11-22 20:33 ` Matt Roper
2022-11-22 20:34 ` [Intel-gfx] [PATCH 3/4] drm/i915/gt: Add dedicated MCR lock Matt Roper
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Matt Roper @ 2022-11-22 20:33 UTC (permalink / raw)
To: intel-gfx; +Cc: dri-devel
Passing the GT rather than uncore to the lowest level MCR read and write
functions will make it easier to introduce dedicated MCR locking in a
folling patch.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
drivers/gpu/drm/i915/gt/intel_gt_mcr.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
index ea86c1ab5dc5..f4484bb18ec9 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
@@ -221,7 +221,7 @@ static i915_reg_t mcr_reg_cast(const i915_mcr_reg_t mcr)
/*
* rw_with_mcr_steering_fw - Access a register with specific MCR steering
- * @uncore: pointer to struct intel_uncore
+ * @gt: GT to read register from
* @reg: register being accessed
* @rw_flag: FW_REG_READ for read access or FW_REG_WRITE for write access
* @group: group number (documented as "sliceid" on older platforms)
@@ -232,10 +232,11 @@ static i915_reg_t mcr_reg_cast(const i915_mcr_reg_t mcr)
*
* Caller needs to make sure the relevant forcewake wells are up.
*/
-static u32 rw_with_mcr_steering_fw(struct intel_uncore *uncore,
+static u32 rw_with_mcr_steering_fw(struct intel_gt *gt,
i915_mcr_reg_t reg, u8 rw_flag,
int group, int instance, u32 value)
{
+ struct intel_uncore *uncore = gt->uncore;
u32 mcr_mask, mcr_ss, mcr, old_mcr, val = 0;
lockdep_assert_held(&uncore->lock);
@@ -308,11 +309,12 @@ static u32 rw_with_mcr_steering_fw(struct intel_uncore *uncore,
return val;
}
-static u32 rw_with_mcr_steering(struct intel_uncore *uncore,
+static u32 rw_with_mcr_steering(struct intel_gt *gt,
i915_mcr_reg_t reg, u8 rw_flag,
int group, int instance,
u32 value)
{
+ struct intel_uncore *uncore = gt->uncore;
enum forcewake_domains fw_domains;
u32 val;
@@ -325,7 +327,7 @@ static u32 rw_with_mcr_steering(struct intel_uncore *uncore,
spin_lock_irq(&uncore->lock);
intel_uncore_forcewake_get__locked(uncore, fw_domains);
- val = rw_with_mcr_steering_fw(uncore, reg, rw_flag, group, instance, value);
+ val = rw_with_mcr_steering_fw(gt, reg, rw_flag, group, instance, value);
intel_uncore_forcewake_put__locked(uncore, fw_domains);
spin_unlock_irq(&uncore->lock);
@@ -347,7 +349,7 @@ u32 intel_gt_mcr_read(struct intel_gt *gt,
i915_mcr_reg_t reg,
int group, int instance)
{
- return rw_with_mcr_steering(gt->uncore, reg, FW_REG_READ, group, instance, 0);
+ return rw_with_mcr_steering(gt, reg, FW_REG_READ, group, instance, 0);
}
/**
@@ -364,7 +366,7 @@ u32 intel_gt_mcr_read(struct intel_gt *gt,
void intel_gt_mcr_unicast_write(struct intel_gt *gt, i915_mcr_reg_t reg, u32 value,
int group, int instance)
{
- rw_with_mcr_steering(gt->uncore, reg, FW_REG_WRITE, group, instance, value);
+ rw_with_mcr_steering(gt, reg, FW_REG_WRITE, group, instance, value);
}
/**
@@ -588,7 +590,7 @@ u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_mcr_reg_t reg)
for (type = 0; type < NUM_STEERING_TYPES; type++) {
if (reg_needs_read_steering(gt, reg, type)) {
get_nonterminated_steering(gt, type, &group, &instance);
- return rw_with_mcr_steering_fw(gt->uncore, reg,
+ return rw_with_mcr_steering_fw(gt, reg,
FW_REG_READ,
group, instance, 0);
}
@@ -615,7 +617,7 @@ u32 intel_gt_mcr_read_any(struct intel_gt *gt, i915_mcr_reg_t reg)
for (type = 0; type < NUM_STEERING_TYPES; type++) {
if (reg_needs_read_steering(gt, reg, type)) {
get_nonterminated_steering(gt, type, &group, &instance);
- return rw_with_mcr_steering(gt->uncore, reg,
+ return rw_with_mcr_steering(gt, reg,
FW_REG_READ,
group, instance, 0);
}
--
2.38.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [Intel-gfx] [PATCH 3/4] drm/i915/gt: Add dedicated MCR lock
2022-11-22 20:33 [Intel-gfx] [PATCH 0/4] i915: dedicated MCR locking and hardware semaphore Matt Roper
2022-11-22 20:33 ` [Intel-gfx] [PATCH 1/4] drm/i915/gt: Correct kerneldoc for intel_gt_mcr_wait_for_reg() Matt Roper
2022-11-22 20:33 ` [Intel-gfx] [PATCH 2/4] drm/i915/gt: Pass gt rather than uncore to lowest-level reads/writes Matt Roper
@ 2022-11-22 20:34 ` Matt Roper
2022-11-22 20:34 ` [Intel-gfx] [PATCH 4/4] drm/i915/mtl: Add hardware-level lock for steering Matt Roper
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Matt Roper @ 2022-11-22 20:34 UTC (permalink / raw)
To: intel-gfx; +Cc: Chris Wilson, Balasubramani Vivekanandan, dri-devel
We've been overloading uncore->lock to protect access to the MCR
steering register. That's not really what uncore->lock is intended for,
and it would be better if we didn't need to hold such a high-traffic
spinlock for the whole sequence of (apply steering, access MCR register,
restore steering). Let's create a dedicated MCR lock to protect the
steering control register over this critical section and stop relying on
the high-traffic uncore->lock.
For now the new lock is a software lock. However some platforms (MTL
and beyond) have a hardware-provided locking mechanism that can be used
to serialize not only software accesses, but also hardware/firmware
accesses as well; support for that hardware level lock will be added in
a future patch.
Cc: Chris Wilson <chris.p.wilson@linux.intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
drivers/gpu/drm/i915/gt/intel_gt.c | 2 +
drivers/gpu/drm/i915/gt/intel_gt_mcr.c | 66 ++++++++++++++++++++-
drivers/gpu/drm/i915/gt/intel_gt_mcr.h | 2 +
drivers/gpu/drm/i915/gt/intel_gt_types.h | 8 +++
drivers/gpu/drm/i915/gt/intel_mocs.c | 2 +
drivers/gpu/drm/i915/gt/intel_workarounds.c | 4 ++
6 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index b5ad9caa5537..f823fc0b3827 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -1094,6 +1094,7 @@ static void mmio_invalidate_full(struct intel_gt *gt)
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
+ intel_gt_mcr_lock(gt);
spin_lock_irq(&uncore->lock); /* serialise invalidate with GT reset */
awake = 0;
@@ -1129,6 +1130,7 @@ static void mmio_invalidate_full(struct intel_gt *gt)
intel_uncore_write_fw(uncore, GEN12_OA_TLB_INV_CR, 1);
spin_unlock_irq(&uncore->lock);
+ intel_gt_mcr_unlock(gt);
for_each_engine_masked(engine, gt, awake, tmp) {
struct reg_and_bit rb;
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
index f4484bb18ec9..f9e722d91904 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
@@ -143,6 +143,8 @@ void intel_gt_mcr_init(struct intel_gt *gt)
unsigned long fuse;
int i;
+ spin_lock_init(>->mcr_lock);
+
/*
* An mslice is unavailable only if both the meml3 for the slice is
* disabled *and* all of the DSS in the slice (quadrant) are disabled.
@@ -228,6 +230,7 @@ static i915_reg_t mcr_reg_cast(const i915_mcr_reg_t mcr)
* @instance: instance number (documented as "subsliceid" on older platforms)
* @value: register value to be written (ignored for read)
*
+ * Context: The caller must hold the MCR lock
* Return: 0 for write access. register value for read access.
*
* Caller needs to make sure the relevant forcewake wells are up.
@@ -239,7 +242,7 @@ static u32 rw_with_mcr_steering_fw(struct intel_gt *gt,
struct intel_uncore *uncore = gt->uncore;
u32 mcr_mask, mcr_ss, mcr, old_mcr, val = 0;
- lockdep_assert_held(&uncore->lock);
+ lockdep_assert_held(>->mcr_lock);
if (GRAPHICS_VER_FULL(uncore->i915) >= IP_VER(12, 70)) {
/*
@@ -324,6 +327,7 @@ static u32 rw_with_mcr_steering(struct intel_gt *gt,
GEN8_MCR_SELECTOR,
FW_REG_READ | FW_REG_WRITE);
+ intel_gt_mcr_lock(gt);
spin_lock_irq(&uncore->lock);
intel_uncore_forcewake_get__locked(uncore, fw_domains);
@@ -331,10 +335,45 @@ static u32 rw_with_mcr_steering(struct intel_gt *gt,
intel_uncore_forcewake_put__locked(uncore, fw_domains);
spin_unlock_irq(&uncore->lock);
+ intel_gt_mcr_unlock(gt);
return val;
}
+/**
+ * intel_gt_mcr_lock - Acquire MCR steering lock
+ * @gt: GT structure
+ *
+ * Performs locking to protect the steering for the duration of an MCR
+ * operation. Depending on the platform, this may be a software lock
+ * (gt->mcr_lock) or a hardware lock (i.e., a register that synchronizes
+ * access not only for the driver, but also for external hardware and
+ * firmware agents).
+ *
+ * Context: Takes gt->mcr_lock. uncore->lock should *not* be held when this
+ * function is called, although it may be acquired after this
+ * function call.
+ */
+void intel_gt_mcr_lock(struct intel_gt *gt)
+{
+ lockdep_assert_not_held(>->uncore->lock);
+
+ spin_lock(>->mcr_lock);
+}
+
+/**
+ * intel_gt_mcr_unlock - Release MCR steering lock
+ * @gt: GT structure
+ *
+ * Releases the lock acquired by intel_gt_mcr_lock().
+ *
+ * Context: Releases gt->mcr_lock
+ */
+void intel_gt_mcr_unlock(struct intel_gt *gt)
+{
+ spin_unlock(>->mcr_lock);
+}
+
/**
* intel_gt_mcr_read - read a specific instance of an MCR register
* @gt: GT structure
@@ -342,6 +381,8 @@ static u32 rw_with_mcr_steering(struct intel_gt *gt,
* @group: the MCR group
* @instance: the MCR instance
*
+ * Context: Takes and releases gt->mcr_lock
+ *
* Returns the value read from an MCR register after steering toward a specific
* group/instance.
*/
@@ -362,6 +403,8 @@ u32 intel_gt_mcr_read(struct intel_gt *gt,
*
* Write an MCR register in unicast mode after steering toward a specific
* group/instance.
+ *
+ * Context: Calls a function that takes and releases gt->mcr_lock
*/
void intel_gt_mcr_unicast_write(struct intel_gt *gt, i915_mcr_reg_t reg, u32 value,
int group, int instance)
@@ -376,10 +419,14 @@ void intel_gt_mcr_unicast_write(struct intel_gt *gt, i915_mcr_reg_t reg, u32 val
* @value: value to write
*
* Write an MCR register in multicast mode to update all instances.
+ *
+ * Context: Takes and releases gt->mcr_lock
*/
void intel_gt_mcr_multicast_write(struct intel_gt *gt,
i915_mcr_reg_t reg, u32 value)
{
+ intel_gt_mcr_lock(gt);
+
/*
* Ensure we have multicast behavior, just in case some non-i915 agent
* left the hardware in unicast mode.
@@ -388,6 +435,8 @@ void intel_gt_mcr_multicast_write(struct intel_gt *gt,
intel_uncore_write_fw(gt->uncore, MTL_MCR_SELECTOR, GEN11_MCR_MULTICAST);
intel_uncore_write(gt->uncore, mcr_reg_cast(reg), value);
+
+ intel_gt_mcr_unlock(gt);
}
/**
@@ -400,9 +449,13 @@ void intel_gt_mcr_multicast_write(struct intel_gt *gt,
* function assumes the caller is already holding any necessary forcewake
* domains; use intel_gt_mcr_multicast_write() in cases where forcewake should
* be obtained automatically.
+ *
+ * Context: The caller must hold gt->mcr_lock.
*/
void intel_gt_mcr_multicast_write_fw(struct intel_gt *gt, i915_mcr_reg_t reg, u32 value)
{
+ lockdep_assert_held(>->mcr_lock);
+
/*
* Ensure we have multicast behavior, just in case some non-i915 agent
* left the hardware in unicast mode.
@@ -429,6 +482,8 @@ void intel_gt_mcr_multicast_write_fw(struct intel_gt *gt, i915_mcr_reg_t reg, u3
* domains; use intel_gt_mcr_multicast_rmw() in cases where forcewake should
* be obtained automatically.
*
+ * Context: Calls functions that take and release gt->mcr_lock
+ *
* Returns the old (unmodified) value read.
*/
u32 intel_gt_mcr_multicast_rmw(struct intel_gt *gt, i915_mcr_reg_t reg,
@@ -580,6 +635,8 @@ void intel_gt_mcr_get_nonterminated_steering(struct intel_gt *gt,
* domains; use intel_gt_mcr_read_any() in cases where forcewake should be
* obtained automatically.
*
+ * Context: The caller must hold gt->mcr_lock.
+ *
* Returns the value from a non-terminated instance of @reg.
*/
u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_mcr_reg_t reg)
@@ -587,6 +644,8 @@ u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_mcr_reg_t reg)
int type;
u8 group, instance;
+ lockdep_assert_held(>->mcr_lock);
+
for (type = 0; type < NUM_STEERING_TYPES; type++) {
if (reg_needs_read_steering(gt, reg, type)) {
get_nonterminated_steering(gt, type, &group, &instance);
@@ -607,6 +666,8 @@ u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_mcr_reg_t reg)
* Reads a GT MCR register. The read will be steered to a non-terminated
* instance (i.e., one that isn't fused off or powered down by power gating).
*
+ * Context: Calls a function that takes and releases gt->mcr_lock.
+ *
* Returns the value from a non-terminated instance of @reg.
*/
u32 intel_gt_mcr_read_any(struct intel_gt *gt, i915_mcr_reg_t reg)
@@ -730,6 +791,7 @@ void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss,
* Note that this routine assumes the caller holds forcewake asserted, it is
* not suitable for very long waits.
*
+ * Context: Calls a function that takes and releases gt->mcr_lock
* Return: 0 if the register matches the desired condition, or -ETIMEDOUT.
*/
int intel_gt_mcr_wait_for_reg(struct intel_gt *gt,
@@ -741,7 +803,7 @@ int intel_gt_mcr_wait_for_reg(struct intel_gt *gt,
{
int ret;
- lockdep_assert_not_held(>->uncore->lock);
+ lockdep_assert_not_held(>->mcr_lock);
#define done ((intel_gt_mcr_read_any(gt, reg) & mask) == value)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h
index ae93b20e1c17..bdcc07233778 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h
@@ -9,6 +9,8 @@
#include "intel_gt_types.h"
void intel_gt_mcr_init(struct intel_gt *gt);
+void intel_gt_mcr_lock(struct intel_gt *gt);
+void intel_gt_mcr_unlock(struct intel_gt *gt);
u32 intel_gt_mcr_read(struct intel_gt *gt,
i915_mcr_reg_t reg,
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h
index c1d9cd255e06..76c34c4af867 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h
@@ -233,6 +233,14 @@ struct intel_gt {
u8 instanceid;
} default_steering;
+ /**
+ * @mcr_lock: Protects the MCR steering register
+ *
+ * Protects the MCR steering register (e.g., GEN8_MCR_SELECTOR).
+ * Should be taken before uncore->lock in cases where both are desired.
+ */
+ spinlock_t mcr_lock;
+
/*
* Base of per-tile GTTMMADR where we can derive the MMIO and the GGTT.
*/
diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c
index 49fdd509527a..6a68463e376d 100644
--- a/drivers/gpu/drm/i915/gt/intel_mocs.c
+++ b/drivers/gpu/drm/i915/gt/intel_mocs.c
@@ -616,11 +616,13 @@ static void init_l3cc_table(struct intel_gt *gt,
unsigned int i;
u32 l3cc;
+ intel_gt_mcr_lock(gt);
for_each_l3cc(l3cc, table, i)
if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
intel_gt_mcr_multicast_write_fw(gt, XEHP_LNCFCMOCS(i), l3cc);
else
intel_uncore_write_fw(gt->uncore, GEN9_LNCFCMOCS(i), l3cc);
+ intel_gt_mcr_unlock(gt);
}
void intel_mocs_init_engine(struct intel_engine_cs *engine)
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 2afb4f80a954..69285cb9e2d3 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -1752,6 +1752,7 @@ static void wa_list_apply(const struct i915_wa_list *wal)
fw = wal_get_fw_for_rmw(uncore, wal);
+ intel_gt_mcr_lock(gt);
spin_lock_irqsave(&uncore->lock, flags);
intel_uncore_forcewake_get__locked(uncore, fw);
@@ -1782,6 +1783,7 @@ static void wa_list_apply(const struct i915_wa_list *wal)
intel_uncore_forcewake_put__locked(uncore, fw);
spin_unlock_irqrestore(&uncore->lock, flags);
+ intel_gt_mcr_unlock(gt);
}
void intel_gt_apply_workarounds(struct intel_gt *gt)
@@ -1802,6 +1804,7 @@ static bool wa_list_verify(struct intel_gt *gt,
fw = wal_get_fw_for_rmw(uncore, wal);
+ intel_gt_mcr_lock(gt);
spin_lock_irqsave(&uncore->lock, flags);
intel_uncore_forcewake_get__locked(uncore, fw);
@@ -1813,6 +1816,7 @@ static bool wa_list_verify(struct intel_gt *gt,
intel_uncore_forcewake_put__locked(uncore, fw);
spin_unlock_irqrestore(&uncore->lock, flags);
+ intel_gt_mcr_unlock(gt);
return ok;
}
--
2.38.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [Intel-gfx] [PATCH 4/4] drm/i915/mtl: Add hardware-level lock for steering
2022-11-22 20:33 [Intel-gfx] [PATCH 0/4] i915: dedicated MCR locking and hardware semaphore Matt Roper
` (2 preceding siblings ...)
2022-11-22 20:34 ` [Intel-gfx] [PATCH 3/4] drm/i915/gt: Add dedicated MCR lock Matt Roper
@ 2022-11-22 20:34 ` Matt Roper
2022-11-22 22:24 ` [Intel-gfx] ✗ Fi.CI.SPARSE: warning for i915: dedicated MCR locking and hardware semaphore Patchwork
2022-11-22 22:46 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
5 siblings, 0 replies; 7+ messages in thread
From: Matt Roper @ 2022-11-22 20:34 UTC (permalink / raw)
To: intel-gfx; +Cc: dri-devel
Starting with MTL, the driver needs to not only protect the steering
control register from simultaneous software accesses, but also protect
against races with hardware/firmware agents. The hardware provides a
dedicated locking mechanism to support this via the STEER_SEMAPHORE
register. Reading the register acts as a 'trylock' operation; the read
will return 0x1 if the lock is acquired or 0x0 if something else is
already holding the lock; once acquired, writing 0x1 to the register
will release the lock.
We'll continue to grab the software lock as well, just so lockdep can
track our locking; assuming the hardware lock is behaving properly,
there should never be any contention on the software lock in this case.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
---
drivers/gpu/drm/i915/gt/intel_gt_mcr.c | 29 +++++++++++++++++++++----
drivers/gpu/drm/i915/gt/intel_gt_regs.h | 1 +
2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
index f9e722d91904..fe5f5e0affdf 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
@@ -345,10 +345,9 @@ static u32 rw_with_mcr_steering(struct intel_gt *gt,
* @gt: GT structure
*
* Performs locking to protect the steering for the duration of an MCR
- * operation. Depending on the platform, this may be a software lock
- * (gt->mcr_lock) or a hardware lock (i.e., a register that synchronizes
- * access not only for the driver, but also for external hardware and
- * firmware agents).
+ * operation. On MTL and beyond, a hardware lock will also be taken to
+ * serialize access not only for the driver, but also for external hardware and
+ * firmware agents.
*
* Context: Takes gt->mcr_lock. uncore->lock should *not* be held when this
* function is called, although it may be acquired after this
@@ -356,9 +355,28 @@ static u32 rw_with_mcr_steering(struct intel_gt *gt,
*/
void intel_gt_mcr_lock(struct intel_gt *gt)
{
+ int err = 0;
+
lockdep_assert_not_held(>->uncore->lock);
+ /*
+ * Starting with MTL, we need to coordinate not only with other
+ * driver threads, but also with hardware/firmware agents. A dedicated
+ * locking register is used.
+ */
+ if (GRAPHICS_VER(gt->i915) >= IP_VER(12, 70))
+ err = wait_for(intel_uncore_read_fw(gt->uncore,
+ STEER_SEMAPHORE) == 0x1, 1);
+
+ /*
+ * Even on platforms with a hardware lock, we'll continue to grab
+ * a software spinlock too for lockdep purposes. If the hardware lock
+ * was already acquired, there should never be contention on the
+ * software lock.
+ */
spin_lock(>->mcr_lock);
+
+ drm_WARN_ON_ONCE(>->i915->drm, err == -ETIMEDOUT);
}
/**
@@ -372,6 +390,9 @@ void intel_gt_mcr_lock(struct intel_gt *gt)
void intel_gt_mcr_unlock(struct intel_gt *gt)
{
spin_unlock(>->mcr_lock);
+
+ if (GRAPHICS_VER(gt->i915) >= IP_VER(12, 70))
+ intel_uncore_write_fw(gt->uncore, STEER_SEMAPHORE, 0x1);
}
/**
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
index 80a979e6f6be..412c0b399ebd 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
@@ -67,6 +67,7 @@
#define GMD_ID_MEDIA _MMIO(MTL_MEDIA_GSI_BASE + 0xd8c)
#define MCFG_MCR_SELECTOR _MMIO(0xfd0)
+#define STEER_SEMAPHORE _MMIO(0xfd0)
#define MTL_MCR_SELECTOR _MMIO(0xfd4)
#define SF_MCR_SELECTOR _MMIO(0xfd8)
#define GEN8_MCR_SELECTOR _MMIO(0xfdc)
--
2.38.1
^ permalink raw reply related [flat|nested] 7+ messages in thread