[PATCH 04/45] drm/i915: Add unit tests for the breadcrumb rbtree, completion

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Wed Dec 7 07:33:28 UTC 2016


On 06/12/2016 00:12, Chris Wilson wrote:
> Second retroactive test, make sure that the waiters are removed from the
> global wait-tree when their seqno completes.
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/intel_breadcrumbs.c | 110 +++++++++++++++++++++++++++++++
>  1 file changed, 110 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
> index 2c02939fd5b6..e2dc22139716 100644
> --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
> +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
> @@ -698,6 +698,12 @@ static struct intel_engine_cs *mock_engine(const char *name)
>  	return engine;
>  }
>
> +static void mock_seqno_advance(struct intel_engine_cs *engine, u32 seqno)
> +{
> +	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
> +	intel_engine_wakeup(engine);
> +}
> +
>  static int *get_random_order(int count)
>  {
>  	int *order;
> @@ -759,6 +765,27 @@ static int check_rbtree(struct intel_engine_cs *engine,
>  	return 0;
>  }
>
> +static int check_completion(struct intel_engine_cs *engine,
> +			    const unsigned long *bitmap,
> +			    const struct intel_wait *waiters,
> +			    const int count)
> +{
> +	int n;
> +
> +	for (n = 0; n < count; n++) {
> +		if (intel_wait_complete(&waiters[n]) != !!test_bit(n, bitmap))
> +			continue;
> +
> +		pr_err("waiter[%d, seqno=%d] is %s, but expected %s\n",
> +		       n, waiters[n].seqno,
> +		       intel_wait_complete(&waiters[n]) ? "complete" : "active",
> +		       test_bit(n, bitmap) ? "active" : "complete");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
>  static int check_rbtree_empty(struct intel_engine_cs *engine)
>  {
>  	struct intel_breadcrumbs *b = &engine->breadcrumbs;
> @@ -850,10 +877,93 @@ static int igt_random_insert_remove(void *ignore)
>  	return err;
>  }
>
> +static int igt_insert_complete(void *ignore)
> +{
> +	struct intel_engine_cs *engine;
> +	struct intel_wait *waiters;
> +	const int count = 4096;
> +	unsigned long *bitmap;
> +	int err = -ENOMEM;
> +	int n, m;
> +
> +	engine = mock_engine("mock");
> +	if (!engine)
> +		goto out;
> +
> +	waiters = kmalloc_array(count, sizeof(*waiters), GFP_KERNEL);

The same uncertainty about the allocation size as the previous patch.

> +	if (!waiters)
> +		goto out_engines;
> +
> +	bitmap = kcalloc(DIV_ROUND_UP(count, BITS_PER_LONG), sizeof(*bitmap),
> +			 GFP_KERNEL);
> +	if (!bitmap)
> +		goto out_waiters;
> +
> +	for (n = 0; n < count; n++) {
> +		intel_wait_init(&waiters[n], n + 0x1000);
> +		intel_engine_add_wait(engine, &waiters[n]);
> +		__set_bit(n, bitmap);
> +	}
> +	err = check_rbtree(engine, bitmap, waiters, count);
> +	if (err)
> +		goto err;
> +
> +	for (n = 0; n < count; n = m) {
> +		int seqno = 2 * n;
> +
> +		GEM_BUG_ON(find_first_bit(bitmap, count) != n);
> +
> +		if (intel_wait_complete(&waiters[n])) {
> +			pr_err("waiter[%d, seqno=%d] completed too early\n",
> +			       n, waiters[n].seqno);
> +			err = -EINVAL;
> +			goto err;
> +		}
> +
> +		/* complete the following waiters */
> +		mock_seqno_advance(engine, seqno + 0x1000);
> +		for (m = n; m <= seqno; m++) {
> +			if (m == count)
> +				break;
> +
> +			GEM_BUG_ON(!test_bit(m, bitmap));
> +			__clear_bit(m, bitmap);
> +		}
> +
> +		intel_engine_remove_wait(engine, &waiters[n]);
> +		RB_CLEAR_NODE(&waiters[n].node);
> +
> +		err = check_rbtree(engine, bitmap, waiters, count);
> +		if (err) {
> +			pr_err("rbtree corrupt after seqno advance to %d\n",
> +			       seqno + 0x1000);
> +			goto err;
> +		}
> +
> +		err = check_completion(engine, bitmap, waiters, count);
> +		if (err) {
> +			pr_err("completions after seqno advance to %d failed\n",
> +			       seqno + 0x1000);
> +			goto err;
> +		}
> +	}
> +
> +	err = check_rbtree_empty(engine);
> +err:
> +	kfree(bitmap);
> +out_waiters:
> +	kfree(waiters);
> +out_engines:
> +	kfree(engine);
> +out:
> +	return err;
> +}
> +
>  int intel_breadcrumbs_selftest(void)
>  {
>  	static const struct i915_subtest tests[] = {
>  		SUBTEST(igt_random_insert_remove),
> +		SUBTEST(igt_insert_complete),
>  	};
>
>  	return i915_subtests(tests, NULL);
>

Looks OK. Task priority handling in chain wakeups would be interesting 
to test as well but mocking the required bits, hm... not sure if it 
would be possible or better say feasible.

Regards,

Tvrtko


More information about the Intel-gfx-trybot mailing list