/**
 * @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);
}
Пример #3
0
/** @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;
}
Пример #5
0
/**
 * @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;
}