mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
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:
parent
c744f806b4
commit
04c6aea002
10 changed files with 766 additions and 122 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in a new issue