Browse Source

msm: eva: Avoid double free of DSP dma buffer

In DSP use case, if application failed to free dma buffer before
session end. Kernel driver will free all dma buffers belong to the
dsp session. During this process, same dma buffer was freed twice.
This change is to fix the problem.

Change-Id: I641f9fc0eafbd6fe5c04276085ccd3946e439b41
Signed-off-by: George Shen <[email protected]>
George Shen 3 years ago
parent
commit
79fd263380
2 changed files with 12 additions and 5 deletions
  1. 2 3
      msm/eva/msm_cvp_buf.c
  2. 10 2
      msm/eva/msm_cvp_dsp.c

+ 2 - 3
msm/eva/msm_cvp_buf.c

@@ -841,6 +841,8 @@ int msm_cvp_session_deinit_buffers(struct msm_cvp_inst *inst)
 				dprintk(CVP_ERR,
 				"%s: failed dsp deregistration fd=%d rc=%d",
 				__func__, cbuf->fd, rc);
+			msm_cvp_unmap_smem(inst, cbuf->smem, "unmap dsp");
+			msm_cvp_smem_put_dma_buf(cbuf->smem->dma_buf);
 		} else if (cbuf->ownership == DSP) {
 			rc = cvp_dsp_fastrpc_unmap(inst->process_id, cbuf);
 			if (rc)
@@ -854,9 +856,6 @@ int msm_cvp_session_deinit_buffers(struct msm_cvp_inst *inst)
 					"%s Fail to free buffer 0x%x\n",
 					__func__, rc);
 		}
-
-		msm_cvp_unmap_smem(inst, cbuf->smem, "unmap dsp");
-		msm_cvp_smem_put_dma_buf(cbuf->smem->dma_buf);
 		list_del(&cbuf->list);
 		kmem_cache_free(cvp_driver->buf_cache, cbuf);
 	}

+ 10 - 2
msm/eva/msm_cvp_dsp.c

@@ -1166,6 +1166,7 @@ static void __dsp_cvp_sess_delete(struct cvp_dsp_cmd_msg *cmd)
 	int rc;
 	struct cvp_dsp2cpu_cmd_msg *dsp2cpu_cmd = &me->pending_dsp2cpu_cmd;
 	struct cvp_dsp_fastrpc_driver_entry *frpc_node = NULL;
+	struct task_struct *task = NULL;
 
 	cmd->ret = 0;
 
@@ -1187,6 +1188,11 @@ static void __dsp_cvp_sess_delete(struct cvp_dsp_cmd_msg *cmd)
 	inst = (struct msm_cvp_inst *)ptr_dsp2cpu(
 			dsp2cpu_cmd->session_cpu_high,
 			dsp2cpu_cmd->session_cpu_low);
+	if (!inst) {
+		dprintk(CVP_ERR, "%s incorrect session ID\n", __func__);
+		cmd->ret = -1;
+		goto dsp_fail_delete;
+	}
 
 	rc = msm_cvp_session_delete(inst);
 	if (rc) {
@@ -1195,6 +1201,8 @@ static void __dsp_cvp_sess_delete(struct cvp_dsp_cmd_msg *cmd)
 		goto dsp_fail_delete;
 	}
 
+	task = inst->task;
+
 	rc = msm_cvp_close(inst);
 	if (rc) {
 		dprintk(CVP_ERR, "Warning: Failed to close cvp instance\n");
@@ -1205,8 +1213,8 @@ static void __dsp_cvp_sess_delete(struct cvp_dsp_cmd_msg *cmd)
 	/* unregister fastrpc driver */
 	eva_fastrpc_driver_unregister(dsp2cpu_cmd->pid, false);
 
-	if (inst->task)
-		put_task_struct(inst->task);
+	if (task)
+		put_task_struct(task);
 
 	dprintk(CVP_DSP, "%s DSP2CPU_DETELE_SESSION Done\n", __func__);
 dsp_fail_delete: