msm: cvp: Support CVP session flush

Added cvp session flush support for Lahaina.

Change-Id: Id1bd806abf5ab5b41ad876203016f54b58e73a82
Signed-off-by: George Shen <sqiao@codeaurora.org>
This commit is contained in:
George Shen 2020-03-04 10:37:27 -08:00
commit 04c6aea002
10 changed files with 766 additions and 122 deletions

View file

@ -2447,6 +2447,28 @@ err_send_pkt:
return rc;
}
static int iris_hfi_session_flush(void *sess)
{
struct cvp_hal_session *session = sess;
struct iris_hfi_device *device;
int rc = 0;
if (!session || !session->device) {
dprintk(CVP_ERR, "Invalid Params %s\n", __func__);
return -EINVAL;
}
device = session->device;
mutex_lock(&device->lock);
rc = __send_session_cmd(session, HFI_CMD_SESSION_CVP_FLUSH);
mutex_unlock(&device->lock);
return rc;
}
static int __check_core_registered(struct iris_hfi_device *device,
phys_addr_t fw_addr, u8 *reg_addr, u32 reg_size,
phys_addr_t irq)
@ -2673,26 +2695,20 @@ skip_power_off:
return -EAGAIN;
}
static void print_sfr_message(struct iris_hfi_device *device)
static void __process_sys_error(struct iris_hfi_device *device)
{
struct cvp_hfi_sfr_struct *vsfr = NULL;
u32 vsfr_size = 0;
void *p = NULL;
vsfr = (struct cvp_hfi_sfr_struct *)device->sfr.align_virtual_addr;
if (vsfr) {
if (vsfr->bufSize != device->sfr.mem_size) {
dprintk(CVP_ERR, "Invalid SFR buf size %d actual %d\n",
vsfr->bufSize, device->sfr.mem_size);
return;
}
vsfr_size = vsfr->bufSize - sizeof(u32);
p = memchr(vsfr->rg_data, '\0', vsfr_size);
void *p = memchr(vsfr->rg_data, '\0', vsfr->bufSize);
/*
* SFR isn't guaranteed to be NULL terminated
* since SYS_ERROR indicates that Iris is in the
* process of crashing.
*/
if (p == NULL)
vsfr->rg_data[vsfr_size - 1] = '\0';
vsfr->rg_data[vsfr->bufSize - 1] = '\0';
dprintk(CVP_ERR, "SFR Message from FW: %s\n",
vsfr->rg_data);
@ -2816,7 +2832,7 @@ static void process_system_msg(struct msm_cvp_cb_info *info,
switch (info->response_type) {
case HAL_SYS_ERROR:
print_sfr_message(device);
__process_sys_error(device);
break;
case HAL_SYS_RELEASE_RESOURCE_DONE:
dprintk(CVP_DBG, "Received SYS_RELEASE_RESOURCE\n");
@ -2925,6 +2941,8 @@ static int __response_handler(struct iris_hfi_device *device)
}
if (device->intr_status & CVP_FATAL_INTR_BMSK) {
struct cvp_hfi_sfr_struct *vsfr = (struct cvp_hfi_sfr_struct *)
device->sfr.align_virtual_addr;
struct msm_cvp_cb_info info = {
.response_type = HAL_SYS_WATCHDOG_TIMEOUT,
.response.cmd = {
@ -2932,7 +2950,9 @@ static int __response_handler(struct iris_hfi_device *device)
}
};
print_sfr_message(device);
if (vsfr)
dprintk(CVP_ERR, "SFR Message from FW: %s\n",
vsfr->rg_data);
if (device->intr_status & CVP_WRAPPER_INTR_MASK_CPU_NOC_BMSK)
dprintk(CVP_ERR, "Received Xtensa NOC error\n");
@ -4585,6 +4605,7 @@ static void iris_init_hfi_callbacks(struct cvp_hfi_device *hdev)
hdev->session_set_buffers = iris_hfi_session_set_buffers;
hdev->session_release_buffers = iris_hfi_session_release_buffers;
hdev->session_send = iris_hfi_session_send;
hdev->session_flush = iris_hfi_session_flush;
hdev->scale_clocks = iris_hfi_scale_clocks;
hdev->vote_bus = iris_hfi_vote_buses;
hdev->get_fw_info = iris_hfi_get_fw_info;

View file

@ -98,6 +98,8 @@
(HFI_CMD_SESSION_CVP_START + 0x054)
#define HFI_CMD_SESSION_CVP_RELEASE_PERSIST_BUFFERS\
(HFI_CMD_SESSION_CVP_START + 0x055)
#define HFI_CMD_SESSION_CVP_FLUSH\
(HFI_CMD_SESSION_CVP_START + 0x057)
#define HFI_CMD_SESSION_CVP_ICA_FRAME\
(HFI_CMD_SESSION_CVP_START + 0x100)
#define HFI_CMD_SESSION_CVP_ICA_CONFIG\
@ -136,14 +138,16 @@
(HFI_MSG_SESSION_CVP_START + 0x023)
#define HFI_MSG_SESSION_CVP_OPERATION_CONFIG (HFI_MSG_SESSION_CVP_START + 0x030)
#define HFI_MSG_SESSION_CVP_SET_PERSIST_BUFFERS\
#define HFI_MSG_SESSION_CVP_SET_PERSIST_BUFFERS\
(HFI_MSG_SESSION_CVP_START + 0x034)
#define HFI_MSG_SESSION_CVP_SET_MODEL_BUFFERS\
#define HFI_MSG_SESSION_CVP_SET_MODEL_BUFFERS\
(HFI_MSG_SESSION_CVP_START + 0x036)
#define HFI_MSG_SESSION_CVP_FD\
#define HFI_MSG_SESSION_CVP_FD\
(HFI_MSG_SESSION_CVP_START + 0x037)
#define HFI_MSG_SESSION_CVP_RELEASE_PERSIST_BUFFERS\
#define HFI_MSG_SESSION_CVP_RELEASE_PERSIST_BUFFERS\
(HFI_MSG_SESSION_CVP_START + 0x038)
#define HFI_MSG_SESSION_CVP_FLUSH\
(HFI_CMD_SESSION_CVP_START + 0x03A)
#define CVP_IFACEQ_MAX_PKT_SIZE 1024
#define CVP_IFACEQ_MED_PKT_SIZE 768

View file

@ -340,8 +340,8 @@ struct cvp_hfi_device {
int (*session_abort)(void *session);
int (*session_set_buffers)(void *sess, u32 iova, u32 size);
int (*session_release_buffers)(void *sess);
int (*session_send)(void *sess,
struct cvp_kmd_hfi_packet *in_pkt);
int (*session_send)(void *sess, struct cvp_kmd_hfi_packet *in_pkt);
int (*session_flush)(void *sess);
int (*scale_clocks)(void *dev, u32 freq);
int (*vote_bus)(void *dev, struct cvp_bus_vote_data *data,
int num_data);

View file

@ -48,6 +48,7 @@
#define HFI_ERR_SESSION_BUFFERCOUNT_TOOSMALL (HFI_COMMON_BASE + 0x1011)
#define HFI_ERR_SESSION_INVALID_SCALE_FACTOR (HFI_COMMON_BASE + 0x1012)
#define HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED (HFI_COMMON_BASE + 0x1013)
#define HFI_ERR_SESSION_FLUSHED (HFI_COMMON_BASE + 0x101C)
#define HFI_EVENT_SYS_ERROR (HFI_COMMON_BASE + 0x1)
#define HFI_EVENT_SESSION_ERROR (HFI_COMMON_BASE + 0x2)
@ -455,4 +456,12 @@ struct cvp_buf_type {
};
};
struct cvp_hfi_msg_sys_session_flush_done_packet {
u32 size;
u32 packet_type;
u32 session_id;
u32 error_type;
struct cvp_hfi_client client_data;
};
#endif

View file

@ -327,6 +327,31 @@ static int hfi_process_session_set_buf_done(u32 device_id,
return 0;
}
static int hfi_process_session_flush_done(u32 device_id,
struct cvp_hfi_msg_sys_session_flush_done_packet *pkt,
struct msm_cvp_cb_info *info)
{
struct msm_cvp_cb_cmd_done cmd_done = {0};
dprintk(CVP_DBG, "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,
struct cvp_hfi_msg_session_hdr *pkt,
@ -610,6 +635,9 @@ int cvp_hfi_process_msg_packet(u32 device_id,
case HFI_MSG_SYS_SESSION_ABORT_DONE:
pkt_func = (pkt_func_def)hfi_process_session_abort_done;
break;
case HFI_MSG_SESSION_CVP_FLUSH:
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:

View file

@ -13,7 +13,7 @@ struct cvp_power_level {
unsigned long bw_sum;
};
void print_internal_buffer(u32 tag, const char *str,
static void print_internal_buffer(u32 tag, const char *str,
struct msm_cvp_inst *inst, struct cvp_internal_buf *cbuf)
{
if (!(tag & msm_cvp_debug) || !inst || !cbuf)
@ -41,8 +41,8 @@ void print_smem(u32 tag, const char *str, struct msm_cvp_inst *inst,
if (smem->dma_buf) {
dprintk(tag, "%s: %x : %s size %d flags %#x iova %#x", str,
hash32_ptr(inst->session), smem->dma_buf->name, smem->size,
smem->flags, smem->device_addr);
hash32_ptr(inst->session), smem->dma_buf->name,
smem->size, smem->flags, smem->device_addr);
}
}
@ -419,7 +419,7 @@ exit:
return 0;
}
static u32 msm_cvp_map_buf_cpu(struct msm_cvp_inst *inst,
static u32 msm_cvp_map_frame_buf(struct msm_cvp_inst *inst,
struct cvp_buf_type *buf,
struct msm_cvp_frame *frame)
{
@ -443,6 +443,7 @@ static u32 msm_cvp_map_buf_cpu(struct msm_cvp_inst *inst,
if (!smem)
return 0;
frame->bufs[nr].fd = buf->fd;
frame->bufs[nr].smem = smem;
frame->bufs[nr].size = buf->size;
frame->bufs[nr].offset = buf->offset;
@ -459,7 +460,7 @@ static u32 msm_cvp_map_buf_cpu(struct msm_cvp_inst *inst,
return iova;
}
static void msm_cvp_unmap_buf_cpu(struct msm_cvp_frame *frame)
static void msm_cvp_unmap_frame_buf(struct msm_cvp_frame *frame)
{
u32 i;
u32 type;
@ -503,7 +504,7 @@ static void msm_cvp_unmap_frame(struct msm_cvp_inst *inst, u64 ktid)
mutex_unlock(&inst->frames.lock);
if (found)
msm_cvp_unmap_buf_cpu(frame);
msm_cvp_unmap_frame_buf(frame);
else
dprintk(CVP_WARN, "%s frame %llu not found!\n", __func__, ktid);
}
@ -555,6 +556,7 @@ static int cvp_wait_process_message(struct msm_cvp_inst *inst,
struct cvp_kmd_hfi_packet *out)
{
struct cvp_session_msg *msg = NULL;
struct cvp_hfi_msg_session_hdr *hdr;
int rc = 0;
if (wait_event_timeout(sq->wq,
@ -578,11 +580,12 @@ static int cvp_wait_process_message(struct msm_cvp_inst *inst,
goto exit;
}
msm_cvp_unmap_frame(inst, msg->pkt.client_data.kdata);
if (out)
memcpy(out, &msg->pkt, sizeof(struct cvp_hfi_msg_session_hdr));
kmem_cache_free(cvp_driver->msg_cache, msg);
hdr = (struct cvp_hfi_msg_session_hdr *)out;
msm_cvp_unmap_frame(inst, hdr->client_data.kdata);
exit:
return rc;
@ -768,13 +771,13 @@ static int msm_cvp_map_frame(struct msm_cvp_inst *inst,
if (buf->fd < 0 || !buf->size)
continue;
iova = msm_cvp_map_buf_cpu(inst, buf, frame);
iova = msm_cvp_map_frame_buf(inst, buf, frame);
if (!iova) {
dprintk(CVP_ERR,
"%s: buf %d register failed.\n",
__func__, i);
msm_cvp_unmap_buf_cpu(frame);
msm_cvp_unmap_frame_buf(frame);
return -EINVAL;
}
buf->fd = iova;
@ -854,8 +857,7 @@ static int msm_cvp_session_process_hfi(
if (rc)
goto exit;
rc = call_hfi_op(hdev, session_send,
(void *)inst->session, in_pkt);
rc = call_hfi_op(hdev, session_send, (void *)inst->session, in_pkt);
if (rc) {
dprintk(CVP_ERR,
"%s: Failed in call_hfi_op %d, %x\n",
@ -892,15 +894,15 @@ static bool cvp_fence_wait(struct cvp_fence_queue *q,
struct cvp_fence_command *f;
*fence = NULL;
spin_lock(&q->lock);
mutex_lock(&q->lock);
*state = q->state;
if (*state != QUEUE_ACTIVE) {
spin_unlock(&q->lock);
mutex_unlock(&q->lock);
return true;
}
if (list_empty(&q->wait_list)) {
spin_unlock(&q->lock);
mutex_unlock(&q->lock);
return false;
}
@ -908,7 +910,7 @@ static bool cvp_fence_wait(struct cvp_fence_queue *q,
list_del_init(&f->list);
list_add_tail(&q->sched_list, &f->list);
spin_unlock(&q->lock);
mutex_unlock(&q->lock);
*fence = f;
return true;
@ -927,8 +929,10 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx,
struct cvp_hfi_device *hdev;
struct cvp_session_queue *sq;
struct synx_session ssid;
u32 hfi_err = HFI_ERR_NONE;
struct cvp_hfi_msg_session_hdr *hdr;
dprintk(CVP_DBG, "Enter %s\n", __func__);
dprintk(CVP_DBG, "%s %s\n", current->comm, __func__);
hdev = inst->core->device;
sq = &inst->session_queue_fence;
@ -941,8 +945,8 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx,
if (h_synx) {
rc = synx_wait(ssid, h_synx, timeout_ms);
if (rc) {
dprintk(CVP_ERR, "%s: synx_wait %d failed\n",
__func__, i);
dprintk(CVP_ERR, "%s %s: synx_wait %d failed\n",
current->comm, __func__, i);
synx_state = SYNX_STATE_SIGNALED_ERROR;
goto exit;
}
@ -959,14 +963,32 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx,
rc = call_hfi_op(hdev, session_send, (void *)inst->session,
(struct cvp_kmd_hfi_packet *)pkt);
if (rc) {
dprintk(CVP_ERR, "%s: Failed in call_hfi_op %d, %x\n", __func__,
pkt->size, pkt->packet_type);
dprintk(CVP_ERR, "%s %s: Failed in call_hfi_op %d, %x\n",
current->comm, __func__, pkt->size, pkt->packet_type);
synx_state = SYNX_STATE_SIGNALED_ERROR;
goto exit;
}
timeout = msecs_to_jiffies(CVP_MAX_WAIT_TIME);
rc = cvp_wait_process_message(inst, sq, &ktid, timeout, NULL);
rc = cvp_wait_process_message(inst, sq, &ktid, timeout,
(struct cvp_kmd_hfi_packet *)pkt);
hdr = (struct cvp_hfi_msg_session_hdr *)pkt;
hfi_err = hdr->error_type;
if (rc) {
dprintk(CVP_ERR, "%s %s: cvp_wait_process_message rc %d\n",
current->comm, __func__, rc);
synx_state = SYNX_STATE_SIGNALED_ERROR;
goto exit;
}
if (hfi_err == HFI_ERR_SESSION_FLUSHED) {
dprintk(CVP_DBG, "%s %s: cvp_wait_process_message flushed\n",
current->comm, __func__);
synx_state = SYNX_STATE_SIGNALED_CANCEL;
} else if (hfi_err != HFI_ERR_NONE) {
dprintk(CVP_ERR, "%s %s: cvp_wait_process_message hfi err %d\n",
current->comm, __func__, hfi_err);
synx_state = SYNX_STATE_SIGNALED_CANCEL;
}
exit:
if (synx[FENCE_DME_ICA_ENABLED_IDX]) {
@ -974,8 +996,8 @@ exit:
rc = synx_signal(ssid, h_synx, synx_state);
if (rc) {
dprintk(CVP_ERR, "%s: synx_signal %d failed\n",
__func__, FENCE_DME_DS_IDX);
dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n",
current->comm, __func__, FENCE_DME_DS_IDX);
synx_state = SYNX_STATE_SIGNALED_ERROR;
}
}
@ -983,8 +1005,8 @@ exit:
h_synx = synx[FENCE_DME_OUTPUT_IDX];
rc = synx_signal(ssid, h_synx, synx_state);
if (rc)
dprintk(CVP_ERR, "%s: synx_signal %d failed\n",
__func__, FENCE_DME_OUTPUT_IDX);
dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n",
current->comm, __func__, FENCE_DME_OUTPUT_IDX);
return rc;
}
@ -1003,8 +1025,10 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx,
struct cvp_session_queue *sq;
struct synx_session ssid;
u32 in, out;
u32 hfi_err = HFI_ERR_NONE;
struct cvp_hfi_msg_session_hdr *hdr;
dprintk(CVP_DBG, "Enter %s\n", __func__);
dprintk(CVP_DBG, "%s %s\n", current->comm, __func__);
hdev = inst->core->device;
sq = &inst->session_queue_fence;
@ -1020,9 +1044,17 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx,
if (h_synx) {
rc = synx_wait(ssid, h_synx, timeout_ms);
if (rc) {
dprintk(CVP_ERR, "%s: synx_wait %d failed\n",
__func__, i);
synx_state = SYNX_STATE_SIGNALED_ERROR;
synx_state = synx_get_status(ssid, h_synx);
if (synx_state == SYNX_STATE_SIGNALED_CANCEL) {
dprintk(CVP_DBG,
"%s: synx_wait %d cancel %d state %d\n",
current->comm, i, rc, synx_state);
} else {
dprintk(CVP_ERR,
"%s: synx_wait %d failed %d state %d\n",
current->comm, i, rc, synx_state);
synx_state = SYNX_STATE_SIGNALED_ERROR;
}
goto exit;
}
}
@ -1032,14 +1064,32 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx,
rc = call_hfi_op(hdev, session_send, (void *)inst->session,
(struct cvp_kmd_hfi_packet *)pkt);
if (rc) {
dprintk(CVP_ERR, "%s: Failed in call_hfi_op %d, %x\n", __func__,
pkt->size, pkt->packet_type);
dprintk(CVP_ERR, "%s %s: Failed in call_hfi_op %d, %x\n",
current->comm, __func__, pkt->size, pkt->packet_type);
synx_state = SYNX_STATE_SIGNALED_ERROR;
goto exit;
}
timeout = msecs_to_jiffies(CVP_MAX_WAIT_TIME);
rc = cvp_wait_process_message(inst, sq, &ktid, timeout, NULL);
rc = cvp_wait_process_message(inst, sq, &ktid, timeout,
(struct cvp_kmd_hfi_packet *)pkt);
hdr = (struct cvp_hfi_msg_session_hdr *)pkt;
hfi_err = hdr->error_type;
if (rc) {
dprintk(CVP_ERR, "%s %s: cvp_wait_process_message rc %d\n",
current->comm, __func__, rc);
synx_state = SYNX_STATE_SIGNALED_ERROR;
goto exit;
}
if (hfi_err == HFI_ERR_SESSION_FLUSHED) {
dprintk(CVP_DBG, "%s %s: cvp_wait_process_message flushed\n",
current->comm, __func__);
synx_state = SYNX_STATE_SIGNALED_CANCEL;
} else if (hfi_err != HFI_ERR_NONE) {
dprintk(CVP_ERR, "%s %s: cvp_wait_process_message hfi err %d\n",
current->comm, __func__, hfi_err);
synx_state = SYNX_STATE_SIGNALED_CANCEL;
}
exit:
i = in + 1;
@ -1049,7 +1099,7 @@ exit:
rc = synx_signal(ssid, h_synx, synx_state);
if (rc) {
dprintk(CVP_ERR, "%s: synx_signal %d failed\n",
__func__, i);
current->comm, i);
synx_state = SYNX_STATE_SIGNALED_ERROR;
}
}
@ -1102,7 +1152,7 @@ static int cvp_import_synx(struct msm_cvp_inst *inst, u32 type, u32 *fence,
switch (type) {
case HFI_CMD_SESSION_CVP_DME_FRAME:
{
start = 0;
start = 1;
end = HFI_DME_BUF_NUM;
break;
}
@ -1204,9 +1254,10 @@ static int cvp_fence_thread(void *data)
struct msm_cvp_inst *inst;
struct cvp_fence_queue *q;
enum queue_state state;
struct cvp_fence_command *fence_data;
struct cvp_fence_command *f;
struct cvp_hfi_cmd_session_hdr *pkt;
u32 *synx;
u64 ktid;
dprintk(CVP_DBG, "Enter %s\n", current->comm);
@ -1222,20 +1273,22 @@ static int cvp_fence_thread(void *data)
wait:
dprintk(CVP_DBG, "%s starts wait\n", current->comm);
fence_data = NULL;
wait_event_interruptible(q->wq, cvp_fence_wait(q, &fence_data, &state));
f = NULL;
wait_event_interruptible(q->wq, cvp_fence_wait(q, &f, &state));
if (state != QUEUE_ACTIVE)
goto exit;
if (!fence_data)
if (!f)
goto wait;
pkt = fence_data->pkt;
synx = (u32 *)fence_data->synx;
pkt = f->pkt;
synx = (u32 *)f->synx;
dprintk(CVP_DBG, "%s starts work\n", current->comm);
ktid = pkt->client_data.kdata & (FENCE_BIT - 1);
dprintk(CVP_DBG, "%s starts working on frame %llu frameID %llu\n",
current->comm, ktid, f->frame_id);
switch (fence_data->type) {
switch (f->type) {
case HFI_CMD_SESSION_CVP_DME_FRAME:
rc = cvp_fence_dme(inst, synx, pkt);
break;
@ -1244,18 +1297,24 @@ wait:
break;
default:
dprintk(CVP_ERR, "%s: unknown hfi cmd type 0x%x\n",
__func__, fence_data->type);
__func__, f->type);
rc = -EINVAL;
goto exit;
break;
}
cvp_release_synx(inst, fence_data->type, synx);
spin_lock(&q->lock);
list_del_init(&fence_data->list);
spin_unlock(&q->lock);
cvp_free_fence_data(fence_data);
mutex_lock(&q->lock);
cvp_release_synx(inst, f->type, synx);
list_del_init(&f->list);
mutex_unlock(&q->lock);
dprintk(CVP_DBG, "%s is done with frame %llu frameID %llu\n",
current->comm, ktid, f->frame_id);
cvp_free_fence_data(f);
goto wait;
exit:
dprintk(CVP_DBG, "%s exit\n", current->comm);
cvp_put_inst(inst);
@ -1271,9 +1330,10 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst,
struct cvp_hfi_cmd_session_hdr *pkt;
unsigned int offset, buf_num, in_offset, in_buf_num;
struct msm_cvp_inst *s;
struct cvp_fence_command *fcmd;
struct cvp_fence_command *f;
struct cvp_fence_queue *q;
u32 *fence;
enum op_mode mode;
if (!inst || !inst->core || !arg || !inst->core->device) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
@ -1284,6 +1344,18 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst,
if (!s)
return -ECONNRESET;
q = &inst->fence_cmd_queue;
mutex_lock(&q->lock);
mode = q->mode;
mutex_unlock(&q->lock);
if (mode == OP_DRAINING) {
dprintk(CVP_DBG, "%s: flush in progress\n", __func__);
rc = -EBUSY;
goto exit;
}
in_offset = arg->buf_offset;
in_buf_num = arg->buf_num;
@ -1311,24 +1383,29 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst,
if (rc)
goto exit;
rc = cvp_alloc_fence_data(&fcmd, pkt->size);
rc = cvp_alloc_fence_data(&f, pkt->size);
if (rc)
goto exit;
fcmd->type = cvp_hfi_defs[idx].type;
memcpy(fcmd->pkt, pkt, pkt->size);
f->type = cvp_hfi_defs[idx].type;
f->frame_id = arg->data.hfi_fence_pkt.frame_id;
f->mode = OP_NORMAL;
fcmd->pkt->client_data.kdata |= FENCE_BIT;
dprintk(CVP_DBG, "%s: frameID %llu\n", __func__, f->frame_id);
rc = cvp_import_synx(inst, fcmd->type, fence, fcmd->synx);
memcpy(f->pkt, pkt, pkt->size);
f->pkt->client_data.kdata |= FENCE_BIT;
rc = cvp_import_synx(inst, f->type, fence, f->synx);
if (rc) {
kfree(fcmd);
kfree(f);
goto exit;
}
q = &inst->fence_cmd_queue;
spin_lock(&q->lock);
list_add_tail(&fcmd->list, &inst->fence_cmd_queue.wait_list);
spin_unlock(&q->lock);
mutex_lock(&q->lock);
list_add_tail(&f->list, &inst->fence_cmd_queue.wait_list);
mutex_unlock(&q->lock);
wake_up(&inst->fence_cmd_queue.wq);
@ -1840,9 +1917,9 @@ static int cvp_fence_thread_start(struct msm_cvp_inst *inst)
return 0;
q = &inst->fence_cmd_queue;
spin_lock(&q->lock);
mutex_lock(&q->lock);
q->state = QUEUE_ACTIVE;
spin_unlock(&q->lock);
mutex_unlock(&q->lock);
for (i = 0; i < inst->prop.fthread_nr; ++i) {
if (!cvp_get_inst_validate(inst->core, inst)) {
@ -1866,9 +1943,9 @@ static int cvp_fence_thread_start(struct msm_cvp_inst *inst)
exit:
if (rc) {
spin_lock(&q->lock);
mutex_lock(&q->lock);
q->state = QUEUE_STOP;
spin_unlock(&q->lock);
mutex_unlock(&q->lock);
wake_up_all(&q->wq);
}
return rc;
@ -1884,9 +1961,9 @@ static int cvp_fence_thread_stop(struct msm_cvp_inst *inst)
q = &inst->fence_cmd_queue;
spin_lock(&q->lock);
mutex_lock(&q->lock);
q->state = QUEUE_STOP;
spin_unlock(&q->lock);
mutex_unlock(&q->lock);
sq = &inst->session_queue_fence;
spin_lock(&sq->lock);
@ -2102,10 +2179,221 @@ static int msm_cvp_set_sysprop(struct msm_cvp_inst *inst,
return rc;
}
static int msm_cvp_flush_all(struct msm_cvp_inst *inst)
static int cvp_cancel_input_synx(struct msm_cvp_inst *inst, u32 type, u32 *synx)
{
int rc = 0;
int i;
int h_synx;
struct synx_session ssid;
int start = 0, end = 0;
int synx_state = SYNX_STATE_SIGNALED_CANCEL;
ssid = inst->synx_session_id;
switch (type) {
case HFI_CMD_SESSION_CVP_DME_FRAME:
{
start = 1;
end = HFI_DME_BUF_NUM - 1;
break;
}
case HFI_CMD_SESSION_CVP_FD_FRAME:
{
u32 in, out;
in = synx[0] >> 16;
out = synx[0] & 0xFFFF;
start = 1;
end = in + 1;
break;
}
default:
dprintk(CVP_ERR, "%s: unknown fence type\n", __func__);
rc = -EINVAL;
return rc;
}
for (i = start; i < end; ++i) {
h_synx = synx[i];
if (h_synx) {
rc = synx_signal(ssid, h_synx, synx_state);
if (rc && rc != -EALREADY) {
dprintk(CVP_ERR, "%s: synx_signal %d failed\n",
__func__, i);
synx_state = SYNX_STATE_SIGNALED_ERROR;
}
}
}
return rc;
}
static int cvp_cancel_output_synx(struct msm_cvp_inst *inst, u32 type,
u32 *synx)
{
int rc = 0;
int i;
int h_synx;
struct synx_session ssid;
int start = 0, end = 0;
int synx_state = SYNX_STATE_SIGNALED_CANCEL;
ssid = inst->synx_session_id;
switch (type) {
case HFI_CMD_SESSION_CVP_DME_FRAME:
{
start = FENCE_DME_OUTPUT_IDX;
end = FENCE_DME_OUTPUT_IDX + 1;
break;
}
case HFI_CMD_SESSION_CVP_FD_FRAME:
{
u32 in, out;
in = synx[0] >> 16;
out = synx[0] & 0xFFFF;
start = in + 1;
end = in + out + 1;
break;
}
default:
dprintk(CVP_ERR, "%s: unknown fence type\n", __func__);
rc = -EINVAL;
return rc;
}
for (i = start; i < end; ++i) {
h_synx = synx[i];
if (h_synx) {
rc = synx_signal(ssid, h_synx, synx_state);
if (rc) {
dprintk(CVP_ERR, "%s: synx_signal %d failed\n",
__func__, i);
synx_state = SYNX_STATE_SIGNALED_ERROR;
}
}
}
return rc;
}
static int cvp_drain_fence_cmd_queue_partial(struct msm_cvp_inst *inst)
{
unsigned long wait_time;
struct cvp_fence_queue *q;
struct cvp_fence_command *f;
int rc = 0;
int count = 0, max_count = 0;
q = &inst->fence_cmd_queue;
mutex_lock(&q->lock);
list_for_each_entry(f, &q->sched_list, list) {
if (f->mode == OP_FLUSH)
continue;
++count;
}
list_for_each_entry(f, &q->wait_list, list) {
if (f->mode == OP_FLUSH)
continue;
++count;
}
mutex_unlock(&q->lock);
wait_time = count * CVP_MAX_WAIT_TIME * 1000;
dprintk(CVP_DBG, "%s: wait %d us for %d fence command\n",
__func__, wait_time, count);
count = 0;
max_count = wait_time / 100;
retry:
mutex_lock(&q->lock);
f = list_first_entry(&q->sched_list, struct cvp_fence_command, list);
/* Wait for all normal frames to finish before return */
if ((f && f->mode == OP_FLUSH) ||
(list_empty(&q->sched_list) && list_empty(&q->wait_list))) {
mutex_unlock(&q->lock);
return rc;
}
mutex_unlock(&q->lock);
usleep_range(100, 200);
++count;
if (count < max_count) {
goto retry;
} else {
rc = -ETIMEDOUT;
dprintk(CVP_ERR, "%s: timed out!\n", __func__);
}
return rc;
}
static int cvp_drain_fence_sched_list(struct msm_cvp_inst *inst)
{
unsigned long wait_time;
struct cvp_fence_queue *q;
struct cvp_fence_command *f;
int rc = 0;
int count = 0, max_count = 0;
u64 ktid;
q = &inst->fence_cmd_queue;
mutex_lock(&q->lock);
list_for_each_entry(f, &q->sched_list, list) {
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
dprintk(CVP_DBG, "%s: frame %llu is in sched_list\n",
__func__, ktid);
dprintk(CVP_DBG, "%s: frameID %llu is in sched_list\n",
__func__, f->frame_id);
++count;
}
mutex_unlock(&q->lock);
wait_time = count * CVP_MAX_WAIT_TIME * 1000;
dprintk(CVP_DBG, "%s: wait %d us for %d fence command\n",
__func__, wait_time, count);
count = 0;
max_count = wait_time / 100;
retry:
mutex_lock(&q->lock);
if (list_empty(&q->sched_list)) {
mutex_unlock(&q->lock);
return rc;
}
mutex_unlock(&q->lock);
usleep_range(100, 200);
++count;
if (count < max_count) {
goto retry;
} else {
rc = -ETIMEDOUT;
dprintk(CVP_ERR, "%s: timed out!\n", __func__);
}
return rc;
}
static int cvp_flush_all(struct msm_cvp_inst *inst)
{
int rc = 0;
struct msm_cvp_inst *s;
struct cvp_fence_queue *q;
struct cvp_fence_command *f, *d;
struct cvp_hfi_device *hdev;
u64 ktid;
if (!inst || !inst->core) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
@ -2116,6 +2404,166 @@ static int msm_cvp_flush_all(struct msm_cvp_inst *inst)
if (!s)
return -ECONNRESET;
q = &inst->fence_cmd_queue;
hdev = inst->core->device;
mutex_lock(&q->lock);
q->mode = OP_DRAINING;
list_for_each_entry_safe(f, d, &q->wait_list, list) {
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
dprintk(CVP_DBG, "%s: flush frame %llu from wait_list\n",
__func__, ktid);
dprintk(CVP_DBG, "%s: flush frameID %llu from wait_list\n",
__func__, f->frame_id);
list_del_init(&f->list);
msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata);
cvp_cancel_output_synx(inst, f->type, f->synx);
cvp_release_synx(inst, f->type, f->synx);
cvp_free_fence_data(f);
}
list_for_each_entry(f, &q->sched_list, list) {
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
dprintk(CVP_DBG, "%s: flush frame %llu from sched_list\n",
__func__, ktid);
dprintk(CVP_DBG, "%s: flush frameID %llu from sched_list\n",
__func__, f->frame_id);
cvp_cancel_input_synx(inst, f->type, f->synx);
}
mutex_unlock(&q->lock);
dprintk(CVP_DBG, "%s: send flush to fw\n", __func__);
/* Send flush to FW */
rc = call_hfi_op(hdev, session_flush, (void *)inst->session);
if (rc) {
dprintk(CVP_WARN, "%s: continue flush without fw. rc %d\n",
__func__, rc);
goto exit;
}
/* Wait for FW response */
rc = wait_for_sess_signal_receipt(inst, HAL_SESSION_FLUSH_DONE);
if (rc)
dprintk(CVP_WARN, "%s: wait for signal failed, rc %d\n",
__func__, rc);
dprintk(CVP_DBG, "%s: received flush from fw\n", __func__);
exit:
rc = cvp_drain_fence_sched_list(inst);
mutex_lock(&q->lock);
q->mode = OP_NORMAL;
mutex_unlock(&q->lock);
cvp_put_inst(s);
return rc;
}
static void cvp_mark_fence_command(struct msm_cvp_inst *inst, u64 frame_id)
{
int found = false;
struct cvp_fence_queue *q;
struct cvp_fence_command *f;
q = &inst->fence_cmd_queue;
list_for_each_entry(f, &q->sched_list, list) {
if (found) {
f->mode = OP_FLUSH;
continue;
}
if (f->frame_id >= frame_id) {
found = true;
f->mode = OP_FLUSH;
}
}
list_for_each_entry(f, &q->wait_list, list) {
if (found) {
f->mode = OP_FLUSH;
continue;
}
if (f->frame_id >= frame_id) {
found = true;
f->mode = OP_FLUSH;
}
}
}
static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id)
{
int rc = 0;
struct msm_cvp_inst *s;
struct cvp_fence_queue *q;
struct cvp_fence_command *f, *d;
u64 ktid;
if (!inst || !inst->core) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
s = cvp_get_inst_validate(inst->core, inst);
if (!s)
return -ECONNRESET;
q = &inst->fence_cmd_queue;
mutex_lock(&q->lock);
q->mode = OP_DRAINING;
cvp_mark_fence_command(inst, frame_id);
list_for_each_entry_safe(f, d, &q->wait_list, list) {
if (f->mode != OP_FLUSH)
continue;
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
dprintk(CVP_DBG, "%s: flush frame %llu from wait_list\n",
__func__, ktid);
dprintk(CVP_DBG, "%s: flush frameID %llu from wait_list\n",
__func__, f->frame_id);
list_del_init(&f->list);
msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata);
cvp_cancel_output_synx(inst, f->type, f->synx);
cvp_release_synx(inst, f->type, f->synx);
cvp_free_fence_data(f);
}
list_for_each_entry(f, &q->sched_list, list) {
if (f->mode != OP_FLUSH)
continue;
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
dprintk(CVP_DBG, "%s: flush frame %llu from sched_list\n",
__func__, ktid);
dprintk(CVP_DBG, "%s: flush frameID %llu from sched_list\n",
__func__, f->frame_id);
cvp_cancel_input_synx(inst, f->type, f->synx);
}
mutex_unlock(&q->lock);
rc = cvp_drain_fence_cmd_queue_partial(inst);
if (rc)
dprintk(CVP_WARN, "%s: continue flush. rc %d\n",
__func__, rc);
rc = cvp_flush_all(inst);
cvp_put_inst(s);
return rc;
}
@ -2211,10 +2659,10 @@ int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg)
rc = msm_cvp_set_sysprop(inst, arg);
break;
case CVP_KMD_FLUSH_ALL:
rc = msm_cvp_flush_all(inst);
rc = cvp_flush_all(inst);
break;
case CVP_KMD_FLUSH_FRAME:
dprintk(CVP_DBG, "CVP_KMD_FLUSH_FRAME is not implemented\n");
rc = cvp_flush_frame(inst, arg->data.frame_id);
break;
default:
dprintk(CVP_DBG, "%s: unknown arg type %#x\n",
@ -2252,7 +2700,7 @@ int msm_cvp_session_deinit(struct msm_cvp_inst *inst)
mutex_lock(&inst->frames.lock);
list_for_each_entry_safe(frame, dummy1, &inst->frames.list, list) {
list_del(&frame->list);
msm_cvp_unmap_buf_cpu(frame);
msm_cvp_unmap_frame_buf(frame);
}
mutex_unlock(&inst->frames.lock);

View file

@ -520,7 +520,25 @@ static void handle_release_res_done(enum hal_command_response cmd, void *data)
static void handle_session_flush(enum hal_command_response cmd, void *data)
{
dprintk(CVP_WARN, "%s is not supported on CVP!\n", __func__);
struct msm_cvp_cb_cmd_done *response = data;
struct msm_cvp_inst *inst;
if (!response) {
dprintk(CVP_ERR,
"Failed to get valid response for release resource\n");
return;
}
inst = cvp_get_inst(get_cvp_core(response->device_id),
response->session_id);
if (!inst) {
dprintk(CVP_WARN, "%s:Got a response for an inactive session\n",
__func__);
return;
}
signal_session_msg_receipt(cmd, inst);
cvp_put_inst(inst);
}
static void handle_session_error(enum hal_command_response cmd, void *data)

View file

@ -232,11 +232,12 @@ static int __init_session_queue(struct msm_cvp_inst *inst)
static void __init_fence_queue(struct msm_cvp_inst *inst)
{
spin_lock_init(&inst->fence_cmd_queue.lock);
mutex_init(&inst->fence_cmd_queue.lock);
INIT_LIST_HEAD(&inst->fence_cmd_queue.wait_list);
INIT_LIST_HEAD(&inst->fence_cmd_queue.sched_list);
init_waitqueue_head(&inst->fence_cmd_queue.wq);
inst->fence_cmd_queue.state = QUEUE_ACTIVE;
inst->fence_cmd_queue.mode = OP_NORMAL;
spin_lock_init(&inst->session_queue_fence.lock);
INIT_LIST_HEAD(&inst->session_queue_fence.msgs);
@ -245,7 +246,14 @@ static void __init_fence_queue(struct msm_cvp_inst *inst)
inst->session_queue_fence.state = QUEUE_ACTIVE;
}
static void _deinit_session_queue(struct msm_cvp_inst *inst)
static void __deinit_fence_queue(struct msm_cvp_inst *inst)
{
mutex_destroy(&inst->fence_cmd_queue.lock);
inst->fence_cmd_queue.state = QUEUE_INVALID;
inst->fence_cmd_queue.mode = OP_INVALID;
}
static void __deinit_session_queue(struct msm_cvp_inst *inst)
{
struct cvp_session_msg *msg, *tmpmsg;
@ -361,7 +369,7 @@ void *msm_cvp_open(int core_id, int session_type)
return inst;
fail_init:
_deinit_session_queue(inst);
__deinit_session_queue(inst);
mutex_lock(&core->lock);
list_del(&inst->list);
mutex_unlock(&core->lock);
@ -417,7 +425,9 @@ int msm_cvp_destroy(struct msm_cvp_inst *inst)
mutex_destroy(&inst->lock);
msm_cvp_debugfs_deinit_inst(inst);
_deinit_session_queue(inst);
__deinit_session_queue(inst);
__deinit_fence_queue(inst);
synx_uninitialize(inst->synx_session_id);
pr_info(CVP_DBG_TAG "Closed cvp instance: %pK session_id = %d\n",

View file

@ -273,9 +273,17 @@ struct cvp_session_prop {
u32 ddr_op_cache;
};
enum op_mode {
OP_NORMAL,
OP_DRAINING,
OP_FLUSH,
OP_INVALID,
};
struct cvp_fence_queue {
spinlock_t lock;
struct mutex lock;
enum queue_state state;
enum op_mode mode;
struct list_head wait_list;
wait_queue_head_t wq;
struct list_head sched_list;
@ -359,6 +367,8 @@ struct cvp_fence_type {
struct cvp_fence_command {
struct list_head list;
u64 frame_id;
enum op_mode mode;
u32 type;
u32 synx[MAX_HFI_FENCE_SIZE/2];
struct cvp_hfi_cmd_session_hdr *pkt;

View file

@ -78,7 +78,8 @@ static int _copy_fence_pkt_from_user(struct cvp_kmd_arg *kp,
struct cvp_kmd_arg __user *up,
unsigned int size)
{
struct cvp_kmd_hfi_fence_packet *k, *u;
struct cvp_kmd_hfi_fence_packet *k;
struct cvp_kmd_hfi_fence_packet __user *u;
int i;
k = &kp->data.hfi_fence_pkt;
@ -91,6 +92,24 @@ static int _copy_fence_pkt_from_user(struct cvp_kmd_arg *kp,
if (get_user(k->fence_data[i], &u->fence_data[i]))
return -EFAULT;
}
if (get_user(k->frame_id, &u->frame_id)) {
dprintk(CVP_ERR, "Failed to get frame id from fence pkt\n");
return -EFAULT;
}
return 0;
}
static int _copy_frameid_from_user(struct cvp_kmd_arg *kp,
struct cvp_kmd_arg __user *up)
{
if (get_user(kp->data.frame_id, &up->data.frame_id)) {
dprintk(CVP_ERR, "Failed to get frame id from user\n");
return -EFAULT;
}
return 0;
}
@ -211,6 +230,41 @@ static int _get_session_ctrl_from_user(
return 0;
}
static int _get_session_info_from_user(
struct cvp_kmd_session_info *k,
struct cvp_kmd_session_info __user *u)
{
int i;
if (get_user(k->session_id, &u->session_id))
return -EFAULT;
for (i = 0; i < 10; i++)
if (get_user(k->reserved[i], &u->reserved[i]))
return -EFAULT;
return 0;
}
static int _get_power_request(
struct cvp_kmd_request_power *k,
struct cvp_kmd_request_power __user *u)
{
int i;
if (get_user(k->clock_cycles_a, &u->clock_cycles_a) ||
get_user(k->clock_cycles_b, &u->clock_cycles_b) ||
get_user(k->ddr_bw, &u->ddr_bw) ||
get_user(k->sys_cache_bw, &u->sys_cache_bw))
return -EFAULT;
for (i = 0; i < 8; i++)
if (get_user(k->reserved[i], &u->reserved[i]))
return -EFAULT;
return 0;
}
static int convert_from_user(struct cvp_kmd_arg *kp,
unsigned long arg,
struct msm_cvp_inst *inst)
@ -238,31 +292,30 @@ static int convert_from_user(struct cvp_kmd_arg *kp,
switch (kp->type) {
case CVP_KMD_GET_SESSION_INFO:
{
struct cvp_kmd_session_info *k, *u;
struct cvp_kmd_session_info *k;
struct cvp_kmd_session_info __user *u;
k = &kp->data.session;
u = &up->data.session;
if (get_user(k->session_id, &u->session_id))
if (_get_session_info_from_user(k, u)) {
dprintk(CVP_ERR, "fail to get sess info\n");
return -EFAULT;
for (i = 0; i < 10; i++)
if (get_user(k->reserved[i], &u->reserved[i]))
return -EFAULT;
}
break;
}
case CVP_KMD_REQUEST_POWER:
{
struct cvp_kmd_request_power *k, *u;
struct cvp_kmd_request_power *k;
struct cvp_kmd_request_power __user *u;
k = &kp->data.req_power;
u = &up->data.req_power;
if (get_user(k->clock_cycles_a, &u->clock_cycles_a) ||
get_user(k->clock_cycles_b, &u->clock_cycles_b) ||
get_user(k->ddr_bw, &u->ddr_bw) ||
get_user(k->sys_cache_bw, &u->sys_cache_bw))
if (_get_power_request(k, u)) {
dprintk(CVP_ERR, "fail to get power request\n");
return -EFAULT;
for (i = 0; i < 8; i++)
if (get_user(k->reserved[i], &u->reserved[i]))
return -EFAULT;
}
break;
}
case CVP_KMD_REGISTER_BUFFER:
@ -364,8 +417,15 @@ static int convert_from_user(struct cvp_kmd_arg *kp,
}
break;
}
case CVP_KMD_FLUSH_ALL:
case CVP_KMD_UPDATE_POWER:
break;
case CVP_KMD_FLUSH_FRAME:
{
if (_copy_frameid_from_user(kp, up))
return -EFAULT;
break;
}
default:
dprintk(CVP_ERR, "%s: unknown cmd type 0x%x\n",
__func__, kp->type);
@ -376,6 +436,42 @@ static int convert_from_user(struct cvp_kmd_arg *kp,
return rc;
}
static int _put_user_session_info(
struct cvp_kmd_session_info *k,
struct cvp_kmd_session_info __user *u)
{
int i;
if (put_user(k->session_id, &u->session_id))
return -EFAULT;
for (i = 0; i < 10; i++)
if (put_user(k->reserved[i], &u->reserved[i]))
return -EFAULT;
return 0;
}
static int _put_power_request(
struct cvp_kmd_request_power *k,
struct cvp_kmd_request_power __user *u)
{
int i;
if (put_user(k->clock_cycles_a, &u->clock_cycles_a) ||
put_user(k->clock_cycles_b, &u->clock_cycles_b) ||
put_user(k->ddr_bw, &u->ddr_bw) ||
put_user(k->sys_cache_bw, &u->sys_cache_bw))
return -EFAULT;
for (i = 0; i < 8; i++)
if (put_user(k->reserved[i], &u->reserved[i]))
return -EFAULT;
return 0;
}
static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg)
{
int rc = 0;
@ -405,31 +501,30 @@ static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg)
}
case CVP_KMD_GET_SESSION_INFO:
{
struct cvp_kmd_session_info *k, *u;
struct cvp_kmd_session_info *k;
struct cvp_kmd_session_info __user *u;
k = &kp->data.session;
u = &up->data.session;
if (put_user(k->session_id, &u->session_id))
if (_put_user_session_info(k, u)) {
dprintk(CVP_ERR, "fail to copy sess info to user\n");
return -EFAULT;
for (i = 0; i < 10; i++)
if (put_user(k->reserved[i], &u->reserved[i]))
return -EFAULT;
}
break;
}
case CVP_KMD_REQUEST_POWER:
{
struct cvp_kmd_request_power *k, *u;
struct cvp_kmd_request_power *k;
struct cvp_kmd_request_power __user *u;
k = &kp->data.req_power;
u = &up->data.req_power;
if (put_user(k->clock_cycles_a, &u->clock_cycles_a) ||
put_user(k->clock_cycles_b, &u->clock_cycles_b) ||
put_user(k->ddr_bw, &u->ddr_bw) ||
put_user(k->sys_cache_bw, &u->sys_cache_bw))
if (_put_power_request(k, u)) {
dprintk(CVP_ERR, "fail to copy power to user\n");
return -EFAULT;
for (i = 0; i < 8; i++)
if (put_user(k->reserved[i], &u->reserved[i]))
return -EFAULT;
}
break;
}
case CVP_KMD_REGISTER_BUFFER:
@ -508,8 +603,9 @@ static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg)
}
break;
}
case CVP_KMD_FLUSH_ALL:
case CVP_KMD_FLUSH_FRAME:
case CVP_KMD_SET_SYS_PROPERTY:
break;
case CVP_KMD_UPDATE_POWER:
break;
default: