3447e16b78
drivers/media/platform/msm/cvp/hfi_response_handler.c:507:36: warning: cast to smaller integer type 'unsigned int' from 'void *' [-Wvoid-pointer-to-int-cast] inst = cvp_get_inst_from_id(core, (unsigned int)session_id); ^~~~~~~~~~~~~~~~~~~~~~~~ Change-Id: Iadb69f5ba617ce2c7410475bcd9bc024e3a40017
687 lines
19 KiB
C
687 lines
19 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/bitops.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/list.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/hash.h>
|
|
#include <linux/soc/qcom/smem.h>
|
|
#include "cvp_hfi_helper.h"
|
|
#include "cvp_hfi_io.h"
|
|
#include "msm_cvp_debug.h"
|
|
#include "cvp_hfi.h"
|
|
#include "msm_cvp_common.h"
|
|
|
|
extern struct msm_cvp_drv *cvp_driver;
|
|
|
|
static enum cvp_status hfi_map_err_status(u32 hfi_err)
|
|
{
|
|
enum cvp_status cvp_err;
|
|
|
|
switch (hfi_err) {
|
|
case HFI_ERR_NONE:
|
|
cvp_err = CVP_ERR_NONE;
|
|
break;
|
|
case HFI_ERR_SYS_FATAL:
|
|
cvp_err = CVP_ERR_HW_FATAL;
|
|
break;
|
|
case HFI_ERR_SYS_NOC_ERROR:
|
|
cvp_err = CVP_ERR_NOC_ERROR;
|
|
break;
|
|
case HFI_ERR_SYS_VERSION_MISMATCH:
|
|
case HFI_ERR_SYS_INVALID_PARAMETER:
|
|
case HFI_ERR_SYS_SESSION_ID_OUT_OF_RANGE:
|
|
case HFI_ERR_SESSION_INVALID_PARAMETER:
|
|
case HFI_ERR_SESSION_INVALID_SESSION_ID:
|
|
case HFI_ERR_SESSION_INVALID_STREAM_ID:
|
|
cvp_err = CVP_ERR_BAD_PARAM;
|
|
break;
|
|
case HFI_ERR_SYS_INSUFFICIENT_RESOURCES:
|
|
case HFI_ERR_SYS_UNSUPPORTED_DOMAIN:
|
|
case HFI_ERR_SYS_UNSUPPORTED_CODEC:
|
|
case HFI_ERR_SESSION_UNSUPPORTED_PROPERTY:
|
|
case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
|
|
case HFI_ERR_SESSION_INSUFFICIENT_RESOURCES:
|
|
case HFI_ERR_SESSION_UNSUPPORTED_STREAM:
|
|
cvp_err = CVP_ERR_NOT_SUPPORTED;
|
|
break;
|
|
case HFI_ERR_SYS_MAX_SESSIONS_REACHED:
|
|
cvp_err = CVP_ERR_MAX_CLIENTS;
|
|
break;
|
|
case HFI_ERR_SYS_SESSION_IN_USE:
|
|
cvp_err = CVP_ERR_CLIENT_PRESENT;
|
|
break;
|
|
case HFI_ERR_SESSION_FATAL:
|
|
cvp_err = CVP_ERR_CLIENT_FATAL;
|
|
break;
|
|
case HFI_ERR_SESSION_BAD_POINTER:
|
|
cvp_err = CVP_ERR_BAD_PARAM;
|
|
break;
|
|
case HFI_ERR_SESSION_INCORRECT_STATE_OPERATION:
|
|
cvp_err = CVP_ERR_BAD_STATE;
|
|
break;
|
|
default:
|
|
cvp_err = CVP_ERR_FAIL;
|
|
break;
|
|
}
|
|
return cvp_err;
|
|
}
|
|
|
|
static int hfi_process_sys_error(u32 device_id,
|
|
struct cvp_hfi_msg_event_notify_packet *pkt,
|
|
struct msm_cvp_cb_info *info)
|
|
{
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->event_data1);
|
|
|
|
info->response_type = HAL_SYS_ERROR;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_error(u32 device_id,
|
|
struct cvp_hfi_msg_event_notify_packet *pkt,
|
|
struct msm_cvp_cb_info *info)
|
|
{
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->event_data1);
|
|
info->response.cmd = cmd_done;
|
|
dprintk(CVP_INFO, "Received: SESSION_ERROR with event id : %#x %#x\n",
|
|
pkt->event_data1, pkt->event_data2);
|
|
switch (pkt->event_data1) {
|
|
/* Ignore below errors */
|
|
case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
|
|
case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
|
|
dprintk(CVP_INFO, "Non Fatal: HFI_EVENT_SESSION_ERROR\n");
|
|
info->response_type = HAL_RESPONSE_UNUSED;
|
|
break;
|
|
default:
|
|
dprintk(CVP_ERR,
|
|
"%s: session %x data1 %#x, data2 %#x\n", __func__,
|
|
pkt->session_id, pkt->event_data1, pkt->event_data2);
|
|
info->response_type = HAL_RESPONSE_UNUSED;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_event_notify(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_event_notify_packet *pkt =
|
|
(struct cvp_hfi_msg_event_notify_packet *)hdr;
|
|
|
|
dprintk(CVP_HFI, "Received: EVENT_NOTIFY\n");
|
|
|
|
if (pkt->size < sizeof(struct cvp_hfi_msg_event_notify_packet)) {
|
|
dprintk(CVP_ERR, "Invalid Params\n");
|
|
return -E2BIG;
|
|
}
|
|
|
|
switch (pkt->event_id) {
|
|
case HFI_EVENT_SYS_ERROR:
|
|
dprintk(CVP_ERR, "HFI_EVENT_SYS_ERROR: %d, %#x\n",
|
|
pkt->event_data1, pkt->event_data2);
|
|
return hfi_process_sys_error(device_id, pkt, info);
|
|
|
|
case HFI_EVENT_SESSION_ERROR:
|
|
dprintk(CVP_INFO, "HFI_EVENT_SESSION_ERROR[%#x]\n",
|
|
pkt->session_id);
|
|
return hfi_process_session_error(device_id, pkt, info);
|
|
|
|
default:
|
|
*info = (struct msm_cvp_cb_info) {
|
|
.response_type = HAL_RESPONSE_UNUSED,
|
|
};
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int hfi_process_sys_init_done(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_sys_init_done_packet *pkt =
|
|
(struct cvp_hfi_msg_sys_init_done_packet *)hdr;
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
enum cvp_status status = CVP_ERR_NONE;
|
|
|
|
dprintk(CVP_CORE, "RECEIVED: SYS_INIT_DONE\n");
|
|
if (sizeof(struct cvp_hfi_msg_sys_init_done_packet) > pkt->size) {
|
|
dprintk(CVP_ERR, "%s: bad_pkt_size: %d\n", __func__,
|
|
pkt->size);
|
|
return -E2BIG;
|
|
}
|
|
if (!pkt->num_properties) {
|
|
dprintk(CVP_CORE,
|
|
"hal_process_sys_init_done: no_properties\n");
|
|
goto err_no_prop;
|
|
}
|
|
|
|
status = hfi_map_err_status(pkt->error_type);
|
|
if (status) {
|
|
dprintk(CVP_ERR, "%s: status %#x\n",
|
|
__func__, status);
|
|
goto err_no_prop;
|
|
}
|
|
|
|
err_no_prop:
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = NULL;
|
|
cmd_done.status = (u32)status;
|
|
cmd_done.size = sizeof(struct cvp_hal_sys_init_done);
|
|
|
|
info->response_type = HAL_SYS_INIT_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
enum cvp_status cvp_hfi_process_sys_init_done_prop_read(
|
|
struct cvp_hfi_msg_sys_init_done_packet *pkt,
|
|
struct cvp_hal_sys_init_done *sys_init_done)
|
|
{
|
|
enum cvp_status status = CVP_ERR_NONE;
|
|
u32 rem_bytes, num_properties;
|
|
u8 *data_ptr;
|
|
|
|
if (!pkt || !sys_init_done) {
|
|
dprintk(CVP_ERR,
|
|
"hfi_msg_sys_init_done: Invalid input\n");
|
|
return CVP_ERR_FAIL;
|
|
}
|
|
|
|
rem_bytes = pkt->size - sizeof(struct
|
|
cvp_hfi_msg_sys_init_done_packet) + sizeof(u32);
|
|
|
|
if (!rem_bytes) {
|
|
dprintk(CVP_ERR,
|
|
"hfi_msg_sys_init_done: missing_prop_info\n");
|
|
return CVP_ERR_FAIL;
|
|
}
|
|
|
|
status = hfi_map_err_status(pkt->error_type);
|
|
if (status) {
|
|
dprintk(CVP_ERR, "%s: status %#x\n", __func__, status);
|
|
return status;
|
|
}
|
|
|
|
data_ptr = (u8 *) &pkt->rg_property_data[0];
|
|
num_properties = pkt->num_properties;
|
|
dprintk(CVP_HFI,
|
|
"%s: data_start %pK, num_properties %#x\n",
|
|
__func__, data_ptr, num_properties);
|
|
|
|
sys_init_done->capabilities = NULL;
|
|
return status;
|
|
}
|
|
|
|
static int hfi_process_session_init_done(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_sys_session_init_done_packet *pkt =
|
|
(struct cvp_hfi_msg_sys_session_init_done_packet *)hdr;
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
struct cvp_hal_session_init_done session_init_done = { {0} };
|
|
|
|
dprintk(CVP_SESS, "RECEIVED: SESSION_INIT_DONE[%x]\n", pkt->session_id);
|
|
|
|
if (sizeof(struct cvp_hfi_msg_sys_session_init_done_packet)
|
|
> pkt->size) {
|
|
dprintk(CVP_ERR,
|
|
"hal_process_session_init_done: bad_pkt_size\n");
|
|
return -E2BIG;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.data.session_init_done = session_init_done;
|
|
cmd_done.size = sizeof(struct cvp_hal_session_init_done);
|
|
|
|
info->response_type = HAL_SESSION_INIT_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
static int hfi_process_session_end_done(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_sys_session_end_done_packet *pkt =
|
|
(struct cvp_hfi_msg_sys_session_end_done_packet *)hdr;
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(CVP_SESS, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct cvp_hfi_msg_sys_session_end_done_packet)) {
|
|
dprintk(CVP_ERR, "%s: bad packet/packet size\n", __func__);
|
|
return -E2BIG;
|
|
}
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_END_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_abort_done(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_sys_session_abort_done_packet *pkt =
|
|
(struct cvp_hfi_msg_sys_session_abort_done_packet *)hdr;
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(CVP_SESS, "RECEIVED: SESSION_ABORT_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
if (!pkt || pkt->size !=
|
|
sizeof(struct cvp_hfi_msg_sys_session_abort_done_packet)) {
|
|
dprintk(CVP_ERR, "%s: bad packet/packet size: %d\n",
|
|
__func__, pkt ? pkt->size : 0);
|
|
return -E2BIG;
|
|
}
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_ABORT_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_set_buf_done(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_session_hdr *pkt =
|
|
(struct cvp_hfi_msg_session_hdr *)hdr;
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
unsigned int pkt_size = get_msg_size(pkt);
|
|
|
|
if (!pkt || pkt->size < pkt_size) {
|
|
dprintk(CVP_ERR, "bad packet/packet size %d\n",
|
|
pkt ? pkt->size : 0);
|
|
return -E2BIG;
|
|
}
|
|
dprintk(CVP_SESS, "RECEIVED:CVP_SET_BUFFER_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
|
|
cmd_done.status = hfi_map_err_status(get_msg_errorcode(pkt));
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_SET_BUFFER_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_flush_done(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_sys_session_flush_done_packet *pkt =
|
|
(struct cvp_hfi_msg_sys_session_flush_done_packet *)hdr;
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
|
|
dprintk(CVP_SESS, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
if (!pkt || pkt->size <
|
|
sizeof(struct cvp_hfi_msg_sys_session_flush_done_packet)) {
|
|
dprintk(CVP_ERR, "%s: bad packet/packet size: %d\n",
|
|
__func__, pkt ? pkt->size : 0);
|
|
return -E2BIG;
|
|
}
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
|
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_FLUSH_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_rel_buf_done(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_session_hdr *pkt =
|
|
(struct cvp_hfi_msg_session_hdr *)hdr;
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
unsigned int pkt_size = get_msg_size(pkt);
|
|
|
|
if (!pkt || pkt->size < pkt_size) {
|
|
dprintk(CVP_ERR, "bad packet/packet size %d\n",
|
|
pkt ? pkt->size : 0);
|
|
return -E2BIG;
|
|
}
|
|
dprintk(CVP_SESS, "RECEIVED:CVP_RELEASE_BUFFER_DONE[%#x]\n",
|
|
pkt->session_id);
|
|
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
|
|
cmd_done.status = hfi_map_err_status(get_msg_errorcode(pkt));
|
|
cmd_done.size = 0;
|
|
|
|
info->response_type = HAL_SESSION_RELEASE_BUFFER_DONE;
|
|
info->response.cmd = cmd_done;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int hfi_process_session_cvp_operation_config(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_session_op_cfg_packet *pkt =
|
|
(struct cvp_hfi_msg_session_op_cfg_packet *)hdr;
|
|
struct cvp_hfi_msg_session_hdr *lhdr =
|
|
(struct cvp_hfi_msg_session_hdr *)hdr;
|
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
|
int signal;
|
|
unsigned int conf_id, session_id, error_type;
|
|
|
|
if (!pkt) {
|
|
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
|
return -EINVAL;
|
|
} else if (pkt->size < get_msg_size(lhdr)) {
|
|
dprintk(CVP_ERR,
|
|
"%s: bad_pkt_size\n", __func__);
|
|
return -E2BIG;
|
|
}
|
|
|
|
get_msg_opconfigs(pkt, &session_id, &error_type, &conf_id);
|
|
cmd_done.device_id = device_id;
|
|
cmd_done.session_id = (void *)(uintptr_t)session_id;
|
|
cmd_done.status = hfi_map_err_status(error_type);
|
|
cmd_done.size = 0;
|
|
|
|
dprintk(CVP_HFI,
|
|
"%s: device_id=%d status=%d, sessionid=%pK config=%x\n",
|
|
__func__, device_id, cmd_done.status,
|
|
cmd_done.session_id, pkt->op_conf_id);
|
|
|
|
if (pkt->packet_type == HFI_MSG_SESSION_CVP_SET_PERSIST_BUFFERS)
|
|
signal = get_signal_from_pkt_type(
|
|
HFI_CMD_SESSION_CVP_SET_PERSIST_BUFFERS);
|
|
else if (pkt->packet_type ==
|
|
HFI_MSG_SESSION_CVP_RELEASE_PERSIST_BUFFERS)
|
|
signal = get_signal_from_pkt_type(
|
|
HFI_CMD_SESSION_CVP_RELEASE_PERSIST_BUFFERS);
|
|
else if (pkt->packet_type == HFI_MSG_SESSION_CVP_SET_MODEL_BUFFERS)
|
|
signal = get_signal_from_pkt_type(
|
|
HFI_CMD_SESSION_CVP_SET_MODEL_BUFFERS);
|
|
else if (pkt->packet_type == HFI_MSG_SESSION_CVP_SET_FD_CHROMA_BUFFER)
|
|
signal = get_signal_from_pkt_type(
|
|
HFI_CMD_SESSION_CVP_SET_FD_CHROMA_BUFFER);
|
|
else if (pkt->packet_type == HFI_MSG_SESSION_CVP_RELEASE_FD_CHROMA_BUFFER)
|
|
signal = get_signal_from_pkt_type(
|
|
HFI_CMD_SESSION_CVP_RELEASE_FD_CHROMA_BUFFER);
|
|
else
|
|
signal = get_signal_from_pkt_type(conf_id);
|
|
|
|
if (signal < 0) {
|
|
dprintk(CVP_ERR, "%s Invalid op config id\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
info->response_type = signal;
|
|
info->response.cmd = cmd_done;
|
|
return 0;
|
|
}
|
|
|
|
static struct msm_cvp_inst *cvp_get_inst_from_id(struct msm_cvp_core *core,
|
|
unsigned int session_id)
|
|
{
|
|
struct msm_cvp_inst *inst = NULL;
|
|
bool match = false;
|
|
int count = 0;
|
|
|
|
if (!core || !session_id)
|
|
return NULL;
|
|
|
|
retry:
|
|
if (mutex_trylock(&core->lock)) {
|
|
list_for_each_entry(inst, &core->instances, list) {
|
|
if (hash32_ptr(inst->session) == session_id) {
|
|
match = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
inst = match ? inst : NULL;
|
|
mutex_unlock(&core->lock);
|
|
} else {
|
|
if (core->state == CVP_CORE_UNINIT)
|
|
return NULL;
|
|
usleep_range(100, 200);
|
|
count++;
|
|
if (count < 1000)
|
|
goto retry;
|
|
else
|
|
dprintk(CVP_ERR, "timeout locking core mutex\n");
|
|
}
|
|
|
|
return inst;
|
|
|
|
}
|
|
|
|
static int hfi_process_session_cvp_msg(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_session_hdr *pkt =
|
|
(struct cvp_hfi_msg_session_hdr *)hdr;
|
|
struct cvp_session_msg *sess_msg;
|
|
struct msm_cvp_inst *inst = NULL;
|
|
struct msm_cvp_core *core;
|
|
void *session_id;
|
|
struct cvp_session_queue *sq;
|
|
|
|
if (!pkt) {
|
|
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
|
return -EINVAL;
|
|
} else if (pkt->size > MAX_HFI_PKT_SIZE * sizeof(unsigned int)) {
|
|
dprintk(CVP_ERR, "%s: bad_pkt_size %d\n", __func__, pkt->size);
|
|
return -E2BIG;
|
|
}
|
|
session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
|
|
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
|
inst = cvp_get_inst_from_id(core, (uintptr_t)session_id);
|
|
|
|
if (!inst) {
|
|
dprintk(CVP_ERR, "%s: invalid session\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (pkt->client_data.kdata & FENCE_BIT)
|
|
sq = &inst->session_queue_fence;
|
|
else
|
|
sq = &inst->session_queue;
|
|
|
|
sess_msg = kmem_cache_alloc(cvp_driver->msg_cache, GFP_KERNEL);
|
|
if (sess_msg == NULL) {
|
|
dprintk(CVP_ERR, "%s runs out msg cache memory\n", __func__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
memcpy(&sess_msg->pkt, pkt, get_msg_size(pkt));
|
|
|
|
dprintk(CVP_HFI,
|
|
"%s: Received msg %x cmd_done.status=%d sessionid=%x\n",
|
|
__func__, pkt->packet_type,
|
|
hfi_map_err_status(get_msg_errorcode(pkt)), session_id);
|
|
|
|
spin_lock(&sq->lock);
|
|
if (sq->msg_count >= MAX_NUM_MSGS_PER_SESSION) {
|
|
dprintk(CVP_ERR, "Reached session queue size limit\n");
|
|
goto error_handle_msg;
|
|
}
|
|
list_add_tail(&sess_msg->node, &sq->msgs);
|
|
sq->msg_count++;
|
|
spin_unlock(&sq->lock);
|
|
|
|
wake_up_all(&sq->wq);
|
|
|
|
info->response_type = HAL_NO_RESP;
|
|
|
|
return 0;
|
|
|
|
error_handle_msg:
|
|
spin_unlock(&sq->lock);
|
|
kmem_cache_free(cvp_driver->msg_cache, sess_msg);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
static void hfi_process_sys_get_prop_image_version(
|
|
struct cvp_hfi_msg_sys_property_info_packet *pkt)
|
|
{
|
|
int i = 0;
|
|
const u32 version_string_size = 128;
|
|
u8 *str_image_version;
|
|
int req_bytes;
|
|
|
|
req_bytes = pkt->size - sizeof(*pkt);
|
|
if (req_bytes < version_string_size ||
|
|
!pkt->rg_property_data[1] ||
|
|
pkt->num_properties > 1) {
|
|
dprintk(CVP_ERR, "%s: bad_pkt: %d\n", __func__, req_bytes);
|
|
return;
|
|
}
|
|
str_image_version = (u8 *)&pkt->rg_property_data[1];
|
|
/*
|
|
* The version string returned by firmware includes null
|
|
* characters at the start and in between. Replace the null
|
|
* characters with space, to print the version info.
|
|
*/
|
|
for (i = 0; i < version_string_size; i++) {
|
|
if (str_image_version[i] != '\0')
|
|
cvp_driver->fw_version[i] = str_image_version[i];
|
|
else
|
|
cvp_driver->fw_version[i] = ' ';
|
|
}
|
|
cvp_driver->fw_version[i - 1] = '\0';
|
|
dprintk(CVP_HFI, "F/W version: %s\n", cvp_driver->fw_version);
|
|
}
|
|
|
|
static int hfi_process_sys_property_info(u32 device_id,
|
|
void *hdr, struct msm_cvp_cb_info *info)
|
|
{
|
|
struct cvp_hfi_msg_sys_property_info_packet *pkt =
|
|
(struct cvp_hfi_msg_sys_property_info_packet *)hdr;
|
|
if (!pkt) {
|
|
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
|
return -EINVAL;
|
|
} else if (pkt->size > sizeof(*pkt)) {
|
|
dprintk(CVP_ERR,
|
|
"%s: bad_pkt_size %d\n", __func__, pkt->size);
|
|
return -E2BIG;
|
|
} else if (!pkt->num_properties) {
|
|
dprintk(CVP_WARN,
|
|
"%s: no_properties\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (pkt->rg_property_data[0]) {
|
|
case HFI_PROPERTY_SYS_IMAGE_VERSION:
|
|
hfi_process_sys_get_prop_image_version(pkt);
|
|
|
|
*info = (struct msm_cvp_cb_info) {
|
|
.response_type = HAL_RESPONSE_UNUSED,
|
|
};
|
|
return 0;
|
|
default:
|
|
dprintk(CVP_WARN,
|
|
"%s: unknown_prop_id: %x\n",
|
|
__func__, pkt->rg_property_data[0]);
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
}
|
|
|
|
int cvp_hfi_process_msg_packet(u32 device_id, void *hdr,
|
|
struct msm_cvp_cb_info *info)
|
|
{
|
|
typedef int (*pkt_func_def)(u32, void *, struct msm_cvp_cb_info *info);
|
|
pkt_func_def pkt_func = NULL;
|
|
struct cvp_hal_msg_pkt_hdr *msg_hdr = (struct cvp_hal_msg_pkt_hdr *)hdr;
|
|
|
|
if (!info || !msg_hdr || msg_hdr->size < CVP_IFACEQ_MIN_PKT_SIZE) {
|
|
dprintk(CVP_ERR, "%s: bad packet/packet size\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
dprintk(CVP_HFI, "Received HFI MSG with type %#x\n", msg_hdr->packet);
|
|
switch (msg_hdr->packet) {
|
|
case HFI_MSG_EVENT_NOTIFY:
|
|
pkt_func = (pkt_func_def)hfi_process_event_notify;
|
|
break;
|
|
case HFI_MSG_SYS_INIT_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_sys_init_done;
|
|
break;
|
|
case HFI_MSG_SYS_SESSION_INIT_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_init_done;
|
|
break;
|
|
case HFI_MSG_SYS_PROPERTY_INFO:
|
|
pkt_func = (pkt_func_def)hfi_process_sys_property_info;
|
|
break;
|
|
case HFI_MSG_SYS_SESSION_END_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_end_done;
|
|
break;
|
|
case HFI_MSG_SESSION_CVP_SET_BUFFERS:
|
|
pkt_func = (pkt_func_def) hfi_process_session_set_buf_done;
|
|
break;
|
|
case HFI_MSG_SESSION_CVP_RELEASE_BUFFERS:
|
|
pkt_func = (pkt_func_def)hfi_process_session_rel_buf_done;
|
|
break;
|
|
case HFI_MSG_SYS_SESSION_ABORT_DONE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_abort_done;
|
|
break;
|
|
case HFI_MSG_SESSION_CVP_FLUSH:
|
|
case HFI_MSG_SESSION_CVP_FLUSH_DEPRECATE:
|
|
pkt_func = (pkt_func_def)hfi_process_session_flush_done;
|
|
break;
|
|
case HFI_MSG_SESSION_CVP_OPERATION_CONFIG:
|
|
case HFI_MSG_SESSION_CVP_SET_PERSIST_BUFFERS:
|
|
case HFI_MSG_SESSION_CVP_RELEASE_PERSIST_BUFFERS:
|
|
case HFI_MSG_SESSION_CVP_SET_FD_CHROMA_BUFFER:
|
|
case HFI_MSG_SESSION_CVP_RELEASE_FD_CHROMA_BUFFER:
|
|
case HFI_MSG_SESSION_CVP_SET_MODEL_BUFFERS:
|
|
pkt_func =
|
|
(pkt_func_def)hfi_process_session_cvp_operation_config;
|
|
break;
|
|
case HFI_MSG_SESSION_CVP_DS:
|
|
case HFI_MSG_SESSION_CVP_DFS:
|
|
case HFI_MSG_SESSION_CVP_DME:
|
|
case HFI_MSG_SESSION_CVP_FD:
|
|
pkt_func = (pkt_func_def)hfi_process_session_cvp_msg;
|
|
break;
|
|
default:
|
|
dprintk(CVP_HFI, "Use default msg handler: %#x\n",
|
|
msg_hdr->packet);
|
|
pkt_func = (pkt_func_def)hfi_process_session_cvp_msg;
|
|
break;
|
|
}
|
|
|
|
return pkt_func ?
|
|
pkt_func(device_id, hdr, info) : -ENOTSUPP;
|
|
}
|