Branch data Line data Source code
1 : : /*
2 : : * SPDX-License-Identifier: MIT
3 : : *
4 : : * Copyright © 2019 Intel Corporation
5 : : */
6 : :
7 : : #include "gem/i915_gem_object.h"
8 : : #include "i915_drv.h"
9 : : #include "i915_vma.h"
10 : : #include "intel_engine.h"
11 : : #include "intel_ring.h"
12 : : #include "intel_timeline.h"
13 : :
14 : 0 : unsigned int intel_ring_update_space(struct intel_ring *ring)
15 : : {
16 : 0 : unsigned int space;
17 : :
18 : 0 : space = __intel_ring_space(ring->head, ring->emit, ring->size);
19 : :
20 : 0 : ring->space = space;
21 [ # # ]: 0 : return space;
22 : : }
23 : :
24 : 0 : int intel_ring_pin(struct intel_ring *ring)
25 : : {
26 : 0 : struct i915_vma *vma = ring->vma;
27 : 0 : unsigned int flags;
28 : 0 : void *addr;
29 : 0 : int ret;
30 : :
31 [ # # ]: 0 : if (atomic_fetch_inc(&ring->pin_count))
32 : : return 0;
33 : :
34 : 0 : flags = PIN_GLOBAL;
35 : :
36 : : /* Ring wraparound at offset 0 sometimes hangs. No idea why. */
37 [ # # ]: 0 : flags |= PIN_OFFSET_BIAS | i915_ggtt_pin_bias(vma);
38 : :
39 [ # # ]: 0 : if (vma->obj->stolen)
40 : 0 : flags |= PIN_MAPPABLE;
41 : : else
42 : 0 : flags |= PIN_HIGH;
43 : :
44 : 0 : ret = i915_vma_pin(vma, 0, 0, flags);
45 [ # # ]: 0 : if (unlikely(ret))
46 : 0 : goto err_unpin;
47 : :
48 [ # # ]: 0 : if (i915_vma_is_map_and_fenceable(vma))
49 : 0 : addr = (void __force *)i915_vma_pin_iomap(vma);
50 : : else
51 : 0 : addr = i915_gem_object_pin_map(vma->obj,
52 : 0 : i915_coherent_map_type(vma->vm->i915));
53 [ # # ]: 0 : if (IS_ERR(addr)) {
54 : 0 : ret = PTR_ERR(addr);
55 : 0 : goto err_ring;
56 : : }
57 : :
58 : 0 : i915_vma_make_unshrinkable(vma);
59 : :
60 : : /* Discard any unused bytes beyond that submitted to hw. */
61 : 0 : intel_ring_reset(ring, ring->emit);
62 : :
63 : 0 : ring->vaddr = addr;
64 : 0 : return 0;
65 : :
66 : : err_ring:
67 : 0 : i915_vma_unpin(vma);
68 : 0 : err_unpin:
69 : 0 : atomic_dec(&ring->pin_count);
70 : 0 : return ret;
71 : : }
72 : :
73 : 0 : void intel_ring_reset(struct intel_ring *ring, u32 tail)
74 : : {
75 : 0 : tail = intel_ring_wrap(ring, tail);
76 : 0 : ring->tail = tail;
77 : 0 : ring->head = tail;
78 : 0 : ring->emit = tail;
79 : 0 : intel_ring_update_space(ring);
80 : 0 : }
81 : :
82 : 0 : void intel_ring_unpin(struct intel_ring *ring)
83 : : {
84 : 0 : struct i915_vma *vma = ring->vma;
85 : :
86 [ # # ]: 0 : if (!atomic_dec_and_test(&ring->pin_count))
87 : : return;
88 : :
89 : 0 : i915_vma_unset_ggtt_write(vma);
90 [ # # ]: 0 : if (i915_vma_is_map_and_fenceable(vma))
91 : 0 : i915_vma_unpin_iomap(vma);
92 : : else
93 : 0 : i915_gem_object_unpin_map(vma->obj);
94 : :
95 : 0 : i915_vma_make_purgeable(vma);
96 : 0 : i915_vma_unpin(vma);
97 : : }
98 : :
99 : 0 : static struct i915_vma *create_ring_vma(struct i915_ggtt *ggtt, int size)
100 : : {
101 : 0 : struct i915_address_space *vm = &ggtt->vm;
102 : 0 : struct drm_i915_private *i915 = vm->i915;
103 : 0 : struct drm_i915_gem_object *obj;
104 : 0 : struct i915_vma *vma;
105 : :
106 [ # # ]: 0 : obj = ERR_PTR(-ENODEV);
107 [ # # ]: 0 : if (i915_ggtt_has_aperture(ggtt))
108 : 0 : obj = i915_gem_object_create_stolen(i915, size);
109 [ # # ]: 0 : if (IS_ERR(obj))
110 : 0 : obj = i915_gem_object_create_internal(i915, size);
111 [ # # ]: 0 : if (IS_ERR(obj))
112 : : return ERR_CAST(obj);
113 : :
114 : : /*
115 : : * Mark ring buffers as read-only from GPU side (so no stray overwrites)
116 : : * if supported by the platform's GGTT.
117 : : */
118 [ # # ]: 0 : if (vm->has_read_only)
119 : 0 : i915_gem_object_set_readonly(obj);
120 : :
121 : 0 : vma = i915_vma_instance(obj, vm, NULL);
122 [ # # ]: 0 : if (IS_ERR(vma))
123 : 0 : goto err;
124 : :
125 : : return vma;
126 : :
127 : : err:
128 : 0 : i915_gem_object_put(obj);
129 : 0 : return vma;
130 : : }
131 : :
132 : : struct intel_ring *
133 : 0 : intel_engine_create_ring(struct intel_engine_cs *engine, int size)
134 : : {
135 : 0 : struct drm_i915_private *i915 = engine->i915;
136 : 0 : struct intel_ring *ring;
137 : 0 : struct i915_vma *vma;
138 : :
139 : 0 : GEM_BUG_ON(!is_power_of_2(size));
140 : 0 : GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES);
141 : :
142 : 0 : ring = kzalloc(sizeof(*ring), GFP_KERNEL);
143 [ # # ]: 0 : if (!ring)
144 : : return ERR_PTR(-ENOMEM);
145 : :
146 : 0 : kref_init(&ring->ref);
147 : 0 : ring->size = size;
148 [ # # # # : 0 : ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(size);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
149 : :
150 : : /*
151 : : * Workaround an erratum on the i830 which causes a hang if
152 : : * the TAIL pointer points to within the last 2 cachelines
153 : : * of the buffer.
154 : : */
155 : 0 : ring->effective_size = size;
156 [ # # # # ]: 0 : if (IS_I830(i915) || IS_I845G(i915))
157 : 0 : ring->effective_size -= 2 * CACHELINE_BYTES;
158 : :
159 : 0 : intel_ring_update_space(ring);
160 : :
161 : 0 : vma = create_ring_vma(engine->gt->ggtt, size);
162 [ # # ]: 0 : if (IS_ERR(vma)) {
163 : 0 : kfree(ring);
164 : 0 : return ERR_CAST(vma);
165 : : }
166 : 0 : ring->vma = vma;
167 : :
168 : 0 : return ring;
169 : : }
170 : :
171 : 0 : void intel_ring_free(struct kref *ref)
172 : : {
173 : 0 : struct intel_ring *ring = container_of(ref, typeof(*ring), ref);
174 : :
175 : 0 : i915_vma_put(ring->vma);
176 : 0 : kfree(ring);
177 : 0 : }
178 : :
179 : : static noinline int
180 : 0 : wait_for_space(struct intel_ring *ring,
181 : : struct intel_timeline *tl,
182 : : unsigned int bytes)
183 : : {
184 : 0 : struct i915_request *target;
185 : 0 : long timeout;
186 : :
187 [ # # ]: 0 : if (intel_ring_update_space(ring) >= bytes)
188 : : return 0;
189 : :
190 : 0 : GEM_BUG_ON(list_empty(&tl->requests));
191 [ # # ]: 0 : list_for_each_entry(target, &tl->requests, link) {
192 [ # # ]: 0 : if (target->ring != ring)
193 : 0 : continue;
194 : :
195 : : /* Would completion of this request free enough space? */
196 [ # # ]: 0 : if (bytes <= __intel_ring_space(target->postfix,
197 : : ring->emit, ring->size))
198 : : break;
199 : : }
200 : :
201 [ # # ]: 0 : if (GEM_WARN_ON(&target->link == &tl->requests))
202 : : return -ENOSPC;
203 : :
204 : 0 : timeout = i915_request_wait(target,
205 : : I915_WAIT_INTERRUPTIBLE,
206 : : MAX_SCHEDULE_TIMEOUT);
207 [ # # ]: 0 : if (timeout < 0)
208 : 0 : return timeout;
209 : :
210 : 0 : i915_request_retire_upto(target);
211 : :
212 : 0 : intel_ring_update_space(ring);
213 : 0 : GEM_BUG_ON(ring->space < bytes);
214 : 0 : return 0;
215 : : }
216 : :
217 : 0 : u32 *intel_ring_begin(struct i915_request *rq, unsigned int num_dwords)
218 : : {
219 : 0 : struct intel_ring *ring = rq->ring;
220 : 0 : const unsigned int remain_usable = ring->effective_size - ring->emit;
221 : 0 : const unsigned int bytes = num_dwords * sizeof(u32);
222 : 0 : unsigned int need_wrap = 0;
223 : 0 : unsigned int total_bytes;
224 : 0 : u32 *cs;
225 : :
226 : : /* Packets must be qword aligned. */
227 : 0 : GEM_BUG_ON(num_dwords & 1);
228 : :
229 : 0 : total_bytes = bytes + rq->reserved_space;
230 : 0 : GEM_BUG_ON(total_bytes > ring->effective_size);
231 : :
232 [ # # ]: 0 : if (unlikely(total_bytes > remain_usable)) {
233 : 0 : const int remain_actual = ring->size - ring->emit;
234 : :
235 [ # # ]: 0 : if (bytes > remain_usable) {
236 : : /*
237 : : * Not enough space for the basic request. So need to
238 : : * flush out the remainder and then wait for
239 : : * base + reserved.
240 : : */
241 : 0 : total_bytes += remain_actual;
242 : 0 : need_wrap = remain_actual | 1;
243 : : } else {
244 : : /*
245 : : * The base request will fit but the reserved space
246 : : * falls off the end. So we don't need an immediate
247 : : * wrap and only need to effectively wait for the
248 : : * reserved size from the start of ringbuffer.
249 : : */
250 : 0 : total_bytes = rq->reserved_space + remain_actual;
251 : : }
252 : : }
253 : :
254 [ # # ]: 0 : if (unlikely(total_bytes > ring->space)) {
255 : 0 : int ret;
256 : :
257 : : /*
258 : : * Space is reserved in the ringbuffer for finalising the
259 : : * request, as that cannot be allowed to fail. During request
260 : : * finalisation, reserved_space is set to 0 to stop the
261 : : * overallocation and the assumption is that then we never need
262 : : * to wait (which has the risk of failing with EINTR).
263 : : *
264 : : * See also i915_request_alloc() and i915_request_add().
265 : : */
266 : 0 : GEM_BUG_ON(!rq->reserved_space);
267 : :
268 : 0 : ret = wait_for_space(ring,
269 : : i915_request_timeline(rq),
270 : : total_bytes);
271 [ # # ]: 0 : if (unlikely(ret))
272 : 0 : return ERR_PTR(ret);
273 : : }
274 : :
275 [ # # ]: 0 : if (unlikely(need_wrap)) {
276 : 0 : need_wrap &= ~1;
277 : 0 : GEM_BUG_ON(need_wrap > ring->space);
278 : 0 : GEM_BUG_ON(ring->emit + need_wrap > ring->size);
279 : 0 : GEM_BUG_ON(!IS_ALIGNED(need_wrap, sizeof(u64)));
280 : :
281 : : /* Fill the tail with MI_NOOP */
282 : 0 : memset64(ring->vaddr + ring->emit, 0, need_wrap / sizeof(u64));
283 : 0 : ring->space -= need_wrap;
284 : 0 : ring->emit = 0;
285 : : }
286 : :
287 : 0 : GEM_BUG_ON(ring->emit > ring->size - bytes);
288 : 0 : GEM_BUG_ON(ring->space < bytes);
289 : 0 : cs = ring->vaddr + ring->emit;
290 : 0 : GEM_DEBUG_EXEC(memset32(cs, POISON_INUSE, bytes / sizeof(*cs)));
291 : 0 : ring->emit += bytes;
292 : 0 : ring->space -= bytes;
293 : :
294 : 0 : return cs;
295 : : }
296 : :
297 : : /* Align the ring tail to a cacheline boundary */
298 : 0 : int intel_ring_cacheline_align(struct i915_request *rq)
299 : : {
300 : 0 : int num_dwords;
301 : 0 : void *cs;
302 : :
303 : 0 : num_dwords = (rq->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(u32);
304 [ # # ]: 0 : if (num_dwords == 0)
305 : : return 0;
306 : :
307 : 0 : num_dwords = CACHELINE_DWORDS - num_dwords;
308 : 0 : GEM_BUG_ON(num_dwords & 1);
309 : :
310 : 0 : cs = intel_ring_begin(rq, num_dwords);
311 [ # # ]: 0 : if (IS_ERR(cs))
312 : 0 : return PTR_ERR(cs);
313 : :
314 : 0 : memset64(cs, (u64)MI_NOOP << 32 | MI_NOOP, num_dwords / 2);
315 : 0 : intel_ring_advance(rq, cs + num_dwords);
316 : :
317 : 0 : GEM_BUG_ON(rq->ring->emit & (CACHELINE_BYTES - 1));
318 : 0 : return 0;
319 : : }
|