• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 #include <linux/sched.h>
20 #include <linux/slab.h>
21 #include <linux/wait.h>
22 #include <linux/spinlock.h>
23 #include "hi_osal.h"
24 #include "securec.h"
25 
26 #define FENCE_READY    1
27 #define FENCE_NOREADY  0
28 typedef struct osal_fence_ {
29     int module_id;
30     int fd;
31     wait_queue_head_t queue;
32     int condition;
33     void *private;
34     unsigned int private_size;
35     unsigned int ref;
36     struct osal_list_head node;
37 } osal_fence;
38 
39 static int g_fd_no = 0; // 临时占用,一秒1000个,可使用49天
40 
41 static DEFINE_SPINLOCK(lock);
42 static OSAL_LIST_HEAD(fence_list);
43 
44 #define FENCE_PRIVATE_MAX_SIZE 0x100
45 
osal_fence_try_del(osal_fence * fence)46 void osal_fence_try_del(osal_fence *fence)
47 {
48     if (fence->ref > 0) {
49         return;
50     }
51 
52     osal_list_del(&fence->node);
53 
54     if (fence->private != NULL) {
55         kfree(fence->private);
56         fence->private = NULL;
57     }
58 
59     kfree(fence);
60 }
61 
osal_fence_find_node(int fd,struct osal_list_head * list)62 osal_fence *osal_fence_find_node(int fd, struct osal_list_head *list)
63 {
64     osal_fence *fence_node = NULL;
65 
66     osal_list_for_each_entry(fence_node, list, node) {
67         if (fence_node->fd == fd) {
68             return fence_node;
69         }
70     }
71 
72     return NULL;
73 }
74 
osal_fence_create(unsigned int module_id,int * fd,unsigned int private_size)75 int osal_fence_create(unsigned int module_id, int *fd, unsigned int private_size)
76 {
77     osal_fence *fence_node = NULL;
78     unsigned long flags;
79     errno_t err;
80 
81     if (fd == NULL) {
82         return -1;
83     }
84 
85     if (private_size > FENCE_PRIVATE_MAX_SIZE) {
86         return -1;
87     }
88 
89     fence_node = kmalloc(sizeof(osal_fence), GFP_KERNEL);
90     if (fence_node == NULL) {
91         return -1;
92     }
93 
94     err = memset_s(fence_node, sizeof(osal_fence), 0, sizeof(osal_fence));
95     if (err != EOK) {
96         kfree(fence_node);
97         return -1;
98     }
99 
100     fence_node->private_size = private_size;
101     if (private_size != 0) {
102         fence_node->private = kmalloc(private_size, GFP_KERNEL);
103         if (fence_node->private == NULL) {
104             kfree(fence_node);
105             return -1;
106         }
107     } else {
108         fence_node->private = NULL;
109     }
110 
111     fence_node->module_id = module_id;
112     fence_node->condition = FENCE_NOREADY;
113     fence_node->ref = 1;
114 
115     init_waitqueue_head(&fence_node->queue);
116 
117     spin_lock_irqsave(&lock, flags);
118     fence_node->fd = g_fd_no;
119     g_fd_no++;
120 
121     osal_list_add_tail(&(fence_node->node), &fence_list);
122 
123     *fd = fence_node->fd;
124 
125     spin_unlock_irqrestore(&lock, flags);
126 
127     return 0;
128 }
129 EXPORT_SYMBOL(osal_fence_create);
130 
osal_fence_destroy(unsigned int module_id,int fd)131 int osal_fence_destroy(unsigned int module_id, int fd)
132 {
133     osal_fence *fence_node = NULL;
134     unsigned long flags;
135 
136     spin_lock_irqsave(&lock, flags);
137 
138     fence_node = osal_fence_find_node(fd, &fence_list);
139     if (fence_node == NULL) {
140         spin_unlock_irqrestore(&lock, flags);
141         return -1;
142     }
143 
144     fence_node->ref--;
145 
146     osal_fence_try_del(fence_node);
147 
148     spin_unlock_irqrestore(&lock, flags);
149 
150     return 0;
151 }
152 EXPORT_SYMBOL(osal_fence_destroy);
153 
osal_fence_acquire_private(unsigned int module_id,int fd,void ** private)154 int osal_fence_acquire_private(unsigned int module_id, int fd, void **private)
155 {
156     osal_fence *fence_node = NULL;
157     unsigned long flags;
158 
159     if (private == NULL) {
160         return -1;
161     }
162 
163     spin_lock_irqsave(&lock, flags);
164 
165     fence_node = osal_fence_find_node(fd, &fence_list);
166     if (fence_node == NULL) {
167         spin_unlock_irqrestore(&lock, flags);
168         return -1;
169     }
170 
171     fence_node->ref++;
172 
173     spin_unlock_irqrestore(&lock, flags);
174 
175     *private = fence_node->private;
176 
177     return 0;
178 }
179 EXPORT_SYMBOL(osal_fence_acquire_private);
180 
osal_fence_release_private(unsigned int module_id,int fd,void * private)181 int osal_fence_release_private(unsigned int module_id, int fd, void *private)
182 {
183     osal_fence *fence_node = NULL;
184     unsigned long flags;
185 
186     spin_lock_irqsave(&lock, flags);
187 
188     fence_node = osal_fence_find_node(fd, &fence_list);
189     if (fence_node == NULL) {
190         spin_unlock_irqrestore(&lock, flags);
191         return -1;
192     }
193 
194     fence_node->ref--;
195 
196     osal_fence_try_del(fence_node);
197 
198     spin_unlock_irqrestore(&lock, flags);
199 
200     return 0;
201 }
202 EXPORT_SYMBOL(osal_fence_release_private);
203 
osal_fence_signal(int fd)204 int osal_fence_signal(int fd)
205 {
206     osal_fence *fence_node = NULL;
207     unsigned long flags;
208 
209     spin_lock_irqsave(&lock, flags);
210 
211     fence_node = osal_fence_find_node(fd, &fence_list);
212     if (fence_node == NULL) {
213         spin_unlock_irqrestore(&lock, flags);
214         return -1;
215     }
216 
217     fence_node->condition = FENCE_READY;
218 
219     wake_up(&fence_node->queue);
220 
221     spin_unlock_irqrestore(&lock, flags);
222 
223     return 0;
224 }
225 EXPORT_SYMBOL(osal_fence_signal);
226 
osal_fence_wait(int fd,unsigned int ms)227 int osal_fence_wait(int fd, unsigned int ms)
228 {
229     osal_fence *fence_node = NULL;
230     long timeout;
231     unsigned long flags;
232 
233     spin_lock_irqsave(&lock, flags);
234 
235     fence_node = osal_fence_find_node(fd, &fence_list);
236     if (fence_node == NULL) {
237         spin_unlock_irqrestore(&lock, flags);
238         return -1;
239     }
240 
241     fence_node->ref++;
242 
243     spin_unlock_irqrestore(&lock, flags);
244 
245     timeout = wait_event_interruptible_timeout(fence_node->queue,
246                                                (fence_node->condition == FENCE_READY),
247                                                msecs_to_jiffies(ms));
248     spin_lock_irqsave(&lock, flags);
249     fence_node->ref--;
250     osal_fence_try_del(fence_node);
251     spin_unlock_irqrestore(&lock, flags);
252 
253     if (timeout == 0) {
254         return -1;
255     }
256 
257     return 0;
258 }
259 EXPORT_SYMBOL(osal_fence_wait);
260 
osal_fence_trywait(int fd)261 int osal_fence_trywait(int fd)
262 {
263     osal_fence *fence_node = NULL;
264     unsigned long flags;
265 
266     spin_lock_irqsave(&lock, flags);
267 
268     fence_node = osal_fence_find_node(fd, &fence_list);
269     if (fence_node == NULL) {
270         spin_unlock_irqrestore(&lock, flags);
271         return -1;
272     }
273 
274     if (fence_node->condition == FENCE_READY) {
275         spin_unlock_irqrestore(&lock, flags);
276         return 0;
277     }
278 
279     spin_unlock_irqrestore(&lock, flags);
280 
281     return -1; // not ready
282 }
283 EXPORT_SYMBOL(osal_fence_trywait);
284 
285