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