Commit 810b7ee3 authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915/gt: Always report the sample time for busy-stats



Return the monotonic timestamp (ktime_get()) at the time of sampling the
busy-time. This is used in preference to taking ktime_get() separately
before or after the read seqlock as there can be some large variance in
reported timestamps. For selftests trying to ascertain that we are
reporting accurate to within a few microseconds, even a small delay
leads to the test failing.

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200617130916.15261-2-chris@chris-wilson.co.uk
parent 1b90e4a4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -334,7 +334,8 @@ void intel_engine_dump(struct intel_engine_cs *engine,
		       struct drm_printer *m,
		       const char *header, ...);

ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine);
ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine,
				   ktime_t *now);

struct i915_request *
intel_engine_find_active_request(struct intel_engine_cs *engine);
+7 −5
Original line number Diff line number Diff line
@@ -1595,7 +1595,8 @@ void intel_engine_dump(struct intel_engine_cs *engine,
	intel_engine_print_breadcrumbs(engine, m);
}

static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine)
static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine,
					    ktime_t *now)
{
	ktime_t total = engine->stats.total;

@@ -1603,9 +1604,9 @@ static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine)
	 * If the engine is executing something at the moment
	 * add it to the total.
	 */
	*now = ktime_get();
	if (atomic_read(&engine->stats.active))
		total = ktime_add(total,
				  ktime_sub(ktime_get(), engine->stats.start));
		total = ktime_add(total, ktime_sub(*now, engine->stats.start));

	return total;
}
@@ -1613,17 +1614,18 @@ static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine)
/**
 * intel_engine_get_busy_time() - Return current accumulated engine busyness
 * @engine: engine to report on
 * @now: monotonic timestamp of sampling
 *
 * Returns accumulated time @engine was busy since engine stats were enabled.
 */
ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine)
ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, ktime_t *now)
{
	unsigned int seq;
	ktime_t total;

	do {
		seq = read_seqbegin(&engine->stats.lock);
		total = __intel_engine_get_busy_time(engine);
		total = __intel_engine_get_busy_time(engine, now);
	} while (read_seqretry(&engine->stats.lock, seq));

	return total;
+4 −5
Original line number Diff line number Diff line
@@ -53,13 +53,13 @@ static void rps_timer(struct timer_list *t)
	struct intel_engine_cs *engine;
	enum intel_engine_id id;
	s64 max_busy[3] = {};
	ktime_t dt, last;
	ktime_t dt, timestamp, last;

	for_each_engine(engine, rps_to_gt(rps), id) {
		s64 busy;
		int i;

		dt = intel_engine_get_busy_time(engine);
		dt = intel_engine_get_busy_time(engine, &timestamp);
		last = engine->stats.rps;
		engine->stats.rps = dt;

@@ -70,15 +70,14 @@ static void rps_timer(struct timer_list *t)
		}
	}

	dt = ktime_get();
	last = rps->pm_timestamp;
	rps->pm_timestamp = dt;
	rps->pm_timestamp = timestamp;

	if (intel_rps_is_active(rps)) {
		s64 busy;
		int i;

		dt = ktime_sub(dt, last);
		dt = ktime_sub(timestamp, last);

		/*
		 * Our goal is to evaluate each engine independently, so we run
+8 −10
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@ static int live_engine_busy_stats(void *arg)
	GEM_BUG_ON(intel_gt_pm_is_awake(gt));
	for_each_engine(engine, gt, id) {
		struct i915_request *rq;
		ktime_t de;
		u64 dt;
		ktime_t de, dt;
		ktime_t t[2];

		if (!intel_engine_supports_stats(engine))
			continue;
@@ -47,12 +47,11 @@ static int live_engine_busy_stats(void *arg)

		ENGINE_TRACE(engine, "measuring idle time\n");
		preempt_disable();
		dt = ktime_to_ns(ktime_get());
		de = intel_engine_get_busy_time(engine);
		de = intel_engine_get_busy_time(engine, &t[0]);
		udelay(100);
		de = ktime_sub(intel_engine_get_busy_time(engine), de);
		dt = ktime_to_ns(ktime_get()) - dt;
		de = ktime_sub(intel_engine_get_busy_time(engine, &t[1]), de);
		preempt_enable();
		dt = ktime_sub(t[1], t[0]);
		if (de < 0 || de > 10) {
			pr_err("%s: reported %lldns [%d%%] busyness while sleeping [for %lldns]\n",
			       engine->name,
@@ -80,12 +79,11 @@ static int live_engine_busy_stats(void *arg)

		ENGINE_TRACE(engine, "measuring busy time\n");
		preempt_disable();
		dt = ktime_to_ns(ktime_get());
		de = intel_engine_get_busy_time(engine);
		de = intel_engine_get_busy_time(engine, &t[0]);
		udelay(100);
		de = ktime_sub(intel_engine_get_busy_time(engine), de);
		dt = ktime_to_ns(ktime_get()) - dt;
		de = ktime_sub(intel_engine_get_busy_time(engine, &t[1]), de);
		preempt_enable();
		dt = ktime_sub(t[1], t[0]);
		if (100 * de < 95 * dt || 95 * de > 100 * dt) {
			pr_err("%s: reported %lldns [%d%%] busyness while spinning [for %lldns]\n",
			       engine->name,
+4 −1
Original line number Diff line number Diff line
@@ -565,7 +565,10 @@ static u64 __i915_pmu_event_read(struct perf_event *event)
			/* Do nothing */
		} else if (sample == I915_SAMPLE_BUSY &&
			   intel_engine_supports_stats(engine)) {
			val = ktime_to_ns(intel_engine_get_busy_time(engine));
			ktime_t unused;

			val = ktime_to_ns(intel_engine_get_busy_time(engine,
								     &unused));
		} else {
			val = engine->pmu.sample[sample].cur;
		}
Loading