xref: /openbmc/linux/drivers/gpu/drm/i915/gt/selftest_ring.c (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
1*8ab3a381SChris Wilson // SPDX-License-Identifier: GPL-2.0
2*8ab3a381SChris Wilson /*
3*8ab3a381SChris Wilson  * Copyright © 2020 Intel Corporation
4*8ab3a381SChris Wilson  */
5*8ab3a381SChris Wilson 
mock_ring(unsigned long sz)6*8ab3a381SChris Wilson static struct intel_ring *mock_ring(unsigned long sz)
7*8ab3a381SChris Wilson {
8*8ab3a381SChris Wilson 	struct intel_ring *ring;
9*8ab3a381SChris Wilson 
10*8ab3a381SChris Wilson 	ring = kzalloc(sizeof(*ring) + sz, GFP_KERNEL);
11*8ab3a381SChris Wilson 	if (!ring)
12*8ab3a381SChris Wilson 		return NULL;
13*8ab3a381SChris Wilson 
14*8ab3a381SChris Wilson 	kref_init(&ring->ref);
15*8ab3a381SChris Wilson 	ring->size = sz;
16*8ab3a381SChris Wilson 	ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(sz);
17*8ab3a381SChris Wilson 	ring->effective_size = sz;
18*8ab3a381SChris Wilson 	ring->vaddr = (void *)(ring + 1);
19*8ab3a381SChris Wilson 	atomic_set(&ring->pin_count, 1);
20*8ab3a381SChris Wilson 
21*8ab3a381SChris Wilson 	intel_ring_update_space(ring);
22*8ab3a381SChris Wilson 
23*8ab3a381SChris Wilson 	return ring;
24*8ab3a381SChris Wilson }
25*8ab3a381SChris Wilson 
mock_ring_free(struct intel_ring * ring)26*8ab3a381SChris Wilson static void mock_ring_free(struct intel_ring *ring)
27*8ab3a381SChris Wilson {
28*8ab3a381SChris Wilson 	kfree(ring);
29*8ab3a381SChris Wilson }
30*8ab3a381SChris Wilson 
check_ring_direction(struct intel_ring * ring,u32 next,u32 prev,int expected)31*8ab3a381SChris Wilson static int check_ring_direction(struct intel_ring *ring,
32*8ab3a381SChris Wilson 				u32 next, u32 prev,
33*8ab3a381SChris Wilson 				int expected)
34*8ab3a381SChris Wilson {
35*8ab3a381SChris Wilson 	int result;
36*8ab3a381SChris Wilson 
37*8ab3a381SChris Wilson 	result = intel_ring_direction(ring, next, prev);
38*8ab3a381SChris Wilson 	if (result < 0)
39*8ab3a381SChris Wilson 		result = -1;
40*8ab3a381SChris Wilson 	else if (result > 0)
41*8ab3a381SChris Wilson 		result = 1;
42*8ab3a381SChris Wilson 
43*8ab3a381SChris Wilson 	if (result != expected) {
44*8ab3a381SChris Wilson 		pr_err("intel_ring_direction(%u, %u):%d != %d\n",
45*8ab3a381SChris Wilson 		       next, prev, result, expected);
46*8ab3a381SChris Wilson 		return -EINVAL;
47*8ab3a381SChris Wilson 	}
48*8ab3a381SChris Wilson 
49*8ab3a381SChris Wilson 	return 0;
50*8ab3a381SChris Wilson }
51*8ab3a381SChris Wilson 
check_ring_step(struct intel_ring * ring,u32 x,u32 step)52*8ab3a381SChris Wilson static int check_ring_step(struct intel_ring *ring, u32 x, u32 step)
53*8ab3a381SChris Wilson {
54*8ab3a381SChris Wilson 	u32 prev = x, next = intel_ring_wrap(ring, x + step);
55*8ab3a381SChris Wilson 	int err = 0;
56*8ab3a381SChris Wilson 
57*8ab3a381SChris Wilson 	err |= check_ring_direction(ring, next, next,  0);
58*8ab3a381SChris Wilson 	err |= check_ring_direction(ring, prev, prev,  0);
59*8ab3a381SChris Wilson 	err |= check_ring_direction(ring, next, prev,  1);
60*8ab3a381SChris Wilson 	err |= check_ring_direction(ring, prev, next, -1);
61*8ab3a381SChris Wilson 
62*8ab3a381SChris Wilson 	return err;
63*8ab3a381SChris Wilson }
64*8ab3a381SChris Wilson 
check_ring_offset(struct intel_ring * ring,u32 x,u32 step)65*8ab3a381SChris Wilson static int check_ring_offset(struct intel_ring *ring, u32 x, u32 step)
66*8ab3a381SChris Wilson {
67*8ab3a381SChris Wilson 	int err = 0;
68*8ab3a381SChris Wilson 
69*8ab3a381SChris Wilson 	err |= check_ring_step(ring, x, step);
70*8ab3a381SChris Wilson 	err |= check_ring_step(ring, intel_ring_wrap(ring, x + 1), step);
71*8ab3a381SChris Wilson 	err |= check_ring_step(ring, intel_ring_wrap(ring, x - 1), step);
72*8ab3a381SChris Wilson 
73*8ab3a381SChris Wilson 	return err;
74*8ab3a381SChris Wilson }
75*8ab3a381SChris Wilson 
igt_ring_direction(void * dummy)76*8ab3a381SChris Wilson static int igt_ring_direction(void *dummy)
77*8ab3a381SChris Wilson {
78*8ab3a381SChris Wilson 	struct intel_ring *ring;
79*8ab3a381SChris Wilson 	unsigned int half = 2048;
80*8ab3a381SChris Wilson 	int step, err = 0;
81*8ab3a381SChris Wilson 
82*8ab3a381SChris Wilson 	ring = mock_ring(2 * half);
83*8ab3a381SChris Wilson 	if (!ring)
84*8ab3a381SChris Wilson 		return -ENOMEM;
85*8ab3a381SChris Wilson 
86*8ab3a381SChris Wilson 	GEM_BUG_ON(ring->size != 2 * half);
87*8ab3a381SChris Wilson 
88*8ab3a381SChris Wilson 	/* Precision of wrap detection is limited to ring->size / 2 */
89*8ab3a381SChris Wilson 	for (step = 1; step < half; step <<= 1) {
90*8ab3a381SChris Wilson 		err |= check_ring_offset(ring, 0, step);
91*8ab3a381SChris Wilson 		err |= check_ring_offset(ring, half, step);
92*8ab3a381SChris Wilson 	}
93*8ab3a381SChris Wilson 	err |= check_ring_step(ring, 0, half - 64);
94*8ab3a381SChris Wilson 
95*8ab3a381SChris Wilson 	/* And check unwrapped handling for good measure */
96*8ab3a381SChris Wilson 	err |= check_ring_offset(ring, 0, 2 * half + 64);
97*8ab3a381SChris Wilson 	err |= check_ring_offset(ring, 3 * half, 1);
98*8ab3a381SChris Wilson 
99*8ab3a381SChris Wilson 	mock_ring_free(ring);
100*8ab3a381SChris Wilson 	return err;
101*8ab3a381SChris Wilson }
102*8ab3a381SChris Wilson 
intel_ring_mock_selftests(void)103*8ab3a381SChris Wilson int intel_ring_mock_selftests(void)
104*8ab3a381SChris Wilson {
105*8ab3a381SChris Wilson 	static const struct i915_subtest tests[] = {
106*8ab3a381SChris Wilson 		SUBTEST(igt_ring_direction),
107*8ab3a381SChris Wilson 	};
108*8ab3a381SChris Wilson 
109*8ab3a381SChris Wilson 	return i915_subtests(tests, NULL);
110*8ab3a381SChris Wilson }
111