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