]> git.ipfire.org Git - thirdparty/kernel/stable.git/blob - drivers/gpu/drm/i915/selftests/igt_spinner.c
drm/amd/display: Check hpd_gpio for NULL before accessing it
[thirdparty/kernel/stable.git] / drivers / gpu / drm / i915 / selftests / igt_spinner.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright © 2018 Intel Corporation
5 */
6
7 #include "igt_spinner.h"
8
9 int igt_spinner_init(struct igt_spinner *spin, struct drm_i915_private *i915)
10 {
11 unsigned int mode;
12 void *vaddr;
13 int err;
14
15 GEM_BUG_ON(INTEL_GEN(i915) < 8);
16
17 memset(spin, 0, sizeof(*spin));
18 spin->i915 = i915;
19
20 spin->hws = i915_gem_object_create_internal(i915, PAGE_SIZE);
21 if (IS_ERR(spin->hws)) {
22 err = PTR_ERR(spin->hws);
23 goto err;
24 }
25
26 spin->obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
27 if (IS_ERR(spin->obj)) {
28 err = PTR_ERR(spin->obj);
29 goto err_hws;
30 }
31
32 i915_gem_object_set_cache_level(spin->hws, I915_CACHE_LLC);
33 vaddr = i915_gem_object_pin_map(spin->hws, I915_MAP_WB);
34 if (IS_ERR(vaddr)) {
35 err = PTR_ERR(vaddr);
36 goto err_obj;
37 }
38 spin->seqno = memset(vaddr, 0xff, PAGE_SIZE);
39
40 mode = i915_coherent_map_type(i915);
41 vaddr = i915_gem_object_pin_map(spin->obj, mode);
42 if (IS_ERR(vaddr)) {
43 err = PTR_ERR(vaddr);
44 goto err_unpin_hws;
45 }
46 spin->batch = vaddr;
47
48 return 0;
49
50 err_unpin_hws:
51 i915_gem_object_unpin_map(spin->hws);
52 err_obj:
53 i915_gem_object_put(spin->obj);
54 err_hws:
55 i915_gem_object_put(spin->hws);
56 err:
57 return err;
58 }
59
60 static unsigned int seqno_offset(u64 fence)
61 {
62 return offset_in_page(sizeof(u32) * fence);
63 }
64
65 static u64 hws_address(const struct i915_vma *hws,
66 const struct i915_request *rq)
67 {
68 return hws->node.start + seqno_offset(rq->fence.context);
69 }
70
71 static int emit_recurse_batch(struct igt_spinner *spin,
72 struct i915_request *rq,
73 u32 arbitration_command)
74 {
75 struct i915_address_space *vm = &rq->gem_context->ppgtt->vm;
76 struct i915_vma *hws, *vma;
77 u32 *batch;
78 int err;
79
80 vma = i915_vma_instance(spin->obj, vm, NULL);
81 if (IS_ERR(vma))
82 return PTR_ERR(vma);
83
84 hws = i915_vma_instance(spin->hws, vm, NULL);
85 if (IS_ERR(hws))
86 return PTR_ERR(hws);
87
88 err = i915_vma_pin(vma, 0, 0, PIN_USER);
89 if (err)
90 return err;
91
92 err = i915_vma_pin(hws, 0, 0, PIN_USER);
93 if (err)
94 goto unpin_vma;
95
96 err = i915_vma_move_to_active(vma, rq, 0);
97 if (err)
98 goto unpin_hws;
99
100 if (!i915_gem_object_has_active_reference(vma->obj)) {
101 i915_gem_object_get(vma->obj);
102 i915_gem_object_set_active_reference(vma->obj);
103 }
104
105 err = i915_vma_move_to_active(hws, rq, 0);
106 if (err)
107 goto unpin_hws;
108
109 if (!i915_gem_object_has_active_reference(hws->obj)) {
110 i915_gem_object_get(hws->obj);
111 i915_gem_object_set_active_reference(hws->obj);
112 }
113
114 batch = spin->batch;
115
116 *batch++ = MI_STORE_DWORD_IMM_GEN4;
117 *batch++ = lower_32_bits(hws_address(hws, rq));
118 *batch++ = upper_32_bits(hws_address(hws, rq));
119 *batch++ = rq->fence.seqno;
120
121 *batch++ = arbitration_command;
122
123 *batch++ = MI_BATCH_BUFFER_START | 1 << 8 | 1;
124 *batch++ = lower_32_bits(vma->node.start);
125 *batch++ = upper_32_bits(vma->node.start);
126 *batch++ = MI_BATCH_BUFFER_END; /* not reached */
127
128 i915_gem_chipset_flush(spin->i915);
129
130 err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0);
131
132 unpin_hws:
133 i915_vma_unpin(hws);
134 unpin_vma:
135 i915_vma_unpin(vma);
136 return err;
137 }
138
139 struct i915_request *
140 igt_spinner_create_request(struct igt_spinner *spin,
141 struct i915_gem_context *ctx,
142 struct intel_engine_cs *engine,
143 u32 arbitration_command)
144 {
145 struct i915_request *rq;
146 int err;
147
148 rq = i915_request_alloc(engine, ctx);
149 if (IS_ERR(rq))
150 return rq;
151
152 err = emit_recurse_batch(spin, rq, arbitration_command);
153 if (err) {
154 i915_request_add(rq);
155 return ERR_PTR(err);
156 }
157
158 return rq;
159 }
160
161 static u32
162 hws_seqno(const struct igt_spinner *spin, const struct i915_request *rq)
163 {
164 u32 *seqno = spin->seqno + seqno_offset(rq->fence.context);
165
166 return READ_ONCE(*seqno);
167 }
168
169 void igt_spinner_end(struct igt_spinner *spin)
170 {
171 *spin->batch = MI_BATCH_BUFFER_END;
172 i915_gem_chipset_flush(spin->i915);
173 }
174
175 void igt_spinner_fini(struct igt_spinner *spin)
176 {
177 igt_spinner_end(spin);
178
179 i915_gem_object_unpin_map(spin->obj);
180 i915_gem_object_put(spin->obj);
181
182 i915_gem_object_unpin_map(spin->hws);
183 i915_gem_object_put(spin->hws);
184 }
185
186 bool igt_wait_for_spinner(struct igt_spinner *spin, struct i915_request *rq)
187 {
188 if (!wait_event_timeout(rq->execute,
189 READ_ONCE(rq->global_seqno),
190 msecs_to_jiffies(10)))
191 return false;
192
193 return !(wait_for_us(i915_seqno_passed(hws_seqno(spin, rq),
194 rq->fence.seqno),
195 10) &&
196 wait_for(i915_seqno_passed(hws_seqno(spin, rq),
197 rq->fence.seqno),
198 1000));
199 }