Merge "msm: vidc: Amend error handling"
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index c2a93a96..e5d1576 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -337,26 +337,26 @@
cmd_done.device_id = device_id;
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
cmd_done.status = hfi_map_err_status(pkt->event_data1);
+ info->response.cmd = cmd_done;
dprintk(VIDC_INFO, "Received: SESSION_ERROR with event id : %#x %#x\n",
pkt->event_data1, pkt->event_data2);
switch (pkt->event_data1) {
+ /* Ignore below errors */
case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
- case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
- case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
- cmd_done.status = VIDC_ERR_NONE;
dprintk(VIDC_INFO, "Non Fatal: HFI_EVENT_SESSION_ERROR\n");
info->response_type = HAL_RESPONSE_UNUSED;
- info->response.cmd = cmd_done;
- return 0;
+ break;
default:
+ /* All other errors are not expected and treated as sys error */
dprintk(VIDC_ERR,
- "HFI_EVENT_SESSION_ERROR: data1 %#x, data2 %#x\n",
- pkt->event_data1, pkt->event_data2);
- info->response_type = HAL_SESSION_ERROR;
- info->response.cmd = cmd_done;
- return 0;
+ "%s: data1 %#x, data2 %#x, treat as sys error\n",
+ __func__, pkt->event_data1, pkt->event_data2);
+ info->response_type = HAL_SYS_ERROR;
+ break;
}
+
+ return 0;
}
static int hfi_process_event_notify(u32 device_id,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 21ad17a..98a59a5 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -918,6 +918,10 @@
}
fail_start:
+ if (rc) {
+ dprintk(VIDC_ERR, "%s: kill session %pK\n", __func__, inst);
+ msm_comm_kill_session(inst);
+ }
return rc;
}
@@ -1601,13 +1605,25 @@
}
EXPORT_SYMBOL(msm_vidc_open);
-static void cleanup_instance(struct msm_vidc_inst *inst)
+static void msm_vidc_cleanup_instance(struct msm_vidc_inst *inst)
{
+ struct msm_vidc_buffer *temp, *dummy;
+
if (!inst) {
dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
return;
}
+ mutex_lock(&inst->registeredbufs.lock);
+ list_for_each_entry_safe(temp, dummy, &inst->registeredbufs.list,
+ list) {
+ print_vidc_buffer(VIDC_ERR, "undequeud buf", inst, temp);
+ msm_comm_unmap_vidc_buffer(inst, temp);
+ list_del(&temp->list);
+ kfree(temp);
+ }
+ mutex_unlock(&inst->registeredbufs.lock);
+
msm_comm_free_freq_table(inst);
if (msm_comm_release_scratch_buffers(inst, false))
@@ -1661,18 +1677,18 @@
msm_comm_ctrl_deinit(inst);
- DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
- DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
- DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
- DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
- DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
-
v4l2_fh_del(&inst->event_handler);
v4l2_fh_exit(&inst->event_handler);
for (i = 0; i < MAX_PORT_NUM; i++)
vb2_queue_release(&inst->bufq[i].vb2_bufq);
+ DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
+ DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
+ DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
+ DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
+ DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
+
mutex_destroy(&inst->sync_lock);
mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
mutex_destroy(&inst->bufq[OUTPUT_PORT].lock);
@@ -1695,7 +1711,6 @@
int msm_vidc_close(void *instance)
{
struct msm_vidc_inst *inst = instance;
- struct msm_vidc_buffer *temp, *dummy;
int rc = 0;
if (!inst || !inst->core) {
@@ -1707,30 +1722,20 @@
* Make sure that HW stop working on these buffers that
* we are going to free.
*/
- if (inst->state != MSM_VIDC_CORE_INVALID &&
- inst->core->state != VIDC_CORE_INVALID)
- rc = msm_comm_try_state(inst,
- MSM_VIDC_RELEASE_RESOURCES_DONE);
-
- mutex_lock(&inst->registeredbufs.lock);
- list_for_each_entry_safe(temp, dummy, &inst->registeredbufs.list,
- list) {
- print_vidc_buffer(VIDC_ERR, "undequeud buf", inst, temp);
- msm_comm_unmap_vidc_buffer(inst, temp);
- list_del(&temp->list);
- kfree(temp);
- }
- mutex_unlock(&inst->registeredbufs.lock);
-
- cleanup_instance(inst);
- if (inst->state != MSM_VIDC_CORE_INVALID &&
- inst->core->state != VIDC_CORE_INVALID)
- rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
- else
- rc = msm_comm_force_cleanup(inst);
+ rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
if (rc)
dprintk(VIDC_ERR,
- "Failed to move video instance to uninit state\n");
+ "Failed to move inst %pK to rel resource done state\n",
+ inst);
+
+ msm_vidc_cleanup_instance(inst);
+
+ rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to move inst %pK to uninit state\n", inst);
+ rc = msm_comm_force_cleanup(inst);
+ }
msm_comm_session_clean(inst);
msm_smem_delete_client(inst->mem_client);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 61c4d7b..844a4e1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1175,11 +1175,6 @@
if (!rc) {
dprintk(VIDC_ERR, "Wait interrupted or timed out: %d\n",
SESSION_MSG_INDEX(cmd));
- call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
- dprintk(VIDC_ERR,
- "sess resp timeout can potentially crash the system\n");
- msm_comm_print_debug_info(inst);
- msm_vidc_handle_hw_error(inst->core);
msm_comm_kill_session(inst);
rc = -EIO;
} else {
@@ -1951,7 +1946,6 @@
hdev = inst->core->device;
dprintk(VIDC_WARN, "Session error received for session %pK\n", inst);
- change_inst_state(inst, MSM_VIDC_CORE_INVALID);
if (response->status == VIDC_ERR_MAX_CLIENTS) {
dprintk(VIDC_WARN, "Too many clients, rejecting %pK", inst);
@@ -1989,7 +1983,6 @@
dprintk(VIDC_WARN, "%s: Core %pK\n", __func__, core);
mutex_lock(&core->lock);
- core->state = VIDC_CORE_INVALID;
list_for_each_entry(inst, &core->instances, list) {
mutex_lock(&inst->lock);
@@ -2026,52 +2019,37 @@
}
mutex_lock(&core->lock);
- if (core->state == VIDC_CORE_INVALID ||
- core->state == VIDC_CORE_UNINIT) {
+ if (core->state == VIDC_CORE_UNINIT) {
dprintk(VIDC_ERR,
- "%s: Core already moved to state %d\n",
- __func__, core->state);
+ "%s: Core %pK already moved to state %d\n",
+ __func__, core, core->state);
mutex_unlock(&core->lock);
return;
}
- mutex_unlock(&core->lock);
- dprintk(VIDC_WARN, "SYS_ERROR %d received for core %pK\n", cmd, core);
- msm_comm_clean_notify_client(core);
-
- hdev = core->device;
- mutex_lock(&core->lock);
- if (core->state == VIDC_CORE_INVALID) {
- dprintk(VIDC_DBG, "Calling core_release\n");
- rc = call_hfi_op(hdev, core_release,
- hdev->hfi_device_data);
- if (rc) {
- dprintk(VIDC_ERR, "core_release failed\n");
- mutex_unlock(&core->lock);
- return;
- }
- core->state = VIDC_CORE_UNINIT;
- }
- mutex_unlock(&core->lock);
-
- msm_vidc_print_running_insts(core);
+ dprintk(VIDC_WARN, "SYS_ERROR received for core %pK\n", core);
call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
+ list_for_each_entry(inst, &core->instances, list) {
+ dprintk(VIDC_WARN,
+ "%s: Send sys error for inst %pK\n", __func__, inst);
+ change_inst_state(inst, MSM_VIDC_CORE_INVALID);
+ msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
+ msm_comm_print_inst_info(inst);
+ }
+ hdev = core->device;
+ dprintk(VIDC_DBG, "Calling core_release\n");
+ rc = call_hfi_op(hdev, core_release, hdev->hfi_device_data);
+ if (rc) {
+ dprintk(VIDC_ERR, "core_release failed\n");
+ mutex_unlock(&core->lock);
+ return;
+ }
+ core->state = VIDC_CORE_UNINIT;
+ mutex_unlock(&core->lock);
+
dprintk(VIDC_ERR,
"SYS_ERROR can potentially crash the system\n");
- /*
- * For SYS_ERROR, there will not be any inst pointer.
- * Just grab one of the inst from instances list and
- * use it.
- */
-
- mutex_lock(&core->lock);
- inst = list_first_entry_or_null(&core->instances,
- struct msm_vidc_inst, list);
- mutex_unlock(&core->lock);
-
- msm_comm_print_debug_info(inst);
-
msm_vidc_handle_hw_error(core);
}
@@ -2084,19 +2062,22 @@
dprintk(VIDC_ERR, "%s invalid params\n", __func__);
return;
}
+ if (!inst->session) {
+ dprintk(VIDC_DBG, "%s: inst %pK session already cleaned\n",
+ __func__, inst);
+ return;
+ }
hdev = inst->core->device;
mutex_lock(&inst->lock);
- if (hdev && inst->session) {
- dprintk(VIDC_DBG, "cleaning up instance: %pK\n", inst);
- rc = call_hfi_op(hdev, session_clean,
- (void *)inst->session);
- if (rc) {
- dprintk(VIDC_ERR,
- "Session clean failed :%pK\n", inst);
- }
- inst->session = NULL;
+ dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
+ rc = call_hfi_op(hdev, session_clean,
+ (void *)inst->session);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Session clean failed :%pK\n", inst);
}
+ inst->session = NULL;
mutex_unlock(&inst->lock);
}
@@ -2586,31 +2567,26 @@
hdev = inst->core->device;
abort_completion = SESSION_MSG_INDEX(HAL_SESSION_ABORT_DONE);
+ dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
rc = call_hfi_op(hdev, session_abort, (void *)inst->session);
if (rc) {
dprintk(VIDC_ERR,
"%s session_abort failed rc: %d\n", __func__, rc);
- return rc;
+ goto exit;
}
rc = wait_for_completion_timeout(
&inst->completions[abort_completion],
msecs_to_jiffies(
inst->core->resources.msm_vidc_hw_rsp_timeout));
if (!rc) {
- dprintk(VIDC_ERR,
- "%s: Wait interrupted or timed out [%pK]: %d\n",
- __func__, inst, abort_completion);
- call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
- dprintk(VIDC_ERR,
- "ABORT timeout can potentially crash the system\n");
- msm_comm_print_debug_info(inst);
-
- msm_vidc_handle_hw_error(inst->core);
+ dprintk(VIDC_ERR, "%s: inst %pK abort timed out\n",
+ __func__, inst);
+ msm_comm_generate_sys_error(inst);
rc = -EBUSY;
} else {
rc = 0;
}
- msm_comm_session_clean(inst);
+exit:
return rc;
}
@@ -2765,7 +2741,7 @@
"%s: capabilities memory is expected to be freed\n",
__func__);
}
-
+ dprintk(VIDC_DBG, "%s: core %pK\n", __func__, core);
rc = call_hfi_op(hdev, core_init, hdev->hfi_device_data);
if (rc) {
dprintk(VIDC_ERR, "Failed to init core, id = %d\n",
@@ -2825,13 +2801,12 @@
* e.g. thumbnail generation.
*/
schedule_delayed_work(&core->fw_unload_work,
- msecs_to_jiffies(core->state == VIDC_CORE_INVALID ?
- 0 :
- core->resources.msm_vidc_firmware_unload_delay));
+ msecs_to_jiffies(core->state == VIDC_CORE_INIT_DONE ?
+ core->resources.msm_vidc_firmware_unload_delay : 0));
dprintk(VIDC_DBG, "firmware unload delayed by %u ms\n",
- core->state == VIDC_CORE_INVALID ?
- 0 : core->resources.msm_vidc_firmware_unload_delay);
+ core->state == VIDC_CORE_INIT_DONE ?
+ core->resources.msm_vidc_firmware_unload_delay : 0);
}
core_already_uninited:
@@ -2875,6 +2850,7 @@
msm_comm_init_clocks_and_bus_data(inst);
+ dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
rc = call_hfi_op(hdev, session_init, hdev->hfi_device_data,
inst, get_hal_domain(inst->session_type),
get_hal_codec(fourcc),
@@ -2940,19 +2916,17 @@
dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
return -EINVAL;
}
-
- core = inst->core;
- if (core->state == VIDC_CORE_INVALID) {
- dprintk(VIDC_ERR,
- "Core is in bad state can't do load res\n");
- return -EINVAL;
- }
-
if (inst->state == MSM_VIDC_CORE_INVALID) {
dprintk(VIDC_ERR,
- "Instance is in invalid state can't do load res\n");
+ "%s: inst %pK is in invalid state\n", __func__, inst);
return -EINVAL;
}
+ if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
+ dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
+ inst, inst->state);
+ goto exit;
+ }
+ core = inst->core;
num_mbs_per_sec =
msm_comm_get_load(core, MSM_VIDC_DECODER, quirks) +
@@ -2965,18 +2939,12 @@
dprintk(VIDC_ERR, "HW is overloaded, needed: %d max: %d\n",
num_mbs_per_sec, max_load_adj);
msm_vidc_print_running_insts(core);
- inst->state = MSM_VIDC_CORE_INVALID;
msm_comm_kill_session(inst);
return -EBUSY;
}
hdev = core->device;
- if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
- dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
- inst, inst->state);
- goto exit;
- }
-
+ dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
rc = call_hfi_op(hdev, session_load_res, (void *) inst->session);
if (rc) {
dprintk(VIDC_ERR,
@@ -2997,21 +2965,19 @@
dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
return -EINVAL;
}
- if (inst->state == MSM_VIDC_CORE_INVALID ||
- inst->core->state == VIDC_CORE_INVALID) {
+ if (inst->state == MSM_VIDC_CORE_INVALID) {
dprintk(VIDC_ERR,
- "Core is in bad state can't do start\n");
+ "%s: inst %pK is in invalid\n", __func__, inst);
return -EINVAL;
}
-
- hdev = inst->core->device;
-
if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) {
dprintk(VIDC_INFO,
"inst: %pK is already in state: %d\n",
inst, inst->state);
goto exit;
}
+ hdev = inst->core->device;
+ dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
rc = call_hfi_op(hdev, session_start, (void *) inst->session);
if (rc) {
dprintk(VIDC_ERR,
@@ -3032,18 +2998,23 @@
dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
return -EINVAL;
}
- hdev = inst->core->device;
-
+ if (inst->state == MSM_VIDC_CORE_INVALID) {
+ dprintk(VIDC_ERR,
+ "%s: inst %pK is in invalid state\n", __func__, inst);
+ return -EINVAL;
+ }
if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) {
dprintk(VIDC_INFO,
"inst: %pK is already in state: %d\n",
inst, inst->state);
goto exit;
}
- dprintk(VIDC_DBG, "Send Stop to hal\n");
+ hdev = inst->core->device;
+ dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
rc = call_hfi_op(hdev, session_stop, (void *) inst->session);
if (rc) {
- dprintk(VIDC_ERR, "Failed to send stop\n");
+ dprintk(VIDC_ERR, "%s: inst %pK session_stop failed\n",
+ __func__, inst);
goto exit;
}
change_inst_state(inst, MSM_VIDC_STOP);
@@ -3060,16 +3031,19 @@
dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
return -EINVAL;
}
- hdev = inst->core->device;
-
+ if (inst->state == MSM_VIDC_CORE_INVALID) {
+ dprintk(VIDC_ERR,
+ "%s: inst %pK is in invalid state\n", __func__, inst);
+ return -EINVAL;
+ }
if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) {
dprintk(VIDC_INFO,
"inst: %pK is already in state: %d\n",
inst, inst->state);
goto exit;
}
- dprintk(VIDC_DBG,
- "Send release res to hal\n");
+ hdev = inst->core->device;
+ dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
rc = call_hfi_op(hdev, session_release_res, (void *) inst->session);
if (rc) {
dprintk(VIDC_ERR,
@@ -3091,15 +3065,14 @@
dprintk(VIDC_ERR, "%s invalid params\n", __func__);
return -EINVAL;
}
- hdev = inst->core->device;
if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) {
dprintk(VIDC_INFO,
"inst: %pK is already in state: %d\n",
inst, inst->state);
goto exit;
}
- dprintk(VIDC_DBG,
- "Send session close to hal\n");
+ hdev = inst->core->device;
+ dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
rc = call_hfi_op(hdev, session_end, (void *) inst->session);
if (rc) {
dprintk(VIDC_ERR,
@@ -3132,7 +3105,7 @@
}
mutex_lock(&core->lock);
- if (core->state == VIDC_CORE_INVALID) {
+ if (core->state != VIDC_CORE_INIT_DONE) {
dprintk(VIDC_ERR,
"%s - fw is not in proper state, skip suspend\n",
__func__);
@@ -3490,30 +3463,23 @@
{
int rc = 0;
int flipped_state;
- struct msm_vidc_core *core;
if (!inst) {
- dprintk(VIDC_ERR,
- "Invalid instance pointer = %pK\n", inst);
+ dprintk(VIDC_ERR, "%s: invalid params %pK", __func__, inst);
return -EINVAL;
}
dprintk(VIDC_DBG,
"Trying to move inst: %pK from: %#x to %#x\n",
inst, inst->state, state);
- core = inst->core;
- if (!core) {
- dprintk(VIDC_ERR,
- "Invalid core pointer = %pK\n", inst);
+
+ mutex_lock(&inst->sync_lock);
+ if (inst->state == MSM_VIDC_CORE_INVALID) {
+ dprintk(VIDC_ERR, "%s: inst %pK is in invalid\n",
+ __func__, inst);
+ mutex_unlock(&inst->sync_lock);
return -EINVAL;
}
- mutex_lock(&inst->sync_lock);
- if (inst->state == MSM_VIDC_CORE_INVALID ||
- core->state == VIDC_CORE_INVALID) {
- dprintk(VIDC_ERR,
- "Core is in bad state can't change the state\n");
- rc = -EINVAL;
- goto exit;
- }
+
flipped_state = get_flipped_state(inst->state, state);
dprintk(VIDC_DBG,
"flipped_state = %#x\n", flipped_state);
@@ -3593,15 +3559,17 @@
rc = -EINVAL;
break;
}
-exit:
mutex_unlock(&inst->sync_lock);
- if (rc)
+
+ if (rc) {
dprintk(VIDC_ERR,
"Failed to move from state: %d to %d\n",
inst->state, state);
- else
+ msm_comm_kill_session(inst);
+ } else {
trace_msm_vidc_common_state_change((void *)inst,
inst->state, state);
+ }
return rc;
}
@@ -3631,14 +3599,6 @@
switch (which_cmd) {
case V4L2_QCOM_CMD_FLUSH:
- if (core->state != VIDC_CORE_INVALID &&
- inst->state == MSM_VIDC_CORE_INVALID) {
- rc = msm_comm_kill_session(inst);
- if (rc)
- dprintk(VIDC_ERR,
- "Fail to clean session: %d\n",
- rc);
- }
rc = msm_comm_flush(inst, flags);
if (rc) {
dprintk(VIDC_ERR,
@@ -4252,13 +4212,6 @@
"%s: Wait interrupted or timed out [%pK]: %d\n",
__func__, inst,
SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO));
- inst->state = MSM_VIDC_CORE_INVALID;
- call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
- dprintk(VIDC_ERR,
- "SESS_PROP timeout can potentially crash the system\n");
- msm_comm_print_debug_info(inst);
-
- msm_vidc_handle_hw_error(inst->core);
msm_comm_kill_session(inst);
rc = -ETIMEDOUT;
goto exit;
@@ -4333,9 +4286,7 @@
buffer_info.num_buffers = 1;
buffer_info.align_device_addr = handle->device_addr;
if (inst->buffer_mode_set[CAPTURE_PORT] ==
- HAL_BUFFER_MODE_STATIC &&
- inst->state != MSM_VIDC_CORE_INVALID &&
- core->state != VIDC_CORE_INVALID) {
+ HAL_BUFFER_MODE_STATIC) {
buffer_info.response_required = false;
rc = call_hfi_op(hdev, session_release_buffers,
(void *)inst->session, &buffer_info);
@@ -4441,26 +4392,23 @@
buffer_info.buffer_type = buf->buffer_type;
buffer_info.num_buffers = 1;
buffer_info.align_device_addr = handle->device_addr;
- if (inst->state != MSM_VIDC_CORE_INVALID &&
- core->state != VIDC_CORE_INVALID) {
- buffer_info.response_required = true;
- rc = call_hfi_op(hdev, session_release_buffers,
+ buffer_info.response_required = true;
+ rc = call_hfi_op(hdev, session_release_buffers,
(void *)inst->session, &buffer_info);
- if (rc) {
- dprintk(VIDC_WARN,
- "Rel scrtch buf fail:%x, %d\n",
- buffer_info.align_device_addr,
- buffer_info.buffer_size);
- }
+ if (!rc) {
mutex_unlock(&inst->scratchbufs.lock);
rc = wait_for_sess_signal_receipt(inst,
HAL_SESSION_RELEASE_BUFFER_DONE);
- if (rc) {
- change_inst_state(inst,
- MSM_VIDC_CORE_INVALID);
- msm_comm_kill_session(inst);
- }
+ if (rc)
+ dprintk(VIDC_WARN,
+ "%s: wait for signal failed, rc %d\n",
+ __func__, rc);
mutex_lock(&inst->scratchbufs.lock);
+ } else {
+ dprintk(VIDC_WARN,
+ "Rel scrtch buf fail:%x, %d\n",
+ buffer_info.align_device_addr,
+ buffer_info.buffer_size);
}
/*If scratch buffers can be reused, do not free the buffers*/
@@ -4532,25 +4480,23 @@
buffer_info.buffer_type = buf->buffer_type;
buffer_info.num_buffers = 1;
buffer_info.align_device_addr = handle->device_addr;
- if (inst->state != MSM_VIDC_CORE_INVALID &&
- core->state != VIDC_CORE_INVALID) {
- buffer_info.response_required = true;
- rc = call_hfi_op(hdev, session_release_buffers,
+ buffer_info.response_required = true;
+ rc = call_hfi_op(hdev, session_release_buffers,
(void *)inst->session, &buffer_info);
- if (rc) {
- dprintk(VIDC_WARN,
- "Rel prst buf fail:%x, %d\n",
- buffer_info.align_device_addr,
- buffer_info.buffer_size);
- }
+ if (!rc) {
mutex_unlock(&inst->persistbufs.lock);
rc = wait_for_sess_signal_receipt(inst,
HAL_SESSION_RELEASE_BUFFER_DONE);
- if (rc) {
- change_inst_state(inst, MSM_VIDC_CORE_INVALID);
- msm_comm_kill_session(inst);
- }
+ if (rc)
+ dprintk(VIDC_WARN,
+ "%s: wait for signal failed, rc %d\n",
+ __func__, rc);
mutex_lock(&inst->persistbufs.lock);
+ } else {
+ dprintk(VIDC_WARN,
+ "Rel prst buf fail:%x, %d\n",
+ buffer_info.align_device_addr,
+ buffer_info.buffer_size);
}
list_del(&buf->list);
msm_comm_smem_free(inst, handle);
@@ -5083,7 +5029,6 @@
core = inst->core;
rc = msm_vidc_load_supported(inst);
if (rc) {
- change_inst_state(inst, MSM_VIDC_CORE_INVALID);
dprintk(VIDC_WARN,
"%s: Hardware is overloaded\n", __func__);
return rc;
@@ -5110,7 +5055,7 @@
if (!rc && inst->prop.width[CAPTURE_PORT] >
capability->width.max) {
dprintk(VIDC_ERR,
- "Unsupported width = %u supported max width = %u",
+ "Unsupported width = %u supported max width = %u\n",
inst->prop.width[CAPTURE_PORT],
capability->width.max);
rc = -ENOTSUPP;
@@ -5132,7 +5077,6 @@
}
}
if (rc) {
- change_inst_state(inst, MSM_VIDC_CORE_INVALID);
dprintk(VIDC_ERR,
"%s: Resolution unsupported\n", __func__);
}
@@ -5144,12 +5088,11 @@
enum hal_command_response cmd = HAL_SESSION_ERROR;
struct msm_vidc_cb_cmd_done response = {0};
- dprintk(VIDC_WARN, "msm_comm_generate_session_error\n");
if (!inst || !inst->core) {
dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
return;
}
-
+ dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
response.session_id = inst;
response.status = VIDC_ERR_FAIL;
handle_session_error(cmd, (void *)&response);
@@ -5165,6 +5108,7 @@
dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
return;
}
+ dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
core = inst->core;
response.device_id = (u32) core->id;
handle_sys_error(cmd, (void *) &response);
@@ -5179,10 +5123,13 @@
dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
return -EINVAL;
} else if (!inst->session) {
- /* There's no hfi session to kill */
+ dprintk(VIDC_ERR, "%s: no session to kill for inst %pK\n",
+ __func__, inst);
return 0;
}
+ dprintk(VIDC_WARN, "%s: inst %pK, state %d\n", __func__,
+ inst, inst->state);
/*
* We're internally forcibly killing the session, if fw is aware of
* the session send session_abort to firmware to clean up and release
@@ -5191,20 +5138,18 @@
if ((inst->state >= MSM_VIDC_OPEN_DONE &&
inst->state < MSM_VIDC_CLOSE_DONE) ||
inst->state == MSM_VIDC_CORE_INVALID) {
- if (msm_comm_session_abort(inst)) {
- msm_comm_generate_sys_error(inst);
- return 0;
+ rc = msm_comm_session_abort(inst);
+ if (rc) {
+ dprintk(VIDC_WARN, "%s: inst %pK abort failed\n",
+ __func__, inst);
+ change_inst_state(inst, MSM_VIDC_CORE_INVALID);
}
- change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
- msm_comm_generate_session_error(inst);
- } else {
- dprintk(VIDC_WARN,
- "Inactive session %pK, triggering an internal session error\n",
- inst);
- msm_comm_generate_session_error(inst);
-
}
+ change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
+ msm_comm_session_clean(inst);
+
+ dprintk(VIDC_WARN, "%s: inst %pK handled\n", __func__, inst);
return rc;
}
@@ -5624,8 +5569,7 @@
hdev = inst->core->device;
mutex_lock(&inst->lock);
if (inst->state >= MSM_VIDC_RELEASE_RESOURCES_DONE ||
- inst->state < MSM_VIDC_START_DONE ||
- inst->core->state == VIDC_CORE_INVALID) {
+ inst->state < MSM_VIDC_START_DONE) {
dprintk(VIDC_DBG,
"Inst %pK : Not in valid state to call %s\n",
inst, __func__);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 677ee89..49e6c3ec 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -83,7 +83,6 @@
VIDC_CORE_UNINIT = 0,
VIDC_CORE_INIT,
VIDC_CORE_INIT_DONE,
- VIDC_CORE_INVALID
};
/*
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index dad4b60..0069e40 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -90,6 +90,8 @@
static int __initialize_packetization(struct venus_hfi_device *device);
static struct hal_session *__get_session(struct venus_hfi_device *device,
u32 session_id);
+static bool __is_session_valid(struct venus_hfi_device *device,
+ struct hal_session *session, const char *func);
static int __set_clocks(struct venus_hfi_device *device, u32 freq);
static int __iface_cmdq_write(struct venus_hfi_device *device,
void *pkt);
@@ -1668,11 +1670,9 @@
static int venus_hfi_core_init(void *device)
{
+ int rc = 0;
struct hfi_cmd_sys_init_packet pkt;
struct hfi_cmd_sys_get_property_packet version_pkt;
- int rc = 0;
- struct list_head *ptr, *next;
- struct hal_session *session = NULL;
struct venus_hfi_device *dev;
if (!device) {
@@ -1683,6 +1683,7 @@
dev = device;
mutex_lock(&dev->lock);
+ dprintk(VIDC_DBG, "Core initializing\n");
rc = __load_fw(dev);
if (rc) {
dprintk(VIDC_ERR, "Failed to load Venus FW\n");
@@ -1691,20 +1692,6 @@
__set_state(dev, VENUS_STATE_INIT);
- list_for_each_safe(ptr, next, &dev->sess_head) {
- /*
- * This means that session list is not empty. Kick stale
- * sessions out of our valid instance list, but keep the
- * list_head inited so that list_del (in the future, called
- * by session_clean()) will be valid. When client doesn't close
- * them, then it is a genuine leak which driver can't fix.
- */
- session = list_entry(ptr, struct hal_session, list);
- list_del_init(&session->list);
- }
-
- INIT_LIST_HEAD(&dev->sess_head);
-
if (!dev->hal_client) {
dev->hal_client = msm_smem_new_client(
SMEM_ION, dev->res, MSM_VIDC_UNKNOWN);
@@ -1766,21 +1753,23 @@
pm_qos_add_request(&dev->qos, PM_QOS_CPU_DMA_LATENCY,
dev->res->pm_qos_latency_us);
}
-
+ dprintk(VIDC_DBG, "Core inited successfully\n");
mutex_unlock(&dev->lock);
return rc;
err_core_init:
__set_state(dev, VENUS_STATE_DEINIT);
__unload_fw(dev);
err_load_fw:
+ dprintk(VIDC_ERR, "Core init failed\n");
mutex_unlock(&dev->lock);
return rc;
}
static int venus_hfi_core_release(void *dev)
{
- struct venus_hfi_device *device = dev;
int rc = 0;
+ struct venus_hfi_device *device = dev;
+ struct hal_session *session, *next;
if (!device) {
dprintk(VIDC_ERR, "invalid device\n");
@@ -1788,7 +1777,7 @@
}
mutex_lock(&device->lock);
-
+ dprintk(VIDC_DBG, "Core releasing\n");
if (device->res->pm_qos_latency_us &&
pm_qos_request_active(&device->qos))
pm_qos_remove_request(&device->qos);
@@ -1797,6 +1786,11 @@
__set_state(device, VENUS_STATE_DEINIT);
__unload_fw(device);
+ /* unlink all sessions from device */
+ list_for_each_entry_safe(session, next, &device->sess_head, list)
+ list_del(&session->list);
+
+ dprintk(VIDC_DBG, "Core released successfully\n");
mutex_unlock(&device->lock);
return rc;
@@ -1937,6 +1931,10 @@
mutex_lock(&device->lock);
dprintk(VIDC_INFO, "in set_prop,with prop id: %#x\n", ptype);
+ if (!__is_session_valid(device, session, __func__)) {
+ rc = -EINVAL;
+ goto err_set_prop;
+ }
rc = call_hfi_pkt_op(device, session_set_property,
pkt, session, ptype, pdata);
@@ -1979,6 +1977,10 @@
mutex_lock(&device->lock);
dprintk(VIDC_INFO, "%s: property id: %d\n", __func__, ptype);
+ if (!__is_session_valid(device, session, __func__)) {
+ rc = -EINVAL;
+ goto err_create_pkt;
+ }
rc = call_hfi_pkt_op(device, session_get_property,
&pkt, session, ptype);
@@ -2010,8 +2012,25 @@
static void __session_clean(struct hal_session *session)
{
+ struct hal_session *temp, *next;
+ struct venus_hfi_device *device;
+
+ if (!session || !session->device) {
+ dprintk(VIDC_WARN, "%s: invalid params\n", __func__);
+ return;
+ }
+ device = session->device;
dprintk(VIDC_DBG, "deleted the session: %pK\n", session);
- list_del(&session->list);
+ /*
+ * session might have been removed from the device list in
+ * core_release, so check and remove if it is in the list
+ */
+ list_for_each_entry_safe(temp, next, &device->sess_head, list) {
+ if (session == temp) {
+ list_del(&session->list);
+ break;
+ }
+ }
/* Poison the session handle with zeros */
*session = (struct hal_session){ {0} };
kfree(session);
@@ -2105,6 +2124,9 @@
int rc = 0;
struct venus_hfi_device *device = session->device;
+ if (!__is_session_valid(device, session, __func__))
+ return -EINVAL;
+
rc = call_hfi_pkt_op(device, session_cmd,
&pkt, pkt_type, session);
if (rc == -EPERM)
@@ -2190,6 +2212,10 @@
device = session->device;
mutex_lock(&device->lock);
+ if (!__is_session_valid(device, session, __func__)) {
+ rc = -EINVAL;
+ goto err_create_pkt;
+ }
if (buffer_info->buffer_type == HAL_BUFFER_INPUT) {
/*
* Hardware doesn't care about input buffers being
@@ -2234,6 +2260,10 @@
device = session->device;
mutex_lock(&device->lock);
+ if (!__is_session_valid(device, session, __func__)) {
+ rc = -EINVAL;
+ goto err_create_pkt;
+ }
if (buffer_info->buffer_type == HAL_BUFFER_INPUT) {
rc = 0;
goto err_create_pkt;
@@ -2368,6 +2398,9 @@
int rc = 0;
struct venus_hfi_device *device = session->device;
+ if (!__is_session_valid(device, session, __func__))
+ return -EINVAL;
+
if (session->is_decoder) {
struct hfi_cmd_session_empty_buffer_compressed_packet pkt;
@@ -2437,6 +2470,9 @@
struct venus_hfi_device *device = session->device;
struct hfi_cmd_session_fill_buffer_packet pkt;
+ if (!__is_session_valid(device, session, __func__))
+ return -EINVAL;
+
rc = call_hfi_pkt_op(device, session_ftb,
&pkt, session, output_frame);
if (rc) {
@@ -2490,6 +2526,12 @@
device = session->device;
mutex_lock(&device->lock);
+
+ if (!__is_session_valid(device, session, __func__)) {
+ rc = -EINVAL;
+ goto err_etbs_and_ftbs;
+ }
+
for (c = 0; c < num_ftbs; ++c) {
rc = __session_ftb(session, &ftbs[c], true);
if (rc) {
@@ -2537,6 +2579,10 @@
device = session->device;
mutex_lock(&device->lock);
+ if (!__is_session_valid(device, session, __func__)) {
+ rc = -EINVAL;
+ goto err_create_pkt;
+ }
rc = call_hfi_pkt_op(device, session_get_buf_req,
&pkt, session);
if (rc) {
@@ -2567,6 +2613,10 @@
device = session->device;
mutex_lock(&device->lock);
+ if (!__is_session_valid(device, session, __func__)) {
+ rc = -EINVAL;
+ goto err_create_pkt;
+ }
rc = call_hfi_pkt_op(device, session_flush,
&pkt, session, flush_mode);
if (rc) {
@@ -2844,6 +2894,24 @@
kfree(packet);
}
+static bool __is_session_valid(struct venus_hfi_device *device,
+ struct hal_session *session, const char *func)
+{
+ struct hal_session *temp = NULL;
+
+ if (!device || !session)
+ goto invalid;
+
+ list_for_each_entry(temp, &device->sess_head, list)
+ if (session == temp)
+ return true;
+
+invalid:
+ dprintk(VIDC_WARN, "%s: device %pK, invalid session %pK\n",
+ func, device, session);
+ return false;
+}
+
static struct hal_session *__get_session(struct venus_hfi_device *device,
u32 session_id)
{