1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) Rockchip Electronics Co.Ltd
4 * Author: Felix Zeng <felix.zeng@rock-chips.com>
5 */
6
7 #include <linux/slab.h>
8 #include <linux/file.h>
9 #include <linux/dma-fence.h>
10 #include <linux/sync_file.h>
11
12 #include "rknpu_drv.h"
13 #include "rknpu_job.h"
14
15 #include "rknpu_fence.h"
16
rknpu_fence_get_name(struct dma_fence * fence)17 static const char *rknpu_fence_get_name(struct dma_fence *fence)
18 {
19 return DRIVER_NAME;
20 }
21
22 static const struct dma_fence_ops rknpu_fence_ops = {
23 .get_driver_name = rknpu_fence_get_name,
24 .get_timeline_name = rknpu_fence_get_name,
25 };
26
rknpu_fence_context_alloc(struct rknpu_device * rknpu_dev)27 int rknpu_fence_context_alloc(struct rknpu_device *rknpu_dev)
28 {
29 struct rknpu_fence_context *fence_ctx = NULL;
30
31 fence_ctx =
32 devm_kzalloc(rknpu_dev->dev, sizeof(*fence_ctx), GFP_KERNEL);
33 if (!fence_ctx)
34 return -ENOMEM;
35
36 fence_ctx->context = dma_fence_context_alloc(1);
37 spin_lock_init(&fence_ctx->spinlock);
38
39 rknpu_dev->fence_ctx = fence_ctx;
40
41 return 0;
42 }
43
rknpu_fence_alloc(struct rknpu_job * job)44 int rknpu_fence_alloc(struct rknpu_job *job)
45 {
46 struct rknpu_fence_context *fence_ctx = job->rknpu_dev->fence_ctx;
47 struct dma_fence *fence = NULL;
48
49 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
50 if (!fence)
51 return -ENOMEM;
52
53 dma_fence_init(fence, &rknpu_fence_ops, &fence_ctx->spinlock,
54 fence_ctx->context, ++fence_ctx->seqno);
55
56 job->fence = fence;
57
58 return 0;
59 }
60
rknpu_fence_get_fd(struct rknpu_job * job)61 int rknpu_fence_get_fd(struct rknpu_job *job)
62 {
63 struct sync_file *sync_file = NULL;
64 int fence_fd = -1;
65
66 if (!job->fence)
67 return -EINVAL;
68
69 fence_fd = get_unused_fd_flags(O_CLOEXEC);
70 if (fence_fd < 0)
71 return fence_fd;
72
73 sync_file = sync_file_create(job->fence);
74 if (!sync_file)
75 return -ENOMEM;
76
77 fd_install(fence_fd, sync_file->file);
78
79 return fence_fd;
80 }
81