Skip to content

Commit 41f425a

Browse files
mattroperodrigovivi
authored andcommitted
drm/i915/gt: Manage uncore->lock while waiting on MCR register
The GT MCR code currently relies on uncore->lock to avoid race conditions on the steering control register during MCR operations. The *_fw() versions of MCR operations expect the caller to already hold uncore->lock, while the non-fw variants manage the lock internally. However the sole callsite of intel_gt_mcr_wait_for_reg_fw() does not currently obtain the forcewake lock, allowing a potential race condition (and triggering an assertion on lockdep builds). Furthermore, since 'wait for register value' requests may not return immediately, it is undesirable to hold a fundamental lock like uncore->lock for the entire wait and block all other MMIO for the duration; rather the lock is only needed around the MCR read operations and can be released during the delays. Convert intel_gt_mcr_wait_for_reg_fw() to a non-fw variant that will manage uncore->lock internally. This does have the side effect of causing an unnecessary lookup in the forcewake table on each read operation, but since the caller is still holding the relevant forcewake domain, this will ultimately just incremenent the reference count and won't actually cause any additional MMIO traffic. In the future we plan to switch to a dedicated MCR lock to protect the steering critical section rather than using the overloaded and high-traffic uncore->lock; on MTL and beyond the new lock can be implemented on top of the hardware-provided synchonization mechanism for steering. Fixes: 3068bec ("drm/i915/gt: Add intel_gt_mcr_wait_for_reg_fw()") Cc: Lucas De Marchi <[email protected]> Signed-off-by: Matt Roper <[email protected]> Reviewed-by: Lucas De Marchi <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit 192bb40) Signed-off-by: Rodrigo Vivi <[email protected]>
1 parent 3d335a5 commit 41f425a

File tree

3 files changed

+19
-17
lines changed

3 files changed

+19
-17
lines changed

drivers/gpu/drm/i915/gt/intel_gt.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,9 +1035,9 @@ get_reg_and_bit(const struct intel_engine_cs *engine, const bool gen8,
10351035
static int wait_for_invalidate(struct intel_gt *gt, struct reg_and_bit rb)
10361036
{
10371037
if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
1038-
return intel_gt_mcr_wait_for_reg_fw(gt, rb.mcr_reg, rb.bit, 0,
1039-
TLB_INVAL_TIMEOUT_US,
1040-
TLB_INVAL_TIMEOUT_MS);
1038+
return intel_gt_mcr_wait_for_reg(gt, rb.mcr_reg, rb.bit, 0,
1039+
TLB_INVAL_TIMEOUT_US,
1040+
TLB_INVAL_TIMEOUT_MS);
10411041
else
10421042
return __intel_wait_for_register_fw(gt->uncore, rb.reg, rb.bit, 0,
10431043
TLB_INVAL_TIMEOUT_US,

drivers/gpu/drm/i915/gt/intel_gt_mcr.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -730,17 +730,19 @@ void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss,
730730
*
731731
* Return: 0 if the register matches the desired condition, or -ETIMEDOUT.
732732
*/
733-
int intel_gt_mcr_wait_for_reg_fw(struct intel_gt *gt,
734-
i915_mcr_reg_t reg,
735-
u32 mask,
736-
u32 value,
737-
unsigned int fast_timeout_us,
738-
unsigned int slow_timeout_ms)
733+
int intel_gt_mcr_wait_for_reg(struct intel_gt *gt,
734+
i915_mcr_reg_t reg,
735+
u32 mask,
736+
u32 value,
737+
unsigned int fast_timeout_us,
738+
unsigned int slow_timeout_ms)
739739
{
740-
u32 reg_value = 0;
741-
#define done (((reg_value = intel_gt_mcr_read_any_fw(gt, reg)) & mask) == value)
742740
int ret;
743741

742+
lockdep_assert_not_held(&gt->uncore->lock);
743+
744+
#define done ((intel_gt_mcr_read_any(gt, reg) & mask) == value)
745+
744746
/* Catch any overuse of this function */
745747
might_sleep_if(slow_timeout_ms);
746748
GEM_BUG_ON(fast_timeout_us > 20000);

drivers/gpu/drm/i915/gt/intel_gt_mcr.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt,
3737
void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss,
3838
unsigned int *group, unsigned int *instance);
3939

40-
int intel_gt_mcr_wait_for_reg_fw(struct intel_gt *gt,
41-
i915_mcr_reg_t reg,
42-
u32 mask,
43-
u32 value,
44-
unsigned int fast_timeout_us,
45-
unsigned int slow_timeout_ms);
40+
int intel_gt_mcr_wait_for_reg(struct intel_gt *gt,
41+
i915_mcr_reg_t reg,
42+
u32 mask,
43+
u32 value,
44+
unsigned int fast_timeout_us,
45+
unsigned int slow_timeout_ms);
4646

4747
/*
4848
* Helper for for_each_ss_steering loop. On pre-Xe_HP platforms, subslice

0 commit comments

Comments
 (0)