]>
Commit | Line | Data |
---|---|---|
a8c21a54 T |
1 | /* |
2 | * Copyright (C) 2015 Etnaviv Project | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of the GNU General Public License version 2 as published by | |
6 | * the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
11 | * more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License along with | |
14 | * this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
9ad59fea | 17 | #include <linux/dma-fence-array.h> |
a8c21a54 | 18 | #include <linux/reservation.h> |
9ad59fea | 19 | #include <linux/sync_file.h> |
ea1f5729 | 20 | #include "etnaviv_cmdbuf.h" |
a8c21a54 T |
21 | #include "etnaviv_drv.h" |
22 | #include "etnaviv_gpu.h" | |
23 | #include "etnaviv_gem.h" | |
c8e4a7fd | 24 | #include "etnaviv_perfmon.h" |
a8c21a54 T |
25 | |
26 | /* | |
27 | * Cmdstream submission: | |
28 | */ | |
29 | ||
30 | #define BO_INVALID_FLAGS ~(ETNA_SUBMIT_BO_READ | ETNA_SUBMIT_BO_WRITE) | |
31 | /* make sure these don't conflict w/ ETNAVIV_SUBMIT_BO_x */ | |
32 | #define BO_LOCKED 0x4000 | |
33 | #define BO_PINNED 0x2000 | |
34 | ||
a8c21a54 T |
35 | static struct etnaviv_gem_submit *submit_create(struct drm_device *dev, |
36 | struct etnaviv_gpu *gpu, size_t nr) | |
37 | { | |
38 | struct etnaviv_gem_submit *submit; | |
39 | size_t sz = size_vstruct(nr, sizeof(submit->bos[0]), sizeof(*submit)); | |
40 | ||
c5283723 LS |
41 | submit = kzalloc(sz, GFP_KERNEL); |
42 | if (!submit) | |
43 | return NULL; | |
a8c21a54 | 44 | |
c5283723 | 45 | submit->gpu = gpu; |
a8c21a54 | 46 | |
a8c21a54 T |
47 | return submit; |
48 | } | |
49 | ||
50 | static int submit_lookup_objects(struct etnaviv_gem_submit *submit, | |
51 | struct drm_file *file, struct drm_etnaviv_gem_submit_bo *submit_bos, | |
52 | unsigned nr_bos) | |
53 | { | |
54 | struct drm_etnaviv_gem_submit_bo *bo; | |
55 | unsigned i; | |
56 | int ret = 0; | |
57 | ||
58 | spin_lock(&file->table_lock); | |
59 | ||
60 | for (i = 0, bo = submit_bos; i < nr_bos; i++, bo++) { | |
61 | struct drm_gem_object *obj; | |
62 | ||
63 | if (bo->flags & BO_INVALID_FLAGS) { | |
64 | DRM_ERROR("invalid flags: %x\n", bo->flags); | |
65 | ret = -EINVAL; | |
66 | goto out_unlock; | |
67 | } | |
68 | ||
69 | submit->bos[i].flags = bo->flags; | |
70 | ||
71 | /* normally use drm_gem_object_lookup(), but for bulk lookup | |
72 | * all under single table_lock just hit object_idr directly: | |
73 | */ | |
74 | obj = idr_find(&file->object_idr, bo->handle); | |
75 | if (!obj) { | |
76 | DRM_ERROR("invalid handle %u at index %u\n", | |
77 | bo->handle, i); | |
78 | ret = -EINVAL; | |
79 | goto out_unlock; | |
80 | } | |
81 | ||
82 | /* | |
83 | * Take a refcount on the object. The file table lock | |
84 | * prevents the object_idr's refcount on this being dropped. | |
85 | */ | |
23d1dd03 | 86 | drm_gem_object_get(obj); |
a8c21a54 T |
87 | |
88 | submit->bos[i].obj = to_etnaviv_bo(obj); | |
89 | } | |
90 | ||
91 | out_unlock: | |
92 | submit->nr_bos = i; | |
93 | spin_unlock(&file->table_lock); | |
94 | ||
95 | return ret; | |
96 | } | |
97 | ||
98 | static void submit_unlock_object(struct etnaviv_gem_submit *submit, int i) | |
99 | { | |
100 | if (submit->bos[i].flags & BO_LOCKED) { | |
101 | struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; | |
102 | ||
103 | ww_mutex_unlock(&etnaviv_obj->resv->lock); | |
104 | submit->bos[i].flags &= ~BO_LOCKED; | |
105 | } | |
106 | } | |
107 | ||
08301d73 LS |
108 | static int submit_lock_objects(struct etnaviv_gem_submit *submit, |
109 | struct ww_acquire_ctx *ticket) | |
a8c21a54 T |
110 | { |
111 | int contended, slow_locked = -1, i, ret = 0; | |
112 | ||
113 | retry: | |
114 | for (i = 0; i < submit->nr_bos; i++) { | |
115 | struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; | |
116 | ||
117 | if (slow_locked == i) | |
118 | slow_locked = -1; | |
119 | ||
120 | contended = i; | |
121 | ||
122 | if (!(submit->bos[i].flags & BO_LOCKED)) { | |
123 | ret = ww_mutex_lock_interruptible(&etnaviv_obj->resv->lock, | |
08301d73 | 124 | ticket); |
a8c21a54 T |
125 | if (ret == -EALREADY) |
126 | DRM_ERROR("BO at index %u already on submit list\n", | |
127 | i); | |
128 | if (ret) | |
129 | goto fail; | |
130 | submit->bos[i].flags |= BO_LOCKED; | |
131 | } | |
132 | } | |
133 | ||
08301d73 | 134 | ww_acquire_done(ticket); |
a8c21a54 T |
135 | |
136 | return 0; | |
137 | ||
138 | fail: | |
139 | for (; i >= 0; i--) | |
140 | submit_unlock_object(submit, i); | |
141 | ||
142 | if (slow_locked > 0) | |
143 | submit_unlock_object(submit, slow_locked); | |
144 | ||
145 | if (ret == -EDEADLK) { | |
146 | struct etnaviv_gem_object *etnaviv_obj; | |
147 | ||
148 | etnaviv_obj = submit->bos[contended].obj; | |
149 | ||
150 | /* we lost out in a seqno race, lock and retry.. */ | |
151 | ret = ww_mutex_lock_slow_interruptible(&etnaviv_obj->resv->lock, | |
08301d73 | 152 | ticket); |
a8c21a54 T |
153 | if (!ret) { |
154 | submit->bos[contended].flags |= BO_LOCKED; | |
155 | slow_locked = contended; | |
156 | goto retry; | |
157 | } | |
158 | } | |
159 | ||
160 | return ret; | |
161 | } | |
162 | ||
163 | static int submit_fence_sync(const struct etnaviv_gem_submit *submit) | |
164 | { | |
165 | unsigned int context = submit->gpu->fence_context; | |
166 | int i, ret = 0; | |
167 | ||
168 | for (i = 0; i < submit->nr_bos; i++) { | |
169 | struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; | |
170 | bool write = submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE; | |
426ef1bb | 171 | bool explicit = !!(submit->flags & ETNA_SUBMIT_NO_IMPLICIT); |
a8c21a54 | 172 | |
9ad59fea PZ |
173 | ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write, |
174 | explicit); | |
a8c21a54 T |
175 | if (ret) |
176 | break; | |
177 | } | |
178 | ||
9efabd73 LS |
179 | if (submit->flags & ETNA_SUBMIT_FENCE_FD_IN) { |
180 | /* | |
181 | * Wait if the fence is from a foreign context, or if the fence | |
182 | * array contains any fence from a foreign context. | |
183 | */ | |
184 | if (!dma_fence_match_context(submit->in_fence, context)) | |
185 | ret = dma_fence_wait(submit->in_fence, true); | |
186 | } | |
187 | ||
a8c21a54 T |
188 | return ret; |
189 | } | |
190 | ||
0236efe9 LS |
191 | static void submit_attach_object_fences(struct etnaviv_gem_submit *submit) |
192 | { | |
193 | int i; | |
194 | ||
195 | for (i = 0; i < submit->nr_bos; i++) { | |
196 | struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; | |
197 | ||
198 | if (submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE) | |
199 | reservation_object_add_excl_fence(etnaviv_obj->resv, | |
10009ea2 | 200 | submit->out_fence); |
0236efe9 LS |
201 | else |
202 | reservation_object_add_shared_fence(etnaviv_obj->resv, | |
10009ea2 | 203 | submit->out_fence); |
0236efe9 LS |
204 | |
205 | submit_unlock_object(submit, i); | |
206 | } | |
207 | } | |
208 | ||
a8c21a54 T |
209 | static int submit_pin_objects(struct etnaviv_gem_submit *submit) |
210 | { | |
211 | int i, ret = 0; | |
212 | ||
213 | for (i = 0; i < submit->nr_bos; i++) { | |
214 | struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; | |
b6325f40 | 215 | struct etnaviv_vram_mapping *mapping; |
a8c21a54 | 216 | |
b6325f40 RK |
217 | mapping = etnaviv_gem_mapping_get(&etnaviv_obj->base, |
218 | submit->gpu); | |
219 | if (IS_ERR(mapping)) { | |
220 | ret = PTR_ERR(mapping); | |
a8c21a54 | 221 | break; |
b6325f40 | 222 | } |
a8c21a54 T |
223 | |
224 | submit->bos[i].flags |= BO_PINNED; | |
b6325f40 | 225 | submit->bos[i].mapping = mapping; |
a8c21a54 T |
226 | } |
227 | ||
228 | return ret; | |
229 | } | |
230 | ||
231 | static int submit_bo(struct etnaviv_gem_submit *submit, u32 idx, | |
8779aa8f | 232 | struct etnaviv_gem_submit_bo **bo) |
a8c21a54 T |
233 | { |
234 | if (idx >= submit->nr_bos) { | |
235 | DRM_ERROR("invalid buffer index: %u (out of %u)\n", | |
236 | idx, submit->nr_bos); | |
237 | return -EINVAL; | |
238 | } | |
239 | ||
8779aa8f | 240 | *bo = &submit->bos[idx]; |
a8c21a54 T |
241 | |
242 | return 0; | |
243 | } | |
244 | ||
245 | /* process the reloc's and patch up the cmdstream as needed: */ | |
246 | static int submit_reloc(struct etnaviv_gem_submit *submit, void *stream, | |
247 | u32 size, const struct drm_etnaviv_gem_submit_reloc *relocs, | |
248 | u32 nr_relocs) | |
249 | { | |
250 | u32 i, last_offset = 0; | |
251 | u32 *ptr = stream; | |
252 | int ret; | |
253 | ||
254 | for (i = 0; i < nr_relocs; i++) { | |
255 | const struct drm_etnaviv_gem_submit_reloc *r = relocs + i; | |
8779aa8f RK |
256 | struct etnaviv_gem_submit_bo *bo; |
257 | u32 off; | |
a8c21a54 T |
258 | |
259 | if (unlikely(r->flags)) { | |
260 | DRM_ERROR("invalid reloc flags\n"); | |
261 | return -EINVAL; | |
262 | } | |
263 | ||
264 | if (r->submit_offset % 4) { | |
265 | DRM_ERROR("non-aligned reloc offset: %u\n", | |
266 | r->submit_offset); | |
267 | return -EINVAL; | |
268 | } | |
269 | ||
270 | /* offset in dwords: */ | |
271 | off = r->submit_offset / 4; | |
272 | ||
273 | if ((off >= size ) || | |
274 | (off < last_offset)) { | |
275 | DRM_ERROR("invalid offset %u at reloc %u\n", off, i); | |
276 | return -EINVAL; | |
277 | } | |
278 | ||
8779aa8f | 279 | ret = submit_bo(submit, r->reloc_idx, &bo); |
a8c21a54 T |
280 | if (ret) |
281 | return ret; | |
282 | ||
d6f756e0 WL |
283 | if (r->reloc_offset > bo->obj->base.size - sizeof(*ptr)) { |
284 | DRM_ERROR("relocation %u outside object\n", i); | |
a8c21a54 T |
285 | return -EINVAL; |
286 | } | |
287 | ||
8779aa8f | 288 | ptr[off] = bo->mapping->iova + r->reloc_offset; |
a8c21a54 T |
289 | |
290 | last_offset = off; | |
291 | } | |
292 | ||
293 | return 0; | |
294 | } | |
295 | ||
c8e4a7fd CG |
296 | static int submit_perfmon_validate(struct etnaviv_gem_submit *submit, |
297 | struct etnaviv_cmdbuf *cmdbuf, | |
298 | const struct drm_etnaviv_gem_submit_pmr *pmrs, | |
299 | u32 nr_pms) | |
300 | { | |
301 | u32 i; | |
302 | ||
303 | for (i = 0; i < nr_pms; i++) { | |
304 | const struct drm_etnaviv_gem_submit_pmr *r = pmrs + i; | |
305 | struct etnaviv_gem_submit_bo *bo; | |
306 | int ret; | |
307 | ||
308 | ret = submit_bo(submit, r->read_idx, &bo); | |
309 | if (ret) | |
310 | return ret; | |
311 | ||
312 | /* at offset 0 a sequence number gets stored used for userspace sync */ | |
313 | if (r->read_offset == 0) { | |
314 | DRM_ERROR("perfmon request: offset is 0"); | |
315 | return -EINVAL; | |
316 | } | |
317 | ||
318 | if (r->read_offset >= bo->obj->base.size - sizeof(u32)) { | |
319 | DRM_ERROR("perfmon request: offset %u outside object", i); | |
320 | return -EINVAL; | |
321 | } | |
322 | ||
323 | if (r->flags & ~(ETNA_PM_PROCESS_PRE | ETNA_PM_PROCESS_POST)) { | |
324 | DRM_ERROR("perfmon request: flags are not valid"); | |
325 | return -EINVAL; | |
326 | } | |
327 | ||
328 | if (etnaviv_pm_req_validate(r, cmdbuf->exec_state)) { | |
329 | DRM_ERROR("perfmon request: domain or signal not valid"); | |
330 | return -EINVAL; | |
331 | } | |
332 | ||
333 | cmdbuf->pmrs[i].flags = r->flags; | |
334 | cmdbuf->pmrs[i].domain = r->domain; | |
335 | cmdbuf->pmrs[i].signal = r->signal; | |
336 | cmdbuf->pmrs[i].sequence = r->sequence; | |
337 | cmdbuf->pmrs[i].offset = r->read_offset; | |
338 | cmdbuf->pmrs[i].bo_vma = etnaviv_gem_vmap(&bo->obj->base); | |
339 | } | |
340 | ||
341 | return 0; | |
342 | } | |
343 | ||
a8c21a54 T |
344 | static void submit_cleanup(struct etnaviv_gem_submit *submit) |
345 | { | |
346 | unsigned i; | |
347 | ||
348 | for (i = 0; i < submit->nr_bos; i++) { | |
349 | struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; | |
350 | ||
33a63e68 LS |
351 | /* unpin all objects */ |
352 | if (submit->bos[i].flags & BO_PINNED) { | |
353 | etnaviv_gem_mapping_unreference(submit->bos[i].mapping); | |
354 | submit->bos[i].mapping = NULL; | |
355 | submit->bos[i].flags &= ~BO_PINNED; | |
356 | } | |
357 | ||
0236efe9 | 358 | /* if the GPU submit failed, objects might still be locked */ |
a8c21a54 | 359 | submit_unlock_object(submit, i); |
23d1dd03 | 360 | drm_gem_object_put_unlocked(&etnaviv_obj->base); |
a8c21a54 T |
361 | } |
362 | ||
9efabd73 LS |
363 | if (submit->in_fence) |
364 | dma_fence_put(submit->in_fence); | |
10009ea2 LS |
365 | if (submit->out_fence) |
366 | dma_fence_put(submit->out_fence); | |
a8c21a54 T |
367 | kfree(submit); |
368 | } | |
369 | ||
370 | int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, | |
371 | struct drm_file *file) | |
372 | { | |
373 | struct etnaviv_drm_private *priv = dev->dev_private; | |
374 | struct drm_etnaviv_gem_submit *args = data; | |
375 | struct drm_etnaviv_gem_submit_reloc *relocs; | |
c8e4a7fd | 376 | struct drm_etnaviv_gem_submit_pmr *pmrs; |
a8c21a54 T |
377 | struct drm_etnaviv_gem_submit_bo *bos; |
378 | struct etnaviv_gem_submit *submit; | |
379 | struct etnaviv_cmdbuf *cmdbuf; | |
380 | struct etnaviv_gpu *gpu; | |
78ec187f | 381 | struct sync_file *sync_file = NULL; |
08301d73 | 382 | struct ww_acquire_ctx ticket; |
78ec187f | 383 | int out_fence_fd = -1; |
a8c21a54 T |
384 | void *stream; |
385 | int ret; | |
386 | ||
387 | if (args->pipe >= ETNA_MAX_PIPES) | |
388 | return -EINVAL; | |
389 | ||
390 | gpu = priv->gpu[args->pipe]; | |
391 | if (!gpu) | |
392 | return -ENXIO; | |
393 | ||
394 | if (args->stream_size % 4) { | |
395 | DRM_ERROR("non-aligned cmdstream buffer size: %u\n", | |
396 | args->stream_size); | |
397 | return -EINVAL; | |
398 | } | |
399 | ||
400 | if (args->exec_state != ETNA_PIPE_3D && | |
401 | args->exec_state != ETNA_PIPE_2D && | |
402 | args->exec_state != ETNA_PIPE_VG) { | |
403 | DRM_ERROR("invalid exec_state: 0x%x\n", args->exec_state); | |
404 | return -EINVAL; | |
405 | } | |
406 | ||
9ad59fea PZ |
407 | if (args->flags & ~ETNA_SUBMIT_FLAGS) { |
408 | DRM_ERROR("invalid flags: 0x%x\n", args->flags); | |
409 | return -EINVAL; | |
410 | } | |
411 | ||
a8c21a54 T |
412 | /* |
413 | * Copy the command submission and bo array to kernel space in | |
414 | * one go, and do this outside of any locks. | |
415 | */ | |
2098105e MH |
416 | bos = kvmalloc_array(args->nr_bos, sizeof(*bos), GFP_KERNEL); |
417 | relocs = kvmalloc_array(args->nr_relocs, sizeof(*relocs), GFP_KERNEL); | |
c8e4a7fd | 418 | pmrs = kvmalloc_array(args->nr_pmrs, sizeof(*pmrs), GFP_KERNEL); |
2098105e | 419 | stream = kvmalloc_array(1, args->stream_size, GFP_KERNEL); |
e66774dd LS |
420 | cmdbuf = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, |
421 | ALIGN(args->stream_size, 8) + 8, | |
c8e4a7fd CG |
422 | args->nr_bos, args->nr_pmrs); |
423 | if (!bos || !relocs || !pmrs || !stream || !cmdbuf) { | |
a8c21a54 T |
424 | ret = -ENOMEM; |
425 | goto err_submit_cmds; | |
426 | } | |
427 | ||
428 | cmdbuf->exec_state = args->exec_state; | |
429 | cmdbuf->ctx = file->driver_priv; | |
430 | ||
3ed605bc | 431 | ret = copy_from_user(bos, u64_to_user_ptr(args->bos), |
a8c21a54 T |
432 | args->nr_bos * sizeof(*bos)); |
433 | if (ret) { | |
434 | ret = -EFAULT; | |
435 | goto err_submit_cmds; | |
436 | } | |
437 | ||
3ed605bc | 438 | ret = copy_from_user(relocs, u64_to_user_ptr(args->relocs), |
a8c21a54 T |
439 | args->nr_relocs * sizeof(*relocs)); |
440 | if (ret) { | |
441 | ret = -EFAULT; | |
442 | goto err_submit_cmds; | |
443 | } | |
444 | ||
c8e4a7fd CG |
445 | ret = copy_from_user(pmrs, u64_to_user_ptr(args->pmrs), |
446 | args->nr_pmrs * sizeof(*pmrs)); | |
447 | if (ret) { | |
448 | ret = -EFAULT; | |
449 | goto err_submit_cmds; | |
450 | } | |
451 | cmdbuf->nr_pmrs = args->nr_pmrs; | |
452 | ||
3ed605bc | 453 | ret = copy_from_user(stream, u64_to_user_ptr(args->stream), |
a8c21a54 T |
454 | args->stream_size); |
455 | if (ret) { | |
456 | ret = -EFAULT; | |
457 | goto err_submit_cmds; | |
458 | } | |
459 | ||
78ec187f PZ |
460 | if (args->flags & ETNA_SUBMIT_FENCE_FD_OUT) { |
461 | out_fence_fd = get_unused_fd_flags(O_CLOEXEC); | |
462 | if (out_fence_fd < 0) { | |
463 | ret = out_fence_fd; | |
464 | goto err_submit_cmds; | |
465 | } | |
466 | } | |
467 | ||
08301d73 LS |
468 | ww_acquire_init(&ticket, &reservation_ww_class); |
469 | ||
a8c21a54 T |
470 | submit = submit_create(dev, gpu, args->nr_bos); |
471 | if (!submit) { | |
472 | ret = -ENOMEM; | |
08301d73 | 473 | goto err_submit_ww_acquire; |
a8c21a54 T |
474 | } |
475 | ||
9ad59fea PZ |
476 | submit->flags = args->flags; |
477 | ||
a8c21a54 T |
478 | ret = submit_lookup_objects(submit, file, bos, args->nr_bos); |
479 | if (ret) | |
480 | goto err_submit_objects; | |
481 | ||
08301d73 | 482 | ret = submit_lock_objects(submit, &ticket); |
a8c21a54 T |
483 | if (ret) |
484 | goto err_submit_objects; | |
485 | ||
486 | if (!etnaviv_cmd_validate_one(gpu, stream, args->stream_size / 4, | |
487 | relocs, args->nr_relocs)) { | |
488 | ret = -EINVAL; | |
489 | goto err_submit_objects; | |
490 | } | |
491 | ||
9ad59fea | 492 | if (args->flags & ETNA_SUBMIT_FENCE_FD_IN) { |
9efabd73 LS |
493 | submit->in_fence = sync_file_get_fence(args->fence_fd); |
494 | if (!submit->in_fence) { | |
9ad59fea PZ |
495 | ret = -EINVAL; |
496 | goto err_submit_objects; | |
497 | } | |
9ad59fea PZ |
498 | } |
499 | ||
a8c21a54 T |
500 | ret = submit_fence_sync(submit); |
501 | if (ret) | |
502 | goto err_submit_objects; | |
503 | ||
504 | ret = submit_pin_objects(submit); | |
505 | if (ret) | |
33a63e68 | 506 | goto err_submit_objects; |
a8c21a54 T |
507 | |
508 | ret = submit_reloc(submit, stream, args->stream_size / 4, | |
509 | relocs, args->nr_relocs); | |
510 | if (ret) | |
33a63e68 | 511 | goto err_submit_objects; |
a8c21a54 | 512 | |
c8e4a7fd CG |
513 | ret = submit_perfmon_validate(submit, cmdbuf, pmrs, args->nr_pmrs); |
514 | if (ret) | |
33a63e68 | 515 | goto err_submit_objects; |
c8e4a7fd | 516 | |
a8c21a54 T |
517 | memcpy(cmdbuf->vaddr, stream, args->stream_size); |
518 | cmdbuf->user_size = ALIGN(args->stream_size, 8); | |
519 | ||
520 | ret = etnaviv_gpu_submit(gpu, submit, cmdbuf); | |
5a642e6b | 521 | if (ret) |
33a63e68 | 522 | goto err_submit_objects; |
5a642e6b | 523 | |
0236efe9 LS |
524 | submit_attach_object_fences(submit); |
525 | ||
5a642e6b | 526 | cmdbuf = NULL; |
a8c21a54 | 527 | |
78ec187f PZ |
528 | if (args->flags & ETNA_SUBMIT_FENCE_FD_OUT) { |
529 | /* | |
530 | * This can be improved: ideally we want to allocate the sync | |
531 | * file before kicking off the GPU job and just attach the | |
532 | * fence to the sync file here, eliminating the ENOMEM | |
533 | * possibility at this stage. | |
534 | */ | |
10009ea2 | 535 | sync_file = sync_file_create(submit->out_fence); |
78ec187f PZ |
536 | if (!sync_file) { |
537 | ret = -ENOMEM; | |
33a63e68 | 538 | goto err_submit_objects; |
78ec187f PZ |
539 | } |
540 | fd_install(out_fence_fd, sync_file->file); | |
541 | } | |
542 | ||
543 | args->fence_fd = out_fence_fd; | |
10009ea2 | 544 | args->fence = submit->out_fence->seqno; |
a8c21a54 | 545 | |
a8c21a54 T |
546 | err_submit_objects: |
547 | submit_cleanup(submit); | |
548 | ||
08301d73 LS |
549 | err_submit_ww_acquire: |
550 | ww_acquire_fini(&ticket); | |
551 | ||
a8c21a54 | 552 | err_submit_cmds: |
78ec187f PZ |
553 | if (ret && (out_fence_fd >= 0)) |
554 | put_unused_fd(out_fence_fd); | |
a8c21a54 T |
555 | /* if we still own the cmdbuf */ |
556 | if (cmdbuf) | |
ea1f5729 | 557 | etnaviv_cmdbuf_free(cmdbuf); |
a8c21a54 | 558 | if (stream) |
2098105e | 559 | kvfree(stream); |
a8c21a54 | 560 | if (bos) |
2098105e | 561 | kvfree(bos); |
a8c21a54 | 562 | if (relocs) |
2098105e | 563 | kvfree(relocs); |
c8e4a7fd CG |
564 | if (pmrs) |
565 | kvfree(pmrs); | |
a8c21a54 T |
566 | |
567 | return ret; | |
568 | } |