]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/rmgr/src/rmgr_vbuf.c
staging/atomisp: Add support for the Intel IPU v2
[karo-tx-linux.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / runtime / rmgr / src / rmgr_vbuf.c
1 #ifndef ISP2401
2 /*
3  * Support for Intel Camera Imaging ISP subsystem.
4  * Copyright (c) 2015, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  */
15 #else
16 /**
17 Support for Intel Camera Imaging ISP subsystem.
18 Copyright (c) 2010 - 2015, Intel Corporation.
19
20 This program is free software; you can redistribute it and/or modify it
21 under the terms and conditions of the GNU General Public License,
22 version 2, as published by the Free Software Foundation.
23
24 This program is distributed in the hope it will be useful, but WITHOUT
25 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
27 more details.
28 */
29 #endif
30
31 #include "ia_css_rmgr.h"
32
33 #include <type_support.h>
34 #include <assert_support.h>
35 #include <platform_support.h> /* memset */
36 #include <memory_access.h>    /* mmmgr_malloc, mmmgr_free */
37 #include <ia_css_debug.h>
38
39 /**
40  * @brief VBUF resource handles
41  */
42 #define NUM_HANDLES 1000
43 struct ia_css_rmgr_vbuf_handle handle_table[NUM_HANDLES];
44
45 /**
46  * @brief VBUF resource pool - refpool
47  */
48 struct ia_css_rmgr_vbuf_pool refpool = {
49         false,                  /* copy_on_write */
50         false,                  /* recycle */
51         0,                      /* size */
52         0,                      /* index */
53         NULL,                   /* handles */
54 };
55
56 /**
57  * @brief VBUF resource pool - writepool
58  */
59 struct ia_css_rmgr_vbuf_pool writepool = {
60         true,                   /* copy_on_write */
61         false,                  /* recycle */
62         0,                      /* size */
63         0,                      /* index */
64         NULL,                   /* handles */
65 };
66
67 /**
68  * @brief VBUF resource pool - hmmbufferpool
69  */
70 struct ia_css_rmgr_vbuf_pool hmmbufferpool = {
71         true,                   /* copy_on_write */
72         true,                   /* recycle */
73         32,                     /* size */
74         0,                      /* index */
75         NULL,                   /* handles */
76 };
77
78 struct ia_css_rmgr_vbuf_pool *vbuf_ref = &refpool;
79 struct ia_css_rmgr_vbuf_pool *vbuf_write = &writepool;
80 struct ia_css_rmgr_vbuf_pool *hmm_buffer_pool = &hmmbufferpool;
81
82 /**
83  * @brief Initialize the reference count (host, vbuf)
84  */
85 static void rmgr_refcount_init_vbuf(void)
86 {
87         /* initialize the refcount table */
88         memset(&handle_table, 0, sizeof(handle_table));
89 }
90
91 /**
92  * @brief Retain the reference count for a handle (host, vbuf)
93  *
94  * @param handle        The pointer to the handle
95  */
96 void ia_css_rmgr_refcount_retain_vbuf(struct ia_css_rmgr_vbuf_handle **handle)
97 {
98         int i;
99         struct ia_css_rmgr_vbuf_handle *h;
100         if ((handle == NULL) || (*handle == NULL)) {
101                 IA_CSS_LOG("Invalid inputs");
102                 return;
103         }
104         /* new vbuf to count on */
105         if ((*handle)->count == 0) {
106                 h = *handle;
107                 *handle = NULL;
108                 for (i = 0; i < NUM_HANDLES; i++) {
109                         if (handle_table[i].count == 0) {
110                                 *handle = &handle_table[i];
111                                 break;
112                         }
113                 }
114                 /* if the loop dus not break and *handle == NULL
115                    this is an error handle and report it.
116                  */
117                 if (*handle == NULL) {
118                         ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
119                                 "ia_css_i_host_refcount_retain_vbuf() failed to find empty slot!\n");
120                         return;
121                 }
122                 (*handle)->vptr = h->vptr;
123                 (*handle)->size = h->size;
124         }
125         (*handle)->count++;
126 }
127
128 /**
129  * @brief Release the reference count for a handle (host, vbuf)
130  *
131  * @param handle        The pointer to the handle
132  */
133 void ia_css_rmgr_refcount_release_vbuf(struct ia_css_rmgr_vbuf_handle **handle)
134 {
135         if ((handle == NULL) || ((*handle) == NULL) || (((*handle)->count) == 0)) {
136                 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
137                                     "ia_css_rmgr_refcount_release_vbuf() invalid arguments!\n");
138                 return;
139         }
140         /* decrease reference count */
141         (*handle)->count--;
142         /* remove from admin */
143         if ((*handle)->count == 0) {
144                 (*handle)->vptr = 0x0;
145                 (*handle)->size = 0;
146                 *handle = NULL;
147         }
148 }
149
150 /**
151  * @brief Initialize the resource pool (host, vbuf)
152  *
153  * @param pool  The pointer to the pool
154  */
155 enum ia_css_err ia_css_rmgr_init_vbuf(struct ia_css_rmgr_vbuf_pool *pool)
156 {
157         enum ia_css_err err = IA_CSS_SUCCESS;
158         size_t bytes_needed;
159         rmgr_refcount_init_vbuf();
160         assert(pool != NULL);
161         if (pool == NULL)
162                 return IA_CSS_ERR_INVALID_ARGUMENTS;
163         /* initialize the recycle pool if used */
164         if (pool->recycle && pool->size) {
165                 /* allocate memory for storing the handles */
166                 bytes_needed =
167                     sizeof(void *) *
168                     pool->size;
169                 pool->handles = sh_css_malloc(bytes_needed);
170                 if (pool->handles != NULL)
171                         memset(pool->handles, 0, bytes_needed);
172                 else
173                         err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
174         } else {
175                 /* just in case, set the size to 0 */
176                 pool->size = 0;
177                 pool->handles = NULL;
178         }
179         return err;
180 }
181
182 /**
183  * @brief Uninitialize the resource pool (host, vbuf)
184  *
185  * @param pool  The pointer to the pool
186  */
187 void ia_css_rmgr_uninit_vbuf(struct ia_css_rmgr_vbuf_pool *pool)
188 {
189         uint32_t i;
190         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_rmgr_uninit_vbuf()\n");
191         if (pool == NULL) {
192                 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, "ia_css_rmgr_uninit_vbuf(): NULL argument\n");
193                  return;
194         }
195         if (pool->handles != NULL) {
196                 /* free the hmm buffers */
197                 for (i = 0; i < pool->size; i++) {
198                         if (pool->handles[i] != NULL) {
199                                 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
200                                       "   freeing/releasing %x (count=%d)\n",
201                                       pool->handles[i]->vptr,
202                                       pool->handles[i]->count);
203                                 /* free memory */
204                                 mmgr_free(pool->handles[i]->vptr);
205                                 /* remove from refcount admin */
206                                 ia_css_rmgr_refcount_release_vbuf(
207                                         &pool->handles[i]);
208                         }
209                 }
210                 /* now free the pool handles list */
211                 sh_css_free(pool->handles);
212                 pool->handles = NULL;
213         }
214 }
215
216 /**
217  * @brief Push a handle to the pool
218  *
219  * @param pool          The pointer to the pool
220  * @param handle        The pointer to the handle
221  */
222 static
223 void rmgr_push_handle(struct ia_css_rmgr_vbuf_pool *pool,
224                       struct ia_css_rmgr_vbuf_handle **handle)
225 {
226         uint32_t i;
227         bool succes = false;
228         assert(pool != NULL);
229         assert(pool->recycle);
230         assert(pool->handles != NULL);
231         assert(handle != NULL);
232         for (i = 0; i < pool->size; i++) {
233                 if (pool->handles[i] == NULL) {
234                         ia_css_rmgr_refcount_retain_vbuf(handle);
235                         pool->handles[i] = *handle;
236                         succes = true;
237                         break;
238                 }
239         }
240         assert(succes);
241 }
242
243 /**
244  * @brief Pop a handle from the pool
245  *
246  * @param pool          The pointer to the pool
247  * @param handle        The pointer to the handle
248  */
249 static
250 void rmgr_pop_handle(struct ia_css_rmgr_vbuf_pool *pool,
251                      struct ia_css_rmgr_vbuf_handle **handle)
252 {
253         uint32_t i;
254         bool succes = false;
255         assert(pool != NULL);
256         assert(pool->recycle);
257         assert(pool->handles != NULL);
258         assert(handle != NULL);
259         assert(*handle != NULL);
260         for (i = 0; i < pool->size; i++) {
261                 if ((pool->handles[i] != NULL) &&
262                     (pool->handles[i]->size == (*handle)->size)) {
263                         *handle = pool->handles[i];
264                         pool->handles[i] = NULL;
265                         /* dont release, we are returning it...
266                            ia_css_rmgr_refcount_release_vbuf(handle); */
267                         succes = true;
268                         break;
269                 }
270         }
271 }
272
273 /**
274  * @brief Acquire a handle from the pool (host, vbuf)
275  *
276  * @param pool          The pointer to the pool
277  * @param handle        The pointer to the handle
278  */
279 void ia_css_rmgr_acq_vbuf(struct ia_css_rmgr_vbuf_pool *pool,
280                           struct ia_css_rmgr_vbuf_handle **handle)
281 {
282 #ifdef __KLOCWORK__
283         /* KW sees the *handle = h; assignment about 20 lines down
284            and thinks that we are assigning a local to a global.
285            What it does not see is that in ia_css_i_host_rmgr_pop_handle
286            a new value is assigned to handle.
287            So this is a false positive KW issue.
288            To fix that we make the struct static for KW so it will
289            think that h remains alive; we do not want this in our
290            production code though as it breaks reentrancy of the code
291          */
292
293         static struct ia_css_rmgr_vbuf_handle h;
294 #else /* __KLOCWORK__ */
295         struct ia_css_rmgr_vbuf_handle h;
296 #endif /* __KLOCWORK__ */
297
298         if ((pool == NULL) || (handle == NULL) || (*handle == NULL)) {
299                 IA_CSS_LOG("Invalid inputs");
300                 return;
301         }
302
303         if (pool->copy_on_write) {
304                 /* only one reference, reuse (no new retain) */
305                 if ((*handle)->count == 1)
306                         return;
307                 /* more than one reference, release current buffer */
308                 if ((*handle)->count > 1) {
309                         /* store current values */
310                         h.vptr = 0x0;
311                         h.size = (*handle)->size;
312                         /* release ref to current buffer */
313                         ia_css_rmgr_refcount_release_vbuf(handle);
314                         *handle = &h;
315                 }
316                 /* get new buffer for needed size */
317                 if ((*handle)->vptr == 0x0) {
318                         if (pool->recycle) {
319                                 /* try and pop from pool */
320                                 rmgr_pop_handle(pool, handle);
321                         }
322                         if ((*handle)->vptr == 0x0) {
323                                 /* we need to allocate */
324                                 (*handle)->vptr = mmgr_malloc((*handle)->size);
325                         } else {
326                                 /* we popped a buffer */
327                                 return;
328                         }
329                 }
330         }
331         /* Note that handle will change to an internally maintained one */
332         ia_css_rmgr_refcount_retain_vbuf(handle);
333 }
334
335 /**
336  * @brief Release a handle to the pool (host, vbuf)
337  *
338  * @param pool          The pointer to the pool
339  * @param handle        The pointer to the handle
340  */
341 void ia_css_rmgr_rel_vbuf(struct ia_css_rmgr_vbuf_pool *pool,
342                           struct ia_css_rmgr_vbuf_handle **handle)
343 {
344         if ((pool == NULL) || (handle == NULL) || (*handle == NULL)) {
345                 IA_CSS_LOG("Invalid inputs");
346                 return;
347         }
348         /* release the handle */
349         if ((*handle)->count == 1) {
350                 if (!pool->recycle) {
351                         /* non recycling pool, free mem */
352                         mmgr_free((*handle)->vptr);
353                 } else {
354                         /* recycle to pool */
355                         rmgr_push_handle(pool, handle);
356                 }
357         }
358         ia_css_rmgr_refcount_release_vbuf(handle);
359         *handle = NULL;
360 }