hc
2023-08-30 862c27fc9920c83318c784bfdadf43a65df1ec8f
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
137
138
139
140
141
142
143
144
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) Rockchip Electronics Co., Ltd.
 *
 * Author: Huang Lee <Putin.li@rock-chips.com>
 */
 
#define pr_fmt(fmt) "rga_fence: " fmt
 
#include <linux/dma-fence.h>
#include <linux/sync_file.h>
#include <linux/slab.h>
 
#include "rga_drv.h"
#include "rga_fence.h"
 
static const char *rga_fence_get_name(struct dma_fence *fence)
{
   return DRIVER_NAME;
}
 
static const struct dma_fence_ops rga_fence_ops = {
   .get_driver_name = rga_fence_get_name,
   .get_timeline_name = rga_fence_get_name,
};
 
int rga_fence_context_init(struct rga_fence_context **ctx)
{
   struct rga_fence_context *fence_ctx = NULL;
 
   fence_ctx = kzalloc(sizeof(struct rga_fence_context), GFP_KERNEL);
   if (!fence_ctx) {
       pr_err("can not kzalloc for rga_fence_context!\n");
       return -ENOMEM;
   }
 
   fence_ctx->context = dma_fence_context_alloc(1);
   spin_lock_init(&fence_ctx->spinlock);
 
   *ctx = fence_ctx;
 
   return 0;
}
 
void rga_fence_context_remove(struct rga_fence_context **ctx)
{
   if (*ctx == NULL)
       return;
 
   kfree(*ctx);
   *ctx = NULL;
}
 
struct dma_fence *rga_dma_fence_alloc(void)
{
   struct rga_fence_context *fence_ctx = rga_drvdata->fence_ctx;
   struct dma_fence *fence = NULL;
 
   if (fence_ctx == NULL) {
       pr_err("fence_context is NULL!\n");
       return ERR_PTR(-EINVAL);
   }
 
   fence = kzalloc(sizeof(*fence), GFP_KERNEL);
   if (!fence)
       return ERR_PTR(-ENOMEM);
 
   dma_fence_init(fence, &rga_fence_ops, &fence_ctx->spinlock,
              fence_ctx->context, ++fence_ctx->seqno);
 
   return fence;
}
 
int rga_dma_fence_get_fd(struct dma_fence *fence)
{
   struct sync_file *sync_file = NULL;
   int fence_fd = -1;
 
   if (!fence)
       return -EINVAL;
 
   fence_fd = get_unused_fd_flags(O_CLOEXEC);
   if (fence_fd < 0)
       return fence_fd;
 
   sync_file = sync_file_create(fence);
   if (!sync_file)
       return -ENOMEM;
 
   fd_install(fence_fd, sync_file->file);
 
   return fence_fd;
}
 
struct dma_fence *rga_get_dma_fence_from_fd(int fence_fd)
{
   struct dma_fence *fence;
 
   fence = sync_file_get_fence(fence_fd);
   if (!fence)
       pr_err("can not get fence from fd\n");
 
   return fence;
}
 
int rga_dma_fence_wait(struct dma_fence *fence)
{
   int ret = 0;
 
   ret = dma_fence_wait(fence, true);
 
   dma_fence_put(fence);
 
   return ret;
}
 
int rga_dma_fence_add_callback(struct dma_fence *fence, dma_fence_func_t func, void *private)
{
   int ret;
   struct rga_fence_waiter *waiter = NULL;
 
   waiter = kmalloc(sizeof(*waiter), GFP_KERNEL);
   if (!waiter) {
       pr_err("%s: Failed to allocate waiter\n", __func__);
       return -ENOMEM;
   }
 
   waiter->private = private;
 
   ret = dma_fence_add_callback(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;
}