Selaa lähdekoodia

video: driver: fix deadlock issue with response workqueue

Both &inst->stats_work and &inst->response_work both were using
&inst->response_workq for scheduling works. From reverse thread
handle_session_response_work_handler incremented refcount via
get_inst_ref(), at the same time driverfd got closed by HAL.
So strongref is held by handle_session_response_work_handler and
as part of put_inst(refcount is zero), will attempt to destry
&inst->response_workq inside msm_vidc_close_helper.

destroy_workqueue() call will wait until all already fired events
to complete, which will never happen in this case i.e leading to
deadlock situation. It is an attempt to self destruction, which is
not allowed.

Added changes to avoid above mentioned situation.

Change-Id: Ieb26a4b02f87f2bb738027cfd16e4c261b756dc3
Signed-off-by: Govindaraj Rajagopal <[email protected]>
Govindaraj Rajagopal 3 vuotta sitten
vanhempi
sitoutus
ae4e77ad42

+ 1 - 0
driver/vidc/inc/venus_hfi_response.h

@@ -20,6 +20,7 @@ void handle_session_response_work_handler(struct work_struct *work);
 int handle_session_response_work(struct msm_vidc_inst *inst,
 	struct response_work *work);
 int cancel_response_work(struct msm_vidc_inst *inst);
+int cancel_response_work_sync(struct msm_vidc_inst *inst);
 int handle_system_error(struct msm_vidc_core *core,
 	struct hfi_packet *pkt);
 void fw_coredump(struct msm_vidc_core *core);

+ 1 - 1
driver/vidc/src/msm_vidc.c

@@ -953,13 +953,13 @@ int msm_vidc_close(void *instance)
 
 	i_vpr_h(inst, "%s()\n", __func__);
 	inst_lock(inst, __func__);
-	cancel_response_work(inst);
 	/* print final stats */
 	msm_vidc_print_stats(inst);
 	msm_vidc_session_close(inst);
 	msm_vidc_remove_session(inst);
 	msm_vidc_destroy_buffers(inst);
 	inst_unlock(inst, __func__);
+	cancel_response_work_sync(inst);
 	cancel_stats_work_sync(inst);
 	msm_vidc_show_stats(inst);
 	put_inst(inst);

+ 11 - 0
driver/vidc/src/venus_hfi_response.c

@@ -1748,6 +1748,17 @@ int cancel_response_work(struct msm_vidc_inst *inst)
 	return 0;
 }
 
+int cancel_response_work_sync(struct msm_vidc_inst *inst)
+{
+	if (!inst) {
+		d_vpr_e("%s: Invalid arguments\n", __func__);
+		return -EINVAL;
+	}
+	cancel_delayed_work_sync(&inst->response_work);
+
+	return 0;
+}
+
 static int handle_session_response(struct msm_vidc_core *core,
 	struct hfi_header *hdr)
 {