Selaa lähdekoodia

msm: eva: Fix nested mutex lock in DSP SSR

rpmsg remove call back hangs with the problem.

Change-Id: I60df9d8772f31778051a905197479aa9f9d61e9f
Signed-off-by: George Shen <[email protected]>
George Shen 3 vuotta sitten
vanhempi
sitoutus
6b7cb5f836
1 muutettua tiedostoa jossa 49 lisäystä ja 33 poistoa
  1. 49 33
      msm/eva/msm_cvp_dsp.c

+ 49 - 33
msm/eva/msm_cvp_dsp.c

@@ -314,14 +314,33 @@ static void eva_fastrpc_driver_release_name(
 		DRIVER_NAME_AVAILABLE;
 }
 
-static void cvp_dsp_rpmsg_remove(struct rpmsg_device *rpdev)
+static struct cvp_dsp_fastrpc_driver_entry *dequeue_frpc_node(void)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
-
 	struct cvp_dsp_fastrpc_driver_entry *frpc_node = NULL;
 	struct list_head *ptr = NULL, *next = NULL;
-	struct list_head *s = NULL, *next_s = NULL;
+
+	ptr = &me->fastrpc_driver_list.list;
+	mutex_lock(&me->fastrpc_driver_list.lock);
+	list_for_each_safe(ptr, next, &me->fastrpc_driver_list.list) {
+		frpc_node = list_entry(ptr,
+			struct cvp_dsp_fastrpc_driver_entry, list);
+
+		if (frpc_node) {
+			list_del(&frpc_node->list);
+			break;
+		}
+	}
+	mutex_unlock(&me->fastrpc_driver_list.lock);
+	return frpc_node;
+}
+
+static void cvp_dsp_rpmsg_remove(struct rpmsg_device *rpdev)
+{
+	struct cvp_dsp_apps *me = &gfa_cv;
+	struct cvp_dsp_fastrpc_driver_entry *frpc_node = NULL;
 	struct msm_cvp_inst *inst = NULL;
+	struct list_head *s = NULL, *next_s = NULL;
 
 	dprintk(CVP_WARN, "%s: CDSP SSR triggered\n", __func__);
 
@@ -332,40 +351,37 @@ static void cvp_dsp_rpmsg_remove(struct rpmsg_device *rpdev)
 	me->state = DSP_UNINIT;
 	mutex_unlock(&me->tx_lock);
 
-	ptr = &me->fastrpc_driver_list.list;
-	mutex_lock(&me->fastrpc_driver_list.lock);
-	list_for_each_safe(ptr, next, &me->fastrpc_driver_list.list) {
-		frpc_node = list_entry(ptr,
-				struct cvp_dsp_fastrpc_driver_entry, list);
-
-		if (frpc_node) {
-			s = &frpc_node->dsp_sessions.list;
-			list_for_each_safe(s, next_s,
-					&frpc_node->dsp_sessions.list) {
-				inst = list_entry(s, struct msm_cvp_inst,
-						dsp_list);
+	while ((frpc_node = dequeue_frpc_node())) {
+		s = &frpc_node->dsp_sessions.list;
+		list_for_each_safe(s, next_s,
+				&frpc_node->dsp_sessions.list) {
+			inst = list_entry(s, struct msm_cvp_inst,
+					dsp_list);
+			if (inst) {
 				delete_dsp_session(inst, frpc_node);
+				mutex_lock(&frpc_node->dsp_sessions.lock);
+				list_del(&inst->dsp_list);
+				frpc_node->session_cnt--;
+				mutex_unlock(&frpc_node->dsp_sessions.lock);
 			}
-
-			dprintk(CVP_DSP, "%s DEINIT_MSM_CVP_LIST 0x%x\n",
-					__func__, frpc_node->dsp_sessions);
-			DEINIT_MSM_CVP_LIST(&frpc_node->dsp_sessions);
-			dprintk(CVP_DSP, "%s list_del fastrpc node 0x%x\n",
-					__func__, frpc_node);
-			list_del(&frpc_node->list);
-			__fastrpc_driver_unregister(
-				&frpc_node->cvp_fastrpc_driver);
-			dprintk(CVP_DSP,
-				"%s Unregistered fastrpc handle 0x%x\n",
-				__func__, frpc_node->handle);
-			mutex_lock(&me->driver_name_lock);
-			eva_fastrpc_driver_release_name(frpc_node);
-			mutex_unlock(&me->driver_name_lock);
-			kfree(frpc_node);
-			frpc_node = NULL;
 		}
+
+		dprintk(CVP_DSP, "%s DEINIT_MSM_CVP_LIST 0x%x\n",
+				__func__, frpc_node->dsp_sessions);
+		DEINIT_MSM_CVP_LIST(&frpc_node->dsp_sessions);
+		dprintk(CVP_DSP, "%s list_del fastrpc node 0x%x\n",
+				__func__, frpc_node);
+		__fastrpc_driver_unregister(
+			&frpc_node->cvp_fastrpc_driver);
+		dprintk(CVP_DSP,
+			"%s Unregistered fastrpc handle 0x%x\n",
+			__func__, frpc_node->handle);
+		mutex_lock(&me->driver_name_lock);
+		eva_fastrpc_driver_release_name(frpc_node);
+		mutex_unlock(&me->driver_name_lock);
+		kfree(frpc_node);
+		frpc_node = NULL;
 	}
-	mutex_unlock(&me->fastrpc_driver_list.lock);
 	dprintk(CVP_WARN, "%s: CDSP SSR handled\n", __func__);
 }