/** * @brief Retain the reference count for a handle (host, vbuf) * * @param handle The pointer to the handle */ void ia_css_rmgr_refcount_retain_vbuf(struct ia_css_rmgr_vbuf_handle **handle) { int i; struct ia_css_rmgr_vbuf_handle *h; if ((handle == NULL) || (*handle == NULL)) { IA_CSS_LOG("Invalid inputs"); return; } /* new vbuf to count on */ if ((*handle)->count == 0) { h = *handle; *handle = NULL; for (i = 0; i < NUM_HANDLES; i++) { if (handle_table[i].count == 0) { *handle = &handle_table[i]; break; } } /* if the loop dus not break and *handle == NULL this is an error handle and report it. */ if (*handle == NULL) { ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, "ia_css_i_host_refcount_retain_vbuf() failed to find empty slot!\n"); return; } (*handle)->vptr = h->vptr; (*handle)->size = h->size; } (*handle)->count++; }
/** * @brief Acquire a handle from the pool (host, vbuf) * * @param pool The pointer to the pool * @param handle The pointer to the handle */ void ia_css_rmgr_acq_vbuf(struct ia_css_rmgr_vbuf_pool *pool, struct ia_css_rmgr_vbuf_handle **handle) { #ifdef __KLOCWORK__ /* KW sees the *handle = h; assignment about 20 lines down and thinks that we are assigning a local to a global. What it does not see is that in ia_css_i_host_rmgr_pop_handle a new value is assigned to handle. So this is a false positive KW issue. To fix that we make the struct static for KW so it will think that h remains alive; we do not want this in our production code though as it breaks reentrancy of the code */ static struct ia_css_rmgr_vbuf_handle h; #else /* __KLOCWORK__ */ struct ia_css_rmgr_vbuf_handle h; #endif /* __KLOCWORK__ */ if ((pool == NULL) || (handle == NULL) || (*handle == NULL)) { IA_CSS_LOG("Invalid inputs"); return; } if (pool->copy_on_write) { /* only one reference, reuse (no new retain) */ if ((*handle)->count == 1) return; /* more than one reference, release current buffer */ if ((*handle)->count > 1) { /* store current values */ h.vptr = 0x0; h.size = (*handle)->size; /* release ref to current buffer */ ia_css_rmgr_refcount_release_vbuf(handle); *handle = &h; } /* get new buffer for needed size */ if ((*handle)->vptr == 0x0) { if (pool->recycle) { /* try and pop from pool */ rmgr_pop_handle(pool, handle); } if ((*handle)->vptr == 0x0) { /* we need to allocate */ (*handle)->vptr = mmgr_malloc((*handle)->size); } else { /* we popped a buffer */ return; } } } /* Note that handle will change to an internally maintained one */ ia_css_rmgr_refcount_retain_vbuf(handle); }
/** @brief destroy a pipeline * * @param[in] pipeline * @return None * */ void ia_css_pipeline_destroy(struct ia_css_pipeline *pipeline) { assert(pipeline != NULL); IA_CSS_ENTER_PRIVATE("pipeline = %p", pipeline); if (pipeline == NULL) { IA_CSS_ERROR("NULL input parameter"); IA_CSS_LEAVE_PRIVATE("void"); return; } IA_CSS_LOG("pipe_num = %d", pipeline->pipe_num); /* Free the pipeline number */ ia_css_pipeline_clean(pipeline); IA_CSS_LEAVE_PRIVATE("void"); }
/** * @brief Release a handle to the pool (host, vbuf) * * @param pool The pointer to the pool * @param handle The pointer to the handle */ void ia_css_rmgr_rel_vbuf(struct ia_css_rmgr_vbuf_pool *pool, struct ia_css_rmgr_vbuf_handle **handle) { if ((pool == NULL) || (handle == NULL) || (*handle == NULL)) { IA_CSS_LOG("Invalid inputs"); return; } /* release the handle */ if ((*handle)->count == 1) { if (!pool->recycle) { /* non recycling pool, free mem */ mmgr_free((*handle)->vptr); } else { /* recycle to pool */ rmgr_push_handle(pool, handle); } } ia_css_rmgr_refcount_release_vbuf(handle); *handle = NULL; }
/** * @brief Query the SP thread ID. * Refer to "sh_css_internal.h" for details. */ bool ia_css_pipeline_get_sp_thread_id(unsigned int key, unsigned int *val) { IA_CSS_ENTER("key=%d, val=%p", key, val); if ((val == NULL) || (key >= IA_CSS_PIPELINE_NUM_MAX) || (key >= IA_CSS_PIPE_ID_NUM)) { IA_CSS_LEAVE("return value = false"); return false; } *val = pipeline_num_to_sp_thread_map[key]; if (*val == (unsigned)PIPELINE_NUM_UNMAPPED) { IA_CSS_LOG("unmapped pipeline number"); IA_CSS_LEAVE("return value = false"); return false; } IA_CSS_LEAVE("return value = true"); return true; }
enum ia_css_err sh_css_load_firmware(const char *fw_data, unsigned int fw_size) { unsigned i; struct ia_css_fw_info *binaries; struct sh_css_fw_bi_file_h *file_header; bool valid_firmware = false; firmware_header = (struct firmware_header *)fw_data; file_header = (struct sh_css_fw_bi_file_h *)&firmware_header->file_header; binaries = (struct ia_css_fw_info *)&firmware_header->binary_header; strncpy(FW_rel_ver_name, file_header->version, min(sizeof(FW_rel_ver_name), sizeof(file_header->version)) - 1); valid_firmware = sh_css_check_firmware_version(fw_data); if (!valid_firmware) { #if (!defined HRT_CSIM && !defined HRT_RTL) IA_CSS_ERROR("CSS code version (%s) and firmware version (%s) mismatch!", file_header->version, release_version); return IA_CSS_ERR_VERSION_MISMATCH; #endif } else { IA_CSS_LOG("successfully load firmware version %s", release_version); } /* some sanity checks */ if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h)) return IA_CSS_ERR_INTERNAL_ERROR; if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h)) return IA_CSS_ERR_INTERNAL_ERROR; sh_css_num_binaries = file_header->binary_nr; /* Only allocate memory for ISP blob info */ if (sh_css_num_binaries > NUM_OF_SPS) { sh_css_blob_info = sh_css_malloc( (sh_css_num_binaries - NUM_OF_SPS) * sizeof(*sh_css_blob_info)); if (sh_css_blob_info == NULL) return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; } else { sh_css_blob_info = NULL; } fw_minibuffer = sh_css_malloc(sh_css_num_binaries * sizeof(struct fw_param)); if (fw_minibuffer == NULL) return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; memset(fw_minibuffer, 0, sh_css_num_binaries * sizeof(struct fw_param)); for (i = 0; i < sh_css_num_binaries; i++) { struct ia_css_fw_info *bi = &binaries[i]; /* note: the var below is made static as it is quite large; if it is not static it ends up on the stack which could cause issues for drivers */ static struct ia_css_blob_descr bd; enum ia_css_err err; err = sh_css_load_blob_info(fw_data, bi, &bd, i); if (err != IA_CSS_SUCCESS) return IA_CSS_ERR_INTERNAL_ERROR; if (bi->blob.offset + bi->blob.size > fw_size) return IA_CSS_ERR_INTERNAL_ERROR; if (bi->type == ia_css_sp_firmware) { if (i != SP_FIRMWARE) return IA_CSS_ERR_INTERNAL_ERROR; err = setup_sp(bi, fw_data, &sh_css_sp_fw, i); if (err != IA_CSS_SUCCESS) return err; #if defined(HAS_SEC_SP) } else if (bi->type == ia_css_sp1_firmware) { if (i != SP1_FIRMWARE) return IA_CSS_ERR_INTERNAL_ERROR; err = setup_sp(bi, fw_data, &sh_css_sp1_fw, i); if (err != IA_CSS_SUCCESS) return err; #endif /* HAS_SEC_SP */ } else { /* All subsequent binaries (i>NUM_OF_SPS) are ISP firmware */ if (i < NUM_OF_SPS) return IA_CSS_ERR_INTERNAL_ERROR; if (bi->type != ia_css_isp_firmware) return IA_CSS_ERR_INTERNAL_ERROR; if (sh_css_blob_info == NULL) /* cannot happen but KW does not see this */ return IA_CSS_ERR_INTERNAL_ERROR; sh_css_blob_info[i-NUM_OF_SPS] = bd; } } return IA_CSS_SUCCESS; }