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 "hmm.h" 16 #include "ia_css_rmgr.h" 17 18 #include <type_support.h> 19 #include <assert_support.h> 20 #include <platform_support.h> /* memset */ 21 #include <ia_css_debug.h> 22 23 /* 24 * @brief VBUF resource handles 25 */ 26 #define NUM_HANDLES 1000 27 static struct ia_css_rmgr_vbuf_handle handle_table[NUM_HANDLES]; 28 29 /* 30 * @brief VBUF resource pool - refpool 31 */ 32 static 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 static 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 static 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 85 if ((!handle) || (!*handle)) { 86 IA_CSS_LOG("Invalid inputs"); 87 return; 88 } 89 /* new vbuf to count on */ 90 if ((*handle)->count == 0) { 91 h = *handle; 92 *handle = NULL; 93 for (i = 0; i < NUM_HANDLES; i++) { 94 if (handle_table[i].count == 0) { 95 *handle = &handle_table[i]; 96 break; 97 } 98 } 99 /* if the loop dus not break and *handle == NULL 100 this is an error handle and report it. 101 */ 102 if (!*handle) { 103 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 104 "ia_css_i_host_refcount_retain_vbuf() failed to find empty slot!\n"); 105 return; 106 } 107 (*handle)->vptr = h->vptr; 108 (*handle)->size = h->size; 109 } 110 (*handle)->count++; 111 } 112 113 /* 114 * @brief Release the reference count for a handle (host, vbuf) 115 * 116 * @param handle The pointer to the handle 117 */ 118 void ia_css_rmgr_refcount_release_vbuf(struct ia_css_rmgr_vbuf_handle **handle) 119 { 120 if ((!handle) || ((*handle) == NULL) || (((*handle)->count) == 0)) { 121 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 122 "ia_css_rmgr_refcount_release_vbuf() invalid arguments!\n"); 123 return; 124 } 125 /* decrease reference count */ 126 (*handle)->count--; 127 /* remove from admin */ 128 if ((*handle)->count == 0) { 129 (*handle)->vptr = 0x0; 130 (*handle)->size = 0; 131 *handle = NULL; 132 } 133 } 134 135 /* 136 * @brief Initialize the resource pool (host, vbuf) 137 * 138 * @param pool The pointer to the pool 139 */ 140 enum ia_css_err ia_css_rmgr_init_vbuf(struct ia_css_rmgr_vbuf_pool *pool) 141 { 142 enum ia_css_err err = IA_CSS_SUCCESS; 143 size_t bytes_needed; 144 145 rmgr_refcount_init_vbuf(); 146 assert(pool); 147 if (!pool) 148 return IA_CSS_ERR_INVALID_ARGUMENTS; 149 /* initialize the recycle pool if used */ 150 if (pool->recycle && pool->size) { 151 /* allocate memory for storing the handles */ 152 bytes_needed = 153 sizeof(void *) * 154 pool->size; 155 pool->handles = kvmalloc(bytes_needed, GFP_KERNEL); 156 if (pool->handles) 157 memset(pool->handles, 0, bytes_needed); 158 else 159 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 160 } else { 161 /* just in case, set the size to 0 */ 162 pool->size = 0; 163 pool->handles = NULL; 164 } 165 return err; 166 } 167 168 /* 169 * @brief Uninitialize the resource pool (host, vbuf) 170 * 171 * @param pool The pointer to the pool 172 */ 173 void ia_css_rmgr_uninit_vbuf(struct ia_css_rmgr_vbuf_pool *pool) 174 { 175 u32 i; 176 177 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_rmgr_uninit_vbuf()\n"); 178 if (!pool) { 179 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 180 "ia_css_rmgr_uninit_vbuf(): NULL argument\n"); 181 return; 182 } 183 if (pool->handles) { 184 /* free the hmm buffers */ 185 for (i = 0; i < pool->size; i++) { 186 if (pool->handles[i]) { 187 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, 188 " freeing/releasing %x (count=%d)\n", 189 pool->handles[i]->vptr, 190 pool->handles[i]->count); 191 /* free memory */ 192 hmm_free(pool->handles[i]->vptr); 193 /* remove from refcount admin */ 194 ia_css_rmgr_refcount_release_vbuf( 195 &pool->handles[i]); 196 } 197 } 198 /* now free the pool handles list */ 199 kvfree(pool->handles); 200 pool->handles = NULL; 201 } 202 } 203 204 /* 205 * @brief Push a handle to the pool 206 * 207 * @param pool The pointer to the pool 208 * @param handle The pointer to the handle 209 */ 210 static 211 void rmgr_push_handle(struct ia_css_rmgr_vbuf_pool *pool, 212 struct ia_css_rmgr_vbuf_handle **handle) 213 { 214 u32 i; 215 bool succes = false; 216 217 assert(pool); 218 assert(pool->recycle); 219 assert(pool->handles); 220 assert(handle); 221 for (i = 0; i < pool->size; i++) { 222 if (!pool->handles[i]) { 223 ia_css_rmgr_refcount_retain_vbuf(handle); 224 pool->handles[i] = *handle; 225 succes = true; 226 break; 227 } 228 } 229 assert(succes); 230 } 231 232 /* 233 * @brief Pop a handle from the pool 234 * 235 * @param pool The pointer to the pool 236 * @param handle The pointer to the handle 237 */ 238 static 239 void rmgr_pop_handle(struct ia_css_rmgr_vbuf_pool *pool, 240 struct ia_css_rmgr_vbuf_handle **handle) 241 { 242 u32 i; 243 bool succes = false; 244 245 assert(pool); 246 assert(pool->recycle); 247 assert(pool->handles); 248 assert(handle); 249 assert(*handle); 250 for (i = 0; i < pool->size; i++) { 251 if ((pool->handles[i]) && 252 (pool->handles[i]->size == (*handle)->size)) { 253 *handle = pool->handles[i]; 254 pool->handles[i] = NULL; 255 /* dont release, we are returning it... 256 ia_css_rmgr_refcount_release_vbuf(handle); */ 257 succes = true; 258 break; 259 } 260 } 261 } 262 263 /* 264 * @brief Acquire a handle from the pool (host, vbuf) 265 * 266 * @param pool The pointer to the pool 267 * @param handle The pointer to the handle 268 */ 269 void ia_css_rmgr_acq_vbuf(struct ia_css_rmgr_vbuf_pool *pool, 270 struct ia_css_rmgr_vbuf_handle **handle) 271 { 272 struct ia_css_rmgr_vbuf_handle h; 273 274 if ((!pool) || (!handle) || (!*handle)) { 275 IA_CSS_LOG("Invalid inputs"); 276 return; 277 } 278 279 if (pool->copy_on_write) { 280 /* only one reference, reuse (no new retain) */ 281 if ((*handle)->count == 1) 282 return; 283 /* more than one reference, release current buffer */ 284 if ((*handle)->count > 1) { 285 /* store current values */ 286 h.vptr = 0x0; 287 h.size = (*handle)->size; 288 /* release ref to current buffer */ 289 ia_css_rmgr_refcount_release_vbuf(handle); 290 *handle = &h; 291 } 292 /* get new buffer for needed size */ 293 if ((*handle)->vptr == 0x0) { 294 if (pool->recycle) { 295 /* try and pop from pool */ 296 rmgr_pop_handle(pool, handle); 297 } 298 if ((*handle)->vptr == 0x0) { 299 /* we need to allocate */ 300 (*handle)->vptr = hmm_alloc((*handle)->size, HMM_BO_PRIVATE, 0, NULL, 0); 301 } else { 302 /* we popped a buffer */ 303 return; 304 } 305 } 306 } 307 /* Note that handle will change to an internally maintained one */ 308 ia_css_rmgr_refcount_retain_vbuf(handle); 309 } 310 311 /* 312 * @brief Release a handle to the pool (host, vbuf) 313 * 314 * @param pool The pointer to the pool 315 * @param handle The pointer to the handle 316 */ 317 void ia_css_rmgr_rel_vbuf(struct ia_css_rmgr_vbuf_pool *pool, 318 struct ia_css_rmgr_vbuf_handle **handle) 319 { 320 if ((!pool) || (!handle) || (!*handle)) { 321 IA_CSS_LOG("Invalid inputs"); 322 return; 323 } 324 /* release the handle */ 325 if ((*handle)->count == 1) { 326 if (!pool->recycle) { 327 /* non recycling pool, free mem */ 328 hmm_free((*handle)->vptr); 329 } else { 330 /* recycle to pool */ 331 rmgr_push_handle(pool, handle); 332 } 333 } 334 ia_css_rmgr_refcount_release_vbuf(handle); 335 *handle = NULL; 336 } 337