Skip to content

Commit

Permalink
drm/i915/selftests: Repeat the rps clock frequency measurement
Browse files Browse the repository at this point in the history
Repeat the measurement of the clock frequency a few times and use the
median to try and reduce the systematic measurement error.

Signed-off-by: Chris Wilson <[email protected]>
Reviewed-by: Mika Kuoppala <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
  • Loading branch information
ickle committed May 4, 2020
1 parent 0065e5f commit 8757797
Showing 1 changed file with 40 additions and 14 deletions.
54 changes: 40 additions & 14 deletions drivers/gpu/drm/i915/gt/selftest_rps.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ static int cmp_u64(const void *A, const void *B)
return 0;
}

static int cmp_u32(const void *A, const void *B)
{
const u32 *a = A, *b = B;

if (a < b)
return -1;
else if (a > b)
return 1;
else
return 0;
}

static struct i915_vma *
create_spin_counter(struct intel_engine_cs *engine,
struct i915_address_space *vm,
Expand Down Expand Up @@ -236,8 +248,8 @@ int live_rps_clock_interval(void *arg)
for_each_engine(engine, gt, id) {
unsigned long saved_heartbeat;
struct i915_request *rq;
ktime_t dt;
u32 cycles;
u64 dt;

if (!intel_engine_can_store_dword(engine))
continue;
Expand Down Expand Up @@ -286,15 +298,29 @@ int live_rps_clock_interval(void *arg)
engine->name);
err = -ENODEV;
} else {
preempt_disable();
dt = ktime_get();
cycles = -intel_uncore_read_fw(gt->uncore,
GEN6_RP_CUR_UP_EI);
udelay(1000);
dt = ktime_sub(ktime_get(), dt);
cycles += intel_uncore_read_fw(gt->uncore,
GEN6_RP_CUR_UP_EI);
preempt_enable();
ktime_t dt_[5];
u32 cycles_[5];
int i;

for (i = 0; i < 5; i++) {
preempt_disable();

dt_[i] = ktime_get();
cycles_[i] = -intel_uncore_read_fw(gt->uncore, GEN6_RP_CUR_UP_EI);

udelay(1000);

dt_[i] = ktime_sub(ktime_get(), dt_[i]);
cycles_[i] += intel_uncore_read_fw(gt->uncore, GEN6_RP_CUR_UP_EI);

preempt_enable();
}

/* Use the median of both cycle/dt; close enough */
sort(cycles_, 5, sizeof(*cycles_), cmp_u32, NULL);
cycles = (cycles_[1] + 2 * cycles_[2] + cycles_[3]) / 4;
sort(dt_, 5, sizeof(*dt_), cmp_u64, NULL);
dt = div_u64(dt_[1] + 2 * dt_[2] + dt_[3], 4);
}

intel_uncore_write_fw(gt->uncore, GEN6_RP_CONTROL, 0);
Expand All @@ -306,14 +332,14 @@ int live_rps_clock_interval(void *arg)
if (err == 0) {
u64 time = intel_gt_pm_interval_to_ns(gt, cycles);
u32 expected =
intel_gt_ns_to_pm_interval(gt, ktime_to_ns(dt));
intel_gt_ns_to_pm_interval(gt, dt);

pr_info("%s: rps counted %d C0 cycles [%lldns] in %lldns [%d cycles], using GT clock frequency of %uKHz\n",
engine->name, cycles, time, ktime_to_ns(dt), expected,
engine->name, cycles, time, dt, expected,
gt->clock_frequency / 1000);

if (10 * time < 8 * ktime_to_ns(dt) ||
8 * time > 10 * ktime_to_ns(dt)) {
if (10 * time < 8 * dt ||
8 * time > 10 * dt) {
pr_err("%s: rps clock time does not match walltime!\n",
engine->name);
err = -EINVAL;
Expand Down

0 comments on commit 8757797

Please sign in to comment.