Commit f79520bb authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915/selftests: Synchronize checking active status with retirement



If retirement is running on another thread, we may inspect the status of
the i915_active before its retirement callback is complete. As we expect
it to be running synchronously, we can wait for any callback to complete
by acquiring the i915_active.mutex.

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Acked-by: default avatarAndi Shyti <andi.shyti@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191022112111.9317-1-chris@chris-wilson.co.uk
parent 905da43c
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -49,12 +49,20 @@ static struct pulse *pulse_create(void)
	return p;
}

static void pulse_unlock_wait(struct pulse *p)
{
	mutex_lock(&p->active.mutex);
	mutex_unlock(&p->active.mutex);
}

static int __live_idle_pulse(struct intel_engine_cs *engine,
			     int (*fn)(struct intel_engine_cs *cs))
{
	struct pulse *p;
	int err;

	GEM_BUG_ON(!intel_engine_pm_is_awake(engine));

	p = pulse_create();
	if (!p)
		return -ENOMEM;
@@ -73,16 +81,21 @@ static int __live_idle_pulse(struct intel_engine_cs *engine,
	i915_active_release(&p->active);

	GEM_BUG_ON(i915_active_is_idle(&p->active));
	GEM_BUG_ON(llist_empty(&engine->barrier_tasks));

	err = fn(engine);
	if (err)
		goto out;

	GEM_BUG_ON(!llist_empty(&engine->barrier_tasks));

	if (intel_gt_retire_requests_timeout(engine->gt, HZ / 5)) {
		err = -ETIME;
		goto out;
	}

	pulse_unlock_wait(p); /* synchronize with the retirement callback */

	if (!i915_active_is_idle(&p->active)) {
		pr_err("%s: heartbeat pulse did not flush idle tasks\n",
		       engine->name);