diff --git a/drivers/media/platform/msm/cvp/msm_cvp.c b/drivers/media/platform/msm/cvp/msm_cvp.c index 6c60839f745f..68819bcc07a2 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp.c +++ b/drivers/media/platform/msm/cvp/msm_cvp.c @@ -301,7 +301,8 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, sq = &inst->session_queue_fence; ktid = pkt->client_data.kdata; - if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) { + rc = cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state); + if (rc) { msm_cvp_unmap_frame(inst, pkt->client_data.kdata); goto exit; } @@ -416,6 +417,7 @@ wait: mutex_lock(&q->lock); cvp_release_synx(inst, f); list_del_init(&f->list); + state = q->state; mutex_unlock(&q->lock); dprintk(CVP_SYNX, "%s done with %d ktid %llu frameID %llu rc %d\n", @@ -423,6 +425,9 @@ wait: cvp_free_fence_data(f); + if (rc && state != QUEUE_ACTIVE) + goto exit; + goto wait; exit: @@ -1277,10 +1282,8 @@ static int cvp_drain_fence_sched_list(struct msm_cvp_inst *inst) mutex_lock(&q->lock); list_for_each_entry(f, &q->sched_list, list) { ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1); - dprintk(CVP_SYNX, "%s: frame %llu is in sched_list\n", - __func__, ktid); - dprintk(CVP_SYNX, "%s: frameID %llu is in sched_list\n", - __func__, f->frame_id); + dprintk(CVP_SYNX, "%s: frame %llu %llu is in sched_list\n", + __func__, ktid, f->frame_id); ++count; } mutex_unlock(&q->lock); @@ -1312,14 +1315,71 @@ retry: return rc; } +static void cvp_clean_fence_queue(struct msm_cvp_inst *inst, int synx_state) +{ + struct cvp_fence_queue *q; + struct cvp_fence_command *f, *d; + u64 ktid; + + q = &inst->fence_cmd_queue; + + 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_SYNX, "%s: (%#x) flush frame %llu %llu wait_list\n", + __func__, hash32_ptr(inst->session), ktid, f->frame_id); + + list_del_init(&f->list); + msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata); + cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f, synx_state); + cvp_release_synx(inst, f); + 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_SYNX, "%s: (%#x)flush frame %llu %llu sched_list\n", + __func__, hash32_ptr(inst->session), ktid, f->frame_id); + cvp_cancel_synx(inst, CVP_INPUT_SYNX, f, synx_state); + } + + mutex_unlock(&q->lock); +} + +int cvp_stop_clean_fence_queue(struct msm_cvp_inst *inst) +{ + struct cvp_fence_queue *q; + u32 count = 0, max_retries = 100; + + cvp_clean_fence_queue(inst, SYNX_STATE_SIGNALED_ERROR); + cvp_fence_thread_stop(inst); + + /* Waiting for all output synx sent */ + q = &inst->fence_cmd_queue; +retry: + mutex_lock(&q->lock); + if (list_empty(&q->sched_list)) { + mutex_unlock(&q->lock); + return 0; + } + mutex_unlock(&q->lock); + usleep_range(500, 1000); + if (++count > max_retries) + return -EBUSY; + + goto retry; +} + 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__); @@ -1330,40 +1390,15 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) if (!s) return -ECONNRESET; + dprintk(CVP_SESS, "session %llx (%#x)flush all starts\n", + inst, hash32_ptr(inst->session)); q = &inst->fence_cmd_queue; hdev = inst->core->device; - mutex_lock(&q->lock); - q->mode = OP_DRAINING; + cvp_clean_fence_queue(inst, SYNX_STATE_SIGNALED_CANCEL); - list_for_each_entry_safe(f, d, &q->wait_list, list) { - ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1); - - dprintk(CVP_SESS, "%s: flush frame %llu from wait_list\n", - __func__, ktid); - dprintk(CVP_SESS, "%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_synx(inst, CVP_OUTPUT_SYNX, f); - cvp_release_synx(inst, f); - 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_SESS, "%s: flush frame %llu from sched_list\n", - __func__, ktid); - dprintk(CVP_SESS, "%s: flush frameID %llu from sched_list\n", - __func__, f->frame_id); - cvp_cancel_synx(inst, CVP_INPUT_SYNX, f); - } - - mutex_unlock(&q->lock); - - dprintk(CVP_SESS, "%s: send flush to fw\n", __func__); + dprintk(CVP_SESS, "%s: (%#x) send flush to fw\n", + __func__, hash32_ptr(inst->session)); /* Send flush to FW */ rc = call_hfi_op(hdev, session_flush, (void *)inst->session); @@ -1379,7 +1414,8 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) dprintk(CVP_WARN, "%s: wait for signal failed, rc %d\n", __func__, rc); - dprintk(CVP_SESS, "%s: received flush from fw\n", __func__); + dprintk(CVP_SESS, "%s: (%#x) received flush from fw\n", + __func__, hash32_ptr(inst->session)); exit: rc = cvp_drain_fence_sched_list(inst); @@ -1442,6 +1478,8 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id) if (!s) return -ECONNRESET; + dprintk(CVP_SESS, "Session %llx, flush frame with id %llu\n", + inst, frame_id); q = &inst->fence_cmd_queue; mutex_lock(&q->lock); @@ -1455,14 +1493,13 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id) ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1); - dprintk(CVP_SESS, "%s: flush frame %llu from wait_list\n", - __func__, ktid); - dprintk(CVP_SESS, "%s: flush frameID %llu from wait_list\n", - __func__, f->frame_id); + dprintk(CVP_SYNX, "%s: flush frame %llu %llu from wait_list\n", + __func__, ktid, f->frame_id); list_del_init(&f->list); msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata); - cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f); + cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f, + SYNX_STATE_SIGNALED_CANCEL); cvp_release_synx(inst, f); cvp_free_fence_data(f); } @@ -1473,11 +1510,10 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id) ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1); - dprintk(CVP_SESS, "%s: flush frame %llu from sched_list\n", - __func__, ktid); - dprintk(CVP_SESS, "%s: flush frameID %llu from sched_list\n", - __func__, f->frame_id); - cvp_cancel_synx(inst, CVP_INPUT_SYNX, f); + dprintk(CVP_SYNX, "%s: flush frame %llu %llu from sched_list\n", + __func__, ktid, f->frame_id); + cvp_cancel_synx(inst, CVP_INPUT_SYNX, f, + SYNX_STATE_SIGNALED_CANCEL); } mutex_unlock(&q->lock); diff --git a/drivers/media/platform/msm/cvp/msm_cvp.h b/drivers/media/platform/msm/cvp/msm_cvp.h index 5875b631c109..b21864b46f1c 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp.h +++ b/drivers/media/platform/msm/cvp/msm_cvp.h @@ -33,4 +33,5 @@ int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg); int msm_cvp_session_init(struct msm_cvp_inst *inst); int msm_cvp_session_deinit(struct msm_cvp_inst *inst); int msm_cvp_session_queue_stop(struct msm_cvp_inst *inst); +int cvp_stop_clean_fence_queue(struct msm_cvp_inst *inst); #endif diff --git a/drivers/media/platform/msm/cvp/msm_cvp_buf.c b/drivers/media/platform/msm/cvp/msm_cvp_buf.c index f67c2a25f792..ac56cd26895f 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_buf.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_buf.c @@ -498,6 +498,10 @@ static void msm_cvp_unmap_frame_buf(struct msm_cvp_inst *inst, } else if (atomic_dec_and_test(&smem->refcount)) { clear_bit(smem->bitmap_index, &inst->dma_cache.usage_bitmap); + dprintk(CVP_MEM, "smem %x %d iova %#x to be reused\n", + hash32_ptr(inst->session), + smem->size, + smem->device_addr); } } @@ -515,7 +519,8 @@ void msm_cvp_unmap_frame(struct msm_cvp_inst *inst, u64 ktid) } ktid &= (FENCE_BIT - 1); - dprintk(CVP_MEM, "%s: unmap frame %llu\n", __func__, ktid); + dprintk(CVP_MEM, "%s: (%#x) unmap frame %llu\n", + __func__, hash32_ptr(inst->session), ktid); found = false; mutex_lock(&inst->frames.lock); diff --git a/drivers/media/platform/msm/cvp/msm_cvp_common.c b/drivers/media/platform/msm/cvp/msm_cvp_common.c index 446a90d06f61..ef375d2e0e19 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_common.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_common.c @@ -402,6 +402,8 @@ int wait_for_sess_signal_receipt(struct msm_cvp_inst *inst, call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data); dump_hfi_queue(hdev->hfi_device_data); rc = -EIO; + } else if (inst->state == MSM_CVP_CORE_INVALID) { + rc = -ECONNRESET; } else { rc = 0; } @@ -623,7 +625,7 @@ static void handle_sys_error(enum hal_command_response cmd, void *data) struct msm_cvp_core *core = NULL; struct cvp_hfi_device *hdev = NULL; struct msm_cvp_inst *inst = NULL; - int rc = 0; + int i, rc = 0; unsigned long flags = 0; enum cvp_core_state cur_state; @@ -663,6 +665,10 @@ static void handle_sys_error(enum hal_command_response cmd, void *data) inst->cur_cmd_type, inst->state); if (inst->state != MSM_CVP_CORE_INVALID) { change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID); + if (cvp_stop_clean_fence_queue(inst)) + dprintk(CVP_ERR, "Failed to clean fences\n"); + for (i = 0; i < ARRAY_SIZE(inst->completions); i++) + complete(&inst->completions[i]); spin_lock_irqsave(&inst->event_handler.lock, flags); inst->event_handler.event = CVP_SSR_EVENT; spin_unlock_irqrestore( diff --git a/drivers/media/platform/msm/cvp/msm_cvp_synx.c b/drivers/media/platform/msm/cvp/msm_cvp_synx.c index a114ff6f9cc7..f70fb4013058 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_synx.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_synx.c @@ -73,8 +73,8 @@ int cvp_import_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc, rc = synx_import(ssid, ¶ms); if (rc) { dprintk(CVP_ERR, - "%s: synx_import failed\n", - __func__); + "%s: %d synx_import failed\n", + __func__, h_synx); return rc; } } @@ -102,8 +102,8 @@ int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc) rc = synx_release(ssid, h_synx); if (rc) dprintk(CVP_ERR, - "%s: synx_release %d failed\n", - __func__, i); + "%s: synx_release %d, %d failed\n", + __func__, h_synx, i); } } return rc; @@ -111,14 +111,14 @@ int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc) static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst, enum cvp_synx_type type, - struct cvp_fence_command *fc) + struct cvp_fence_command *fc, + int synx_state) { 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; @@ -137,11 +137,12 @@ static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst, h_synx = fc->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; - } + dprintk(CVP_SYNX, "Cancel synx %d session %llx\n", + h_synx, inst); + if (rc) + dprintk(CVP_ERR, + "%s: synx_signal %d %d %d failed\n", + __func__, h_synx, i, synx_state); } } @@ -151,14 +152,14 @@ static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst, } int cvp_cancel_synx(struct msm_cvp_inst *inst, enum cvp_synx_type type, - struct cvp_fence_command *fc) + struct cvp_fence_command *fc, int synx_state) { if (fc->signature != 0xFEEDFACE) { dprintk(CVP_ERR, "%s deprecated synx path\n", __func__); return -EINVAL; } - return cvp_cancel_synx_impl(inst, type, fc); + return cvp_cancel_synx_impl(inst, type, fc, synx_state); } static int cvp_wait_synx(struct synx_session ssid, u32 *synx, u32 num_synx, @@ -186,6 +187,8 @@ static int cvp_wait_synx(struct synx_session ssid, u32 *synx, u32 num_synx, } return rc; } + dprintk(CVP_SYNX, "Wait synx %d returned succes\n", + h_synx); } ++i; } @@ -203,10 +206,12 @@ static int cvp_signal_synx(struct synx_session ssid, u32 *synx, u32 num_synx, if (h_synx) { rc = synx_signal(ssid, h_synx, synx_state); if (rc) { - dprintk(CVP_ERR, "%s: synx_signal %d failed\n", - current->comm, i); + dprintk(CVP_ERR, + "%s: synx_signal %d %d failed\n", + current->comm, h_synx, i); synx_state = SYNX_STATE_SIGNALED_ERROR; } + dprintk(CVP_SYNX, "Signaled synx %d\n", h_synx); } ++i; } diff --git a/drivers/media/platform/msm/cvp/msm_cvp_synx.h b/drivers/media/platform/msm/cvp/msm_cvp_synx.h index 27c0052fa8f9..135890a574b2 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_synx.h +++ b/drivers/media/platform/msm/cvp/msm_cvp_synx.h @@ -48,7 +48,7 @@ int cvp_import_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc, u32 *fence); int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc); int cvp_cancel_synx(struct msm_cvp_inst *inst, enum cvp_synx_type type, - struct cvp_fence_command *fc); + struct cvp_fence_command *fc, int synx_state); int cvp_synx_ops(struct msm_cvp_inst *inst, enum cvp_synx_type type, struct cvp_fence_command *fc, u32 *synx_state); void cvp_dump_fence_queue(struct msm_cvp_inst *inst);