hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) Rockchip Electronics Co., Ltd.
 *
 * Author: Huang Lee <Putin.li@rock-chips.com>
 */
 
#define pr_fmt(fmt) "rve_fence: " fmt
 
#include <linux/dma-fence.h>
#include <linux/sync_file.h>
#include <linux/slab.h>
 
#include "rve_fence.h"
 
static const char *rve_fence_get_name(struct dma_fence *fence)
{
   return DRIVER_NAME;
}
 
static const struct dma_fence_ops rve_fence_ops = {
   .get_driver_name = rve_fence_get_name,
   .get_timeline_name = rve_fence_get_name,
};
 
struct rve_fence_context *rve_fence_context_alloc(void)
{
   struct rve_fence_context *fence_ctx = NULL;
 
   fence_ctx = kzalloc(sizeof(*fence_ctx), GFP_KERNEL);
   if (!fence_ctx)
       return ERR_PTR(-ENOMEM);
 
   fence_ctx->context = dma_fence_context_alloc(1);
   spin_lock_init(&fence_ctx->spinlock);
 
   return fence_ctx;
}
 
void rve_fence_context_free(struct rve_fence_context *fence_ctx)
{
   kfree(fence_ctx);
}
 
int rve_out_fence_alloc(struct rve_job *job)
{
   struct rve_fence_context *fence_ctx = rve_drvdata->fence_ctx;
   struct dma_fence *fence = NULL;
 
   fence = kzalloc(sizeof(*fence), GFP_KERNEL);
   if (!fence)
       return -ENOMEM;
 
   dma_fence_init(fence, &rve_fence_ops, &job->fence_lock,
            fence_ctx->context, ++fence_ctx->seqno);
 
   job->out_fence = fence;
 
   return 0;
}
 
int rve_out_fence_get_fd(struct rve_job *job)
{
   struct sync_file *sync_file = NULL;
   int fence_fd = -1;
 
   if (!job->out_fence)
       return -EINVAL;
 
   fence_fd = get_unused_fd_flags(O_CLOEXEC);
   if (fence_fd < 0)
       return fence_fd;
 
   sync_file = sync_file_create(job->out_fence);
   if (!sync_file)
       return -ENOMEM;
 
   fd_install(fence_fd, sync_file->file);
 
   return fence_fd;
}
 
struct dma_fence *rve_get_input_fence(int in_fence_fd)
{
   struct dma_fence *in_fence;
 
   in_fence = sync_file_get_fence(in_fence_fd);
 
   if (!in_fence)
       pr_err("can not get in-fence from fd\n");
 
   return in_fence;
}
 
int rve_wait_input_fence(struct dma_fence *in_fence)
{
   int ret = 0;
 
   ret = dma_fence_wait(in_fence, true);
 
   dma_fence_put(in_fence);
 
   return ret;
}
 
int rve_add_dma_fence_callback(struct rve_job *job, struct dma_fence *in_fence,
                dma_fence_func_t func)
{
   struct rve_fence_waiter *waiter;
   int ret;
 
   waiter = kmalloc(sizeof(*waiter), GFP_KERNEL);
   if (!waiter) {
       pr_err("%s: Failed to allocate waiter\n", __func__);
       return -ENOMEM;
   }
 
   waiter->job = job;
 
   ret = dma_fence_add_callback(in_fence, &waiter->waiter, func);
   if (ret == -ENOENT) {
       pr_err("'input fence' has been already signaled.");
       goto err_free_waiter;
   } else if (ret == -EINVAL) {
       pr_err
           ("%s: failed to add callback to dma_fence, err: %d\n",
            __func__, ret);
       goto err_free_waiter;
   }
 
   return ret;
 
err_free_waiter:
   kfree(waiter);
   return ret;
}