1a1d2a633SQiang Yu // SPDX-License-Identifier: GPL-2.0 OR MIT
2a1d2a633SQiang Yu /* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
3a1d2a633SQiang Yu
480bb8d98SQiang Yu #include <linux/mm.h>
57938f421SLucas De Marchi #include <linux/iosys-map.h>
6a1d2a633SQiang Yu #include <linux/sync_file.h>
7d61dd248SQiang Yu #include <linux/pagemap.h>
86aebc51dSQiang Yu #include <linux/shmem_fs.h>
96aebc51dSQiang Yu #include <linux/dma-mapping.h>
10a1d2a633SQiang Yu
11a1d2a633SQiang Yu #include <drm/drm_file.h>
12a1d2a633SQiang Yu #include <drm/drm_syncobj.h>
13a1d2a633SQiang Yu #include <drm/drm_utils.h>
14a1d2a633SQiang Yu
15a1d2a633SQiang Yu #include <drm/lima_drm.h>
16a1d2a633SQiang Yu
17a1d2a633SQiang Yu #include "lima_drv.h"
18a1d2a633SQiang Yu #include "lima_gem.h"
19a1d2a633SQiang Yu #include "lima_vm.h"
20a1d2a633SQiang Yu
lima_heap_alloc(struct lima_bo * bo,struct lima_vm * vm)216aebc51dSQiang Yu int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
226aebc51dSQiang Yu {
236aebc51dSQiang Yu struct page **pages;
246aebc51dSQiang Yu struct address_space *mapping = bo->base.base.filp->f_mapping;
256aebc51dSQiang Yu struct device *dev = bo->base.base.dev->dev;
266aebc51dSQiang Yu size_t old_size = bo->heap_size;
276aebc51dSQiang Yu size_t new_size = bo->heap_size ? bo->heap_size * 2 :
286aebc51dSQiang Yu (lima_heap_init_nr_pages << PAGE_SHIFT);
296aebc51dSQiang Yu struct sg_table sgt;
306aebc51dSQiang Yu int i, ret;
316aebc51dSQiang Yu
326aebc51dSQiang Yu if (bo->heap_size >= bo->base.base.size)
336aebc51dSQiang Yu return -ENOSPC;
346aebc51dSQiang Yu
356aebc51dSQiang Yu new_size = min(new_size, bo->base.base.size);
366aebc51dSQiang Yu
3721aa27ddSDmitry Osipenko dma_resv_lock(bo->base.base.resv, NULL);
386aebc51dSQiang Yu
396aebc51dSQiang Yu if (bo->base.pages) {
406aebc51dSQiang Yu pages = bo->base.pages;
416aebc51dSQiang Yu } else {
426aebc51dSQiang Yu pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT,
436aebc51dSQiang Yu sizeof(*pages), GFP_KERNEL | __GFP_ZERO);
446aebc51dSQiang Yu if (!pages) {
4521aa27ddSDmitry Osipenko dma_resv_unlock(bo->base.base.resv);
466aebc51dSQiang Yu return -ENOMEM;
476aebc51dSQiang Yu }
486aebc51dSQiang Yu
496aebc51dSQiang Yu bo->base.pages = pages;
506aebc51dSQiang Yu bo->base.pages_use_count = 1;
516aebc51dSQiang Yu
526aebc51dSQiang Yu mapping_set_unevictable(mapping);
536aebc51dSQiang Yu }
546aebc51dSQiang Yu
556aebc51dSQiang Yu for (i = old_size >> PAGE_SHIFT; i < new_size >> PAGE_SHIFT; i++) {
566aebc51dSQiang Yu struct page *page = shmem_read_mapping_page(mapping, i);
576aebc51dSQiang Yu
586aebc51dSQiang Yu if (IS_ERR(page)) {
5921aa27ddSDmitry Osipenko dma_resv_unlock(bo->base.base.resv);
606aebc51dSQiang Yu return PTR_ERR(page);
616aebc51dSQiang Yu }
626aebc51dSQiang Yu pages[i] = page;
636aebc51dSQiang Yu }
646aebc51dSQiang Yu
6521aa27ddSDmitry Osipenko dma_resv_unlock(bo->base.base.resv);
666aebc51dSQiang Yu
676aebc51dSQiang Yu ret = sg_alloc_table_from_pages(&sgt, pages, i, 0,
686aebc51dSQiang Yu new_size, GFP_KERNEL);
696aebc51dSQiang Yu if (ret)
706aebc51dSQiang Yu return ret;
716aebc51dSQiang Yu
726aebc51dSQiang Yu if (bo->base.sgt) {
73c3d9c17fSMarek Szyprowski dma_unmap_sgtable(dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0);
746aebc51dSQiang Yu sg_free_table(bo->base.sgt);
756aebc51dSQiang Yu } else {
766aebc51dSQiang Yu bo->base.sgt = kmalloc(sizeof(*bo->base.sgt), GFP_KERNEL);
776aebc51dSQiang Yu if (!bo->base.sgt) {
78*8e25c0eeSZhipeng Lu ret = -ENOMEM;
79*8e25c0eeSZhipeng Lu goto err_out0;
806aebc51dSQiang Yu }
816aebc51dSQiang Yu }
826aebc51dSQiang Yu
83c3d9c17fSMarek Szyprowski ret = dma_map_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0);
84*8e25c0eeSZhipeng Lu if (ret)
85*8e25c0eeSZhipeng Lu goto err_out1;
866aebc51dSQiang Yu
876aebc51dSQiang Yu *bo->base.sgt = sgt;
886aebc51dSQiang Yu
896aebc51dSQiang Yu if (vm) {
906aebc51dSQiang Yu ret = lima_vm_map_bo(vm, bo, old_size >> PAGE_SHIFT);
916aebc51dSQiang Yu if (ret)
92*8e25c0eeSZhipeng Lu goto err_out2;
936aebc51dSQiang Yu }
946aebc51dSQiang Yu
956aebc51dSQiang Yu bo->heap_size = new_size;
966aebc51dSQiang Yu return 0;
97*8e25c0eeSZhipeng Lu
98*8e25c0eeSZhipeng Lu err_out2:
99*8e25c0eeSZhipeng Lu dma_unmap_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0);
100*8e25c0eeSZhipeng Lu err_out1:
101*8e25c0eeSZhipeng Lu kfree(bo->base.sgt);
102*8e25c0eeSZhipeng Lu bo->base.sgt = NULL;
103*8e25c0eeSZhipeng Lu err_out0:
104*8e25c0eeSZhipeng Lu sg_free_table(&sgt);
105*8e25c0eeSZhipeng Lu return ret;
1066aebc51dSQiang Yu }
1076aebc51dSQiang Yu
lima_gem_create_handle(struct drm_device * dev,struct drm_file * file,u32 size,u32 flags,u32 * handle)108a1d2a633SQiang Yu int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
109a1d2a633SQiang Yu u32 size, u32 flags, u32 *handle)
110a1d2a633SQiang Yu {
111a1d2a633SQiang Yu int err;
112d61dd248SQiang Yu gfp_t mask;
113d61dd248SQiang Yu struct drm_gem_shmem_object *shmem;
114d61dd248SQiang Yu struct drm_gem_object *obj;
1156aebc51dSQiang Yu struct lima_bo *bo;
1166aebc51dSQiang Yu bool is_heap = flags & LIMA_BO_FLAG_HEAP;
117a1d2a633SQiang Yu
118d61dd248SQiang Yu shmem = drm_gem_shmem_create(dev, size);
119d61dd248SQiang Yu if (IS_ERR(shmem))
120d61dd248SQiang Yu return PTR_ERR(shmem);
121a1d2a633SQiang Yu
122d61dd248SQiang Yu obj = &shmem->base;
123a1d2a633SQiang Yu
124d61dd248SQiang Yu /* Mali Utgard GPU can only support 32bit address space */
125d61dd248SQiang Yu mask = mapping_gfp_mask(obj->filp->f_mapping);
126d61dd248SQiang Yu mask &= ~__GFP_HIGHMEM;
127d61dd248SQiang Yu mask |= __GFP_DMA32;
128d61dd248SQiang Yu mapping_set_gfp_mask(obj->filp->f_mapping, mask);
129d61dd248SQiang Yu
1306aebc51dSQiang Yu if (is_heap) {
1316aebc51dSQiang Yu bo = to_lima_bo(obj);
1326aebc51dSQiang Yu err = lima_heap_alloc(bo, NULL);
1336aebc51dSQiang Yu if (err)
1346aebc51dSQiang Yu goto out;
1356aebc51dSQiang Yu } else {
136a193f3b4SThomas Zimmermann struct sg_table *sgt = drm_gem_shmem_get_pages_sgt(shmem);
1376aebc51dSQiang Yu
138d61dd248SQiang Yu if (IS_ERR(sgt)) {
139d61dd248SQiang Yu err = PTR_ERR(sgt);
140d61dd248SQiang Yu goto out;
141d61dd248SQiang Yu }
1426aebc51dSQiang Yu }
143d61dd248SQiang Yu
144d61dd248SQiang Yu err = drm_gem_handle_create(file, obj, handle);
145d61dd248SQiang Yu
146d61dd248SQiang Yu out:
147a1d2a633SQiang Yu /* drop reference from allocate - handle holds it now */
1484ded8550SEmil Velikov drm_gem_object_put(obj);
149a1d2a633SQiang Yu
150a1d2a633SQiang Yu return err;
151a1d2a633SQiang Yu }
152a1d2a633SQiang Yu
lima_gem_free_object(struct drm_gem_object * obj)153d61dd248SQiang Yu static void lima_gem_free_object(struct drm_gem_object *obj)
154a1d2a633SQiang Yu {
155a1d2a633SQiang Yu struct lima_bo *bo = to_lima_bo(obj);
156a1d2a633SQiang Yu
157a1d2a633SQiang Yu if (!list_empty(&bo->va))
158a1d2a633SQiang Yu dev_err(obj->dev->dev, "lima gem free bo still has va\n");
159a1d2a633SQiang Yu
160a193f3b4SThomas Zimmermann drm_gem_shmem_free(&bo->base);
161a1d2a633SQiang Yu }
162a1d2a633SQiang Yu
lima_gem_object_open(struct drm_gem_object * obj,struct drm_file * file)163d61dd248SQiang Yu static int lima_gem_object_open(struct drm_gem_object *obj, struct drm_file *file)
164a1d2a633SQiang Yu {
165a1d2a633SQiang Yu struct lima_bo *bo = to_lima_bo(obj);
166a1d2a633SQiang Yu struct lima_drm_priv *priv = to_lima_drm_priv(file);
167a1d2a633SQiang Yu struct lima_vm *vm = priv->vm;
168a1d2a633SQiang Yu
169a1d2a633SQiang Yu return lima_vm_bo_add(vm, bo, true);
170a1d2a633SQiang Yu }
171a1d2a633SQiang Yu
lima_gem_object_close(struct drm_gem_object * obj,struct drm_file * file)172d61dd248SQiang Yu static void lima_gem_object_close(struct drm_gem_object *obj, struct drm_file *file)
173a1d2a633SQiang Yu {
174a1d2a633SQiang Yu struct lima_bo *bo = to_lima_bo(obj);
175a1d2a633SQiang Yu struct lima_drm_priv *priv = to_lima_drm_priv(file);
176a1d2a633SQiang Yu struct lima_vm *vm = priv->vm;
177a1d2a633SQiang Yu
178a1d2a633SQiang Yu lima_vm_bo_del(vm, bo);
179a1d2a633SQiang Yu }
180a1d2a633SQiang Yu
lima_gem_pin(struct drm_gem_object * obj)1816aebc51dSQiang Yu static int lima_gem_pin(struct drm_gem_object *obj)
1826aebc51dSQiang Yu {
1836aebc51dSQiang Yu struct lima_bo *bo = to_lima_bo(obj);
1846aebc51dSQiang Yu
1856aebc51dSQiang Yu if (bo->heap_size)
1866aebc51dSQiang Yu return -EINVAL;
1876aebc51dSQiang Yu
188a193f3b4SThomas Zimmermann return drm_gem_shmem_pin(&bo->base);
1896aebc51dSQiang Yu }
1906aebc51dSQiang Yu
lima_gem_vmap(struct drm_gem_object * obj,struct iosys_map * map)1917938f421SLucas De Marchi static int lima_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map)
1926aebc51dSQiang Yu {
1936aebc51dSQiang Yu struct lima_bo *bo = to_lima_bo(obj);
1946aebc51dSQiang Yu
1956aebc51dSQiang Yu if (bo->heap_size)
19649a3f51dSThomas Zimmermann return -EINVAL;
1976aebc51dSQiang Yu
198a193f3b4SThomas Zimmermann return drm_gem_shmem_vmap(&bo->base, map);
1996aebc51dSQiang Yu }
2006aebc51dSQiang Yu
lima_gem_mmap(struct drm_gem_object * obj,struct vm_area_struct * vma)2016aebc51dSQiang Yu static int lima_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
2026aebc51dSQiang Yu {
2036aebc51dSQiang Yu struct lima_bo *bo = to_lima_bo(obj);
2046aebc51dSQiang Yu
2056aebc51dSQiang Yu if (bo->heap_size)
2066aebc51dSQiang Yu return -EINVAL;
2076aebc51dSQiang Yu
208a193f3b4SThomas Zimmermann return drm_gem_shmem_mmap(&bo->base, vma);
2096aebc51dSQiang Yu }
2106aebc51dSQiang Yu
211d61dd248SQiang Yu static const struct drm_gem_object_funcs lima_gem_funcs = {
212d61dd248SQiang Yu .free = lima_gem_free_object,
213d61dd248SQiang Yu .open = lima_gem_object_open,
214d61dd248SQiang Yu .close = lima_gem_object_close,
215c7fbcb71SThomas Zimmermann .print_info = drm_gem_shmem_object_print_info,
2166aebc51dSQiang Yu .pin = lima_gem_pin,
217c7fbcb71SThomas Zimmermann .unpin = drm_gem_shmem_object_unpin,
218c7fbcb71SThomas Zimmermann .get_sg_table = drm_gem_shmem_object_get_sg_table,
2196aebc51dSQiang Yu .vmap = lima_gem_vmap,
220c7fbcb71SThomas Zimmermann .vunmap = drm_gem_shmem_object_vunmap,
2216aebc51dSQiang Yu .mmap = lima_gem_mmap,
222d315bdbfSThomas Zimmermann .vm_ops = &drm_gem_shmem_vm_ops,
223d61dd248SQiang Yu };
224d61dd248SQiang Yu
lima_gem_create_object(struct drm_device * dev,size_t size)225d61dd248SQiang Yu struct drm_gem_object *lima_gem_create_object(struct drm_device *dev, size_t size)
226d61dd248SQiang Yu {
227d61dd248SQiang Yu struct lima_bo *bo;
228d61dd248SQiang Yu
229d61dd248SQiang Yu bo = kzalloc(sizeof(*bo), GFP_KERNEL);
230d61dd248SQiang Yu if (!bo)
2314ff22f48SThomas Zimmermann return ERR_PTR(-ENOMEM);
232d61dd248SQiang Yu
233d61dd248SQiang Yu mutex_init(&bo->lock);
234d61dd248SQiang Yu INIT_LIST_HEAD(&bo->va);
2350cf2ef46SThomas Zimmermann bo->base.map_wc = true;
236d61dd248SQiang Yu bo->base.base.funcs = &lima_gem_funcs;
237d61dd248SQiang Yu
238d61dd248SQiang Yu return &bo->base.base;
239d61dd248SQiang Yu }
240d61dd248SQiang Yu
lima_gem_get_info(struct drm_file * file,u32 handle,u32 * va,u64 * offset)241a1d2a633SQiang Yu int lima_gem_get_info(struct drm_file *file, u32 handle, u32 *va, u64 *offset)
242a1d2a633SQiang Yu {
243a1d2a633SQiang Yu struct drm_gem_object *obj;
244a1d2a633SQiang Yu struct lima_bo *bo;
245a1d2a633SQiang Yu struct lima_drm_priv *priv = to_lima_drm_priv(file);
246a1d2a633SQiang Yu struct lima_vm *vm = priv->vm;
247a1d2a633SQiang Yu
248a1d2a633SQiang Yu obj = drm_gem_object_lookup(file, handle);
249a1d2a633SQiang Yu if (!obj)
250a1d2a633SQiang Yu return -ENOENT;
251a1d2a633SQiang Yu
252a1d2a633SQiang Yu bo = to_lima_bo(obj);
253a1d2a633SQiang Yu
254a1d2a633SQiang Yu *va = lima_vm_get_va(vm, bo);
255a1d2a633SQiang Yu
256a1d2a633SQiang Yu *offset = drm_vma_node_offset_addr(&obj->vma_node);
257a1d2a633SQiang Yu
2584ded8550SEmil Velikov drm_gem_object_put(obj);
259a1d2a633SQiang Yu return 0;
260a1d2a633SQiang Yu }
261a1d2a633SQiang Yu
lima_gem_sync_bo(struct lima_sched_task * task,struct lima_bo * bo,bool write,bool explicit)262a1d2a633SQiang Yu static int lima_gem_sync_bo(struct lima_sched_task *task, struct lima_bo *bo,
263a1d2a633SQiang Yu bool write, bool explicit)
264a1d2a633SQiang Yu {
265c8d4c18bSChristian König int err;
266a1d2a633SQiang Yu
267c8d4c18bSChristian König err = dma_resv_reserve_fences(lima_bo_resv(bo), 1);
268a1d2a633SQiang Yu if (err)
269a1d2a633SQiang Yu return err;
270a1d2a633SQiang Yu
271a1d2a633SQiang Yu /* explicit sync use user passed dep fence */
272a1d2a633SQiang Yu if (explicit)
273a1d2a633SQiang Yu return 0;
274a1d2a633SQiang Yu
275c79a4487SDaniel Vetter return drm_sched_job_add_implicit_dependencies(&task->base,
276c79a4487SDaniel Vetter &bo->base.base,
277c79a4487SDaniel Vetter write);
278a1d2a633SQiang Yu }
279a1d2a633SQiang Yu
lima_gem_add_deps(struct drm_file * file,struct lima_submit * submit)280a1d2a633SQiang Yu static int lima_gem_add_deps(struct drm_file *file, struct lima_submit *submit)
281a1d2a633SQiang Yu {
282a1d2a633SQiang Yu int i, err;
283a1d2a633SQiang Yu
284a1d2a633SQiang Yu for (i = 0; i < ARRAY_SIZE(submit->in_sync); i++) {
285a1d2a633SQiang Yu if (!submit->in_sync[i])
286a1d2a633SQiang Yu continue;
287a1d2a633SQiang Yu
288e0dfefa0SMaíra Canal err = drm_sched_job_add_syncobj_dependency(&submit->task->base, file,
289e0dfefa0SMaíra Canal submit->in_sync[i], 0);
290a1d2a633SQiang Yu if (err)
291a1d2a633SQiang Yu return err;
292a1d2a633SQiang Yu }
293a1d2a633SQiang Yu
294a1d2a633SQiang Yu return 0;
295a1d2a633SQiang Yu }
296a1d2a633SQiang Yu
lima_gem_submit(struct drm_file * file,struct lima_submit * submit)297a1d2a633SQiang Yu int lima_gem_submit(struct drm_file *file, struct lima_submit *submit)
298a1d2a633SQiang Yu {
299a1d2a633SQiang Yu int i, err = 0;
300a1d2a633SQiang Yu struct ww_acquire_ctx ctx;
301a1d2a633SQiang Yu struct lima_drm_priv *priv = to_lima_drm_priv(file);
302a1d2a633SQiang Yu struct lima_vm *vm = priv->vm;
303a1d2a633SQiang Yu struct drm_syncobj *out_sync = NULL;
304a1d2a633SQiang Yu struct dma_fence *fence;
305a1d2a633SQiang Yu struct lima_bo **bos = submit->lbos;
306a1d2a633SQiang Yu
307a1d2a633SQiang Yu if (submit->out_sync) {
308a1d2a633SQiang Yu out_sync = drm_syncobj_find(file, submit->out_sync);
309a1d2a633SQiang Yu if (!out_sync)
310a1d2a633SQiang Yu return -ENOENT;
311a1d2a633SQiang Yu }
312a1d2a633SQiang Yu
313a1d2a633SQiang Yu for (i = 0; i < submit->nr_bos; i++) {
314a1d2a633SQiang Yu struct drm_gem_object *obj;
315a1d2a633SQiang Yu struct lima_bo *bo;
316a1d2a633SQiang Yu
317a1d2a633SQiang Yu obj = drm_gem_object_lookup(file, submit->bos[i].handle);
318a1d2a633SQiang Yu if (!obj) {
319a1d2a633SQiang Yu err = -ENOENT;
320a1d2a633SQiang Yu goto err_out0;
321a1d2a633SQiang Yu }
322a1d2a633SQiang Yu
323a1d2a633SQiang Yu bo = to_lima_bo(obj);
324a1d2a633SQiang Yu
325a1d2a633SQiang Yu /* increase refcnt of gpu va map to prevent unmapped when executing,
326a1d2a633SQiang Yu * will be decreased when task done
327a1d2a633SQiang Yu */
328a1d2a633SQiang Yu err = lima_vm_bo_add(vm, bo, false);
329a1d2a633SQiang Yu if (err) {
3304ded8550SEmil Velikov drm_gem_object_put(obj);
331a1d2a633SQiang Yu goto err_out0;
332a1d2a633SQiang Yu }
333a1d2a633SQiang Yu
334a1d2a633SQiang Yu bos[i] = bo;
335a1d2a633SQiang Yu }
336a1d2a633SQiang Yu
337e305b8b6SQiang Yu err = drm_gem_lock_reservations((struct drm_gem_object **)bos,
338e305b8b6SQiang Yu submit->nr_bos, &ctx);
339a1d2a633SQiang Yu if (err)
340a1d2a633SQiang Yu goto err_out0;
341a1d2a633SQiang Yu
342a1d2a633SQiang Yu err = lima_sched_task_init(
343a1d2a633SQiang Yu submit->task, submit->ctx->context + submit->pipe,
344a1d2a633SQiang Yu bos, submit->nr_bos, vm);
345a1d2a633SQiang Yu if (err)
346a1d2a633SQiang Yu goto err_out1;
347a1d2a633SQiang Yu
348a1d2a633SQiang Yu err = lima_gem_add_deps(file, submit);
349a1d2a633SQiang Yu if (err)
350a1d2a633SQiang Yu goto err_out2;
351a1d2a633SQiang Yu
352a1d2a633SQiang Yu for (i = 0; i < submit->nr_bos; i++) {
353a1d2a633SQiang Yu err = lima_gem_sync_bo(
354a1d2a633SQiang Yu submit->task, bos[i],
355a1d2a633SQiang Yu submit->bos[i].flags & LIMA_SUBMIT_BO_WRITE,
356a1d2a633SQiang Yu submit->flags & LIMA_SUBMIT_FLAG_EXPLICIT_FENCE);
357a1d2a633SQiang Yu if (err)
358a1d2a633SQiang Yu goto err_out2;
359a1d2a633SQiang Yu }
360a1d2a633SQiang Yu
3610e10e9a1SDaniel Vetter fence = lima_sched_context_queue_task(submit->task);
362a1d2a633SQiang Yu
363a1d2a633SQiang Yu for (i = 0; i < submit->nr_bos; i++) {
36473511edfSChristian König dma_resv_add_fence(lima_bo_resv(bos[i]), fence,
36573511edfSChristian König submit->bos[i].flags & LIMA_SUBMIT_BO_WRITE ?
36673511edfSChristian König DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ);
367a1d2a633SQiang Yu }
368a1d2a633SQiang Yu
369e305b8b6SQiang Yu drm_gem_unlock_reservations((struct drm_gem_object **)bos,
370e305b8b6SQiang Yu submit->nr_bos, &ctx);
371a1d2a633SQiang Yu
372a1d2a633SQiang Yu for (i = 0; i < submit->nr_bos; i++)
3734ded8550SEmil Velikov drm_gem_object_put(&bos[i]->base.base);
374a1d2a633SQiang Yu
375a1d2a633SQiang Yu if (out_sync) {
376a1d2a633SQiang Yu drm_syncobj_replace_fence(out_sync, fence);
377a1d2a633SQiang Yu drm_syncobj_put(out_sync);
378a1d2a633SQiang Yu }
379a1d2a633SQiang Yu
380a1d2a633SQiang Yu dma_fence_put(fence);
381a1d2a633SQiang Yu
382a1d2a633SQiang Yu return 0;
383a1d2a633SQiang Yu
384a1d2a633SQiang Yu err_out2:
385a1d2a633SQiang Yu lima_sched_task_fini(submit->task);
386a1d2a633SQiang Yu err_out1:
387e305b8b6SQiang Yu drm_gem_unlock_reservations((struct drm_gem_object **)bos,
388e305b8b6SQiang Yu submit->nr_bos, &ctx);
389a1d2a633SQiang Yu err_out0:
390a1d2a633SQiang Yu for (i = 0; i < submit->nr_bos; i++) {
391a1d2a633SQiang Yu if (!bos[i])
392a1d2a633SQiang Yu break;
393a1d2a633SQiang Yu lima_vm_bo_del(vm, bos[i]);
3944ded8550SEmil Velikov drm_gem_object_put(&bos[i]->base.base);
395a1d2a633SQiang Yu }
396a1d2a633SQiang Yu if (out_sync)
397a1d2a633SQiang Yu drm_syncobj_put(out_sync);
398a1d2a633SQiang Yu return err;
399a1d2a633SQiang Yu }
400a1d2a633SQiang Yu
lima_gem_wait(struct drm_file * file,u32 handle,u32 op,s64 timeout_ns)401a1d2a633SQiang Yu int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, s64 timeout_ns)
402a1d2a633SQiang Yu {
403a1d2a633SQiang Yu bool write = op & LIMA_GEM_WAIT_WRITE;
404a1d2a633SQiang Yu long ret, timeout;
405a1d2a633SQiang Yu
406a1d2a633SQiang Yu if (!op)
407a1d2a633SQiang Yu return 0;
408a1d2a633SQiang Yu
409a1d2a633SQiang Yu timeout = drm_timeout_abs_to_jiffies(timeout_ns);
410a1d2a633SQiang Yu
41152791eeeSChristian König ret = drm_gem_dma_resv_wait(file, handle, write, timeout);
41221670bd7SVasily Khoruzhick if (ret == -ETIME)
413a1d2a633SQiang Yu ret = timeout ? -ETIMEDOUT : -EBUSY;
414a1d2a633SQiang Yu
415a1d2a633SQiang Yu return ret;
416a1d2a633SQiang Yu }
417