Skip to content

Commit b3f7493

Browse files
unerligetursulin
authored andcommitted
drm/i915/pmu: Use PM timestamp instead of RING TIMESTAMP for reference
All timestamps returned by GuC for GuC PMU busyness are captured from GUC PM TIMESTAMP. Since this timestamp does not tick when GuC goes idle, kmd uses RING_TIMESTAMP to measure busyness of an engine with an active context. In further stress testing, the MMIO read of the RING_TIMESTAMP is seen to cause a rare hang. Resolve the issue by using gt specific timestamp from PM which is in sync with the GuC PM timestamp. Fixes: 77cdd05 ("drm/i915/pmu: Connect engine busyness stats from GuC to pmu") Signed-off-by: Umesh Nerlige Ramappa <[email protected]> Reviewed-by: Alan Previn <[email protected]> Signed-off-by: John Harrison <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit 721fd84) Signed-off-by: Tvrtko Ursulin <[email protected]>
1 parent 90a3d22 commit b3f7493

File tree

3 files changed

+50
-14
lines changed

3 files changed

+50
-14
lines changed

drivers/gpu/drm/i915/gt/uc/intel_guc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ struct intel_guc {
206206
* context usage for overflows.
207207
*/
208208
struct delayed_work work;
209+
210+
/**
211+
* @shift: Right shift value for the gpm timestamp
212+
*/
213+
u32 shift;
209214
} timestamp;
210215

211216
#ifdef CONFIG_DRM_I915_SELFTEST

drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,23 +1149,51 @@ static void guc_update_engine_gt_clks(struct intel_engine_cs *engine)
11491149
}
11501150
}
11511151

1152-
static void guc_update_pm_timestamp(struct intel_guc *guc,
1153-
struct intel_engine_cs *engine,
1154-
ktime_t *now)
1152+
static u32 gpm_timestamp_shift(struct intel_gt *gt)
11551153
{
1156-
u32 gt_stamp_now, gt_stamp_hi;
1154+
intel_wakeref_t wakeref;
1155+
u32 reg, shift;
1156+
1157+
with_intel_runtime_pm(gt->uncore->rpm, wakeref)
1158+
reg = intel_uncore_read(gt->uncore, RPM_CONFIG0);
1159+
1160+
shift = (reg & GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >>
1161+
GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT;
1162+
1163+
return 3 - shift;
1164+
}
1165+
1166+
static u64 gpm_timestamp(struct intel_gt *gt)
1167+
{
1168+
u32 lo, hi, old_hi, loop = 0;
1169+
1170+
hi = intel_uncore_read(gt->uncore, MISC_STATUS1);
1171+
do {
1172+
lo = intel_uncore_read(gt->uncore, MISC_STATUS0);
1173+
old_hi = hi;
1174+
hi = intel_uncore_read(gt->uncore, MISC_STATUS1);
1175+
} while (old_hi != hi && loop++ < 2);
1176+
1177+
return ((u64)hi << 32) | lo;
1178+
}
1179+
1180+
static void guc_update_pm_timestamp(struct intel_guc *guc, ktime_t *now)
1181+
{
1182+
struct intel_gt *gt = guc_to_gt(guc);
1183+
u32 gt_stamp_lo, gt_stamp_hi;
1184+
u64 gpm_ts;
11571185

11581186
lockdep_assert_held(&guc->timestamp.lock);
11591187

11601188
gt_stamp_hi = upper_32_bits(guc->timestamp.gt_stamp);
1161-
gt_stamp_now = intel_uncore_read(engine->uncore,
1162-
RING_TIMESTAMP(engine->mmio_base));
1189+
gpm_ts = gpm_timestamp(gt) >> guc->timestamp.shift;
1190+
gt_stamp_lo = lower_32_bits(gpm_ts);
11631191
*now = ktime_get();
11641192

1165-
if (gt_stamp_now < lower_32_bits(guc->timestamp.gt_stamp))
1193+
if (gt_stamp_lo < lower_32_bits(guc->timestamp.gt_stamp))
11661194
gt_stamp_hi++;
11671195

1168-
guc->timestamp.gt_stamp = ((u64)gt_stamp_hi << 32) | gt_stamp_now;
1196+
guc->timestamp.gt_stamp = ((u64)gt_stamp_hi << 32) | gt_stamp_lo;
11691197
}
11701198

11711199
/*
@@ -1209,7 +1237,7 @@ static ktime_t guc_engine_busyness(struct intel_engine_cs *engine, ktime_t *now)
12091237
stats_saved = *stats;
12101238
gt_stamp_saved = guc->timestamp.gt_stamp;
12111239
guc_update_engine_gt_clks(engine);
1212-
guc_update_pm_timestamp(guc, engine, now);
1240+
guc_update_pm_timestamp(guc, now);
12131241
intel_gt_pm_put_async(gt);
12141242
if (i915_reset_count(gpu_error) != reset_count) {
12151243
*stats = stats_saved;
@@ -1241,8 +1269,8 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc)
12411269

12421270
spin_lock_irqsave(&guc->timestamp.lock, flags);
12431271

1272+
guc_update_pm_timestamp(guc, &unused);
12441273
for_each_engine(engine, gt, id) {
1245-
guc_update_pm_timestamp(guc, engine, &unused);
12461274
guc_update_engine_gt_clks(engine);
12471275
engine->stats.guc.prev_total = 0;
12481276
}
@@ -1259,10 +1287,11 @@ static void __update_guc_busyness_stats(struct intel_guc *guc)
12591287
ktime_t unused;
12601288

12611289
spin_lock_irqsave(&guc->timestamp.lock, flags);
1262-
for_each_engine(engine, gt, id) {
1263-
guc_update_pm_timestamp(guc, engine, &unused);
1290+
1291+
guc_update_pm_timestamp(guc, &unused);
1292+
for_each_engine(engine, gt, id)
12641293
guc_update_engine_gt_clks(engine);
1265-
}
1294+
12661295
spin_unlock_irqrestore(&guc->timestamp.lock, flags);
12671296
}
12681297

@@ -1783,6 +1812,7 @@ int intel_guc_submission_init(struct intel_guc *guc)
17831812
spin_lock_init(&guc->timestamp.lock);
17841813
INIT_DELAYED_WORK(&guc->timestamp.work, guc_timestamp_ping);
17851814
guc->timestamp.ping_delay = (POLL_TIME_CLKS / gt->clock_frequency + 1) * HZ;
1815+
guc->timestamp.shift = gpm_timestamp_shift(gt);
17861816

17871817
return 0;
17881818
}

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2684,7 +2684,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
26842684
#define RING_WAIT (1 << 11) /* gen3+, PRBx_CTL */
26852685
#define RING_WAIT_SEMAPHORE (1 << 10) /* gen6+ */
26862686

2687-
#define GUCPMTIMESTAMP _MMIO(0xC3E8)
2687+
#define MISC_STATUS0 _MMIO(0xA500)
2688+
#define MISC_STATUS1 _MMIO(0xA504)
26882689

26892690
/* There are 16 64-bit CS General Purpose Registers per-engine on Gen8+ */
26902691
#define GEN8_RING_CS_GPR(base, n) _MMIO((base) + 0x600 + (n) * 8)

0 commit comments

Comments
 (0)