Ver Fonte

msm: eva: Avoid double session close

In case DSP session creation failed due to reaching max
number of EVA sessions. There is a chance DSP may resend
delete session. Blocks re-deletion attempt.

Change-Id: Idf54a9eff124c60af5867b013de641c93450960f
Signed-off-by: George Shen <[email protected]>
George Shen há 2 anos atrás
pai
commit
1e4ff767c3
5 ficheiros alterados com 73 adições e 49 exclusões
  1. 4 2
      msm/eva/cvp_power.c
  2. 1 1
      msm/eva/msm_cvp_buf.c
  3. 24 19
      msm/eva/msm_cvp_common.c
  4. 15 7
      msm/eva/msm_cvp_core.c
  5. 29 20
      msm/eva/msm_cvp_dsp.c

+ 4 - 2
msm/eva/cvp_power.c

@@ -219,8 +219,10 @@ int msm_cvp_update_power(struct msm_cvp_inst *inst)
 		return -ECONNRESET;
 
 	core = inst->core;
-	if (!core || core->state == CVP_CORE_UNINIT)
-                return -ECONNRESET;
+	if (!core || core->state == CVP_CORE_UNINIT) {
+		rc = -ECONNRESET;
+		goto adjust_exit;
+	}
 
 	clocks = &core->resources.clock_set;
 	cl = &clocks->clock_tbl[clocks->count - 1];

+ 1 - 1
msm/eva/msm_cvp_buf.c

@@ -2190,7 +2190,7 @@ int cvp_release_arp_buffers(struct msm_cvp_inst *inst)
 
 	mutex_lock(&inst->persistbufs.lock);
 	/* Workaround for FW: release buffer means release all */
-	if (inst->state <= MSM_CVP_CLOSE_DONE) {
+	if (inst->state > MSM_CVP_CORE_INIT_DONE && inst->state <= MSM_CVP_CLOSE_DONE) {
 		rc = call_hfi_op(hdev, session_release_buffers,
 				(void *)inst->session);
 		if (!rc) {

+ 24 - 19
msm/eva/msm_cvp_common.c

@@ -139,8 +139,11 @@ static void put_inst_helper(struct kref *kref)
 
 void cvp_put_inst(struct msm_cvp_inst *inst)
 {
-	if (!inst)
+	if (!inst || (kref_read(&inst->kref) < 1)) {
+		dprintk(CVP_ERR, "Invalid session %llx\n", inst);
+		WARN_ON(true);
 		return;
+	}
 
 	kref_put(&inst->kref, put_inst_helper);
 }
@@ -399,6 +402,7 @@ static void handle_session_init_done(enum hal_command_response cmd, void *data)
 {
 	struct msm_cvp_cb_cmd_done *response = data;
 	struct msm_cvp_inst *inst = NULL;
+	struct msm_cvp_core *core;
 
 	if (!response) {
 		dprintk(CVP_ERR,
@@ -406,11 +410,13 @@ static void handle_session_init_done(enum hal_command_response cmd, void *data)
 		return;
 	}
 
+	core = cvp_driver->cvp_core;
 	inst = cvp_get_inst(cvp_driver->cvp_core, response->session_id);
-
 	if (!inst) {
-		dprintk(CVP_WARN, "%s:Got a response for an inactive session\n",
-				__func__);
+		dprintk(CVP_WARN, "%s:Got a response for an inactive session %#x\n",
+				__func__, response->session_id);
+		list_for_each_entry(inst, &core->instances, list)
+			cvp_print_inst(CVP_WARN, inst);
 		return;
 	}
 
@@ -579,6 +585,7 @@ void handle_sys_error(enum hal_command_response cmd, void *data)
 	hdev = core->device;
 
 	mutex_lock(&core->lock);
+	core->ssr_count++;
 	if (core->state == CVP_CORE_UNINIT) {
 		dprintk(CVP_ERR,
 			"%s: Core %pK already moved to state %d\n",
@@ -589,8 +596,8 @@ void handle_sys_error(enum hal_command_response cmd, void *data)
 
 	cur_state = core->state;
 	core->state = CVP_CORE_UNINIT;
-	dprintk(CVP_WARN, "SYS_ERROR received for core %pK cmd %x\n",
-			core, cmd);
+	dprintk(CVP_WARN, "SYS_ERROR from core %pK cmd %x total: %d\n",
+			core, cmd, core->ssr_count);
 	mutex_lock(&core->clk_lock);
 	hfi_device = hdev->hfi_device_data;
 	if (hfi_device->error == CVP_ERR_NOC_ERROR) {
@@ -669,6 +676,7 @@ static void handle_session_close(enum hal_command_response cmd, void *data)
 {
 	struct msm_cvp_cb_cmd_done *response = data;
 	struct msm_cvp_inst *inst;
+	struct msm_cvp_core *core;
 
 	if (!response) {
 		dprintk(CVP_ERR,
@@ -676,10 +684,15 @@ static void handle_session_close(enum hal_command_response cmd, void *data)
 		return;
 	}
 
+	core = cvp_driver->cvp_core;
 	inst = cvp_get_inst(cvp_driver->cvp_core, response->session_id);
 	if (!inst) {
-		dprintk(CVP_WARN, "%s: response for an inactive session\n",
-				__func__);
+		dprintk(CVP_WARN, "%s: response for an inactive session %#x\n",
+				__func__, response->session_id);
+
+		list_for_each_entry(inst, &core->instances, list)
+			cvp_print_inst(CVP_WARN, inst);
+
 		return;
 	}
 
@@ -1165,14 +1178,13 @@ int msm_cvp_noc_error_info(struct msm_cvp_core *core)
 		return 0;
 
 	last_fault_count = core->smmu_fault_count;
-	core->ssr_count++;
 	dprintk(CVP_ERR, "cvp ssr count %d %d %d\n", core->ssr_count,
 			core->resources.max_ssr_allowed,
 			core->smmu_fault_count);
 	hdev = core->device;
 	call_hfi_op(hdev, noc_error_info, hdev->hfi_device_data);
 
-	if (core->ssr_count >= core->resources.max_ssr_allowed)
+	if (core->smmu_fault_count >= core->resources.max_ssr_allowed)
 		BUG_ON(!core->resources.non_fatal_pagefaults);
 
 	return 0;
@@ -1302,15 +1314,8 @@ int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst)
 	 */
 	if (inst->state >= MSM_CVP_OPEN_DONE &&
 			inst->state < MSM_CVP_CLOSE_DONE) {
-		rc = msm_comm_session_abort(inst);
-		if (rc) {
-			dprintk(CVP_ERR,
-				"%s: inst %pK session %x abort failed\n",
-				__func__, inst, hash32_ptr(inst->session));
-			change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID);
-		} else {
-			change_cvp_inst_state(inst, MSM_CVP_CORE_UNINIT);
-		}
+		msm_comm_session_abort(inst);
+		change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID);
 	}
 
 	if (inst->state >= MSM_CVP_CORE_UNINIT) {

+ 15 - 7
msm/eva/msm_cvp_core.c

@@ -176,8 +176,7 @@ struct msm_cvp_inst *msm_cvp_open(int session_type, struct task_struct *task)
 		goto err_invalid_core;
 	}
 
-	pr_info_ratelimited(
-		CVP_DBG_TAG "%s opening cvp instance: %pK type %d cnt %d\n",
+	pr_info(CVP_DBG_TAG "%s opening cvp instance: %pK type %d cnt %d\n",
 		"sess", task->comm, inst, session_type, instance_count);
 	mutex_init(&inst->sync_lock);
 	mutex_init(&inst->lock);
@@ -377,6 +376,11 @@ int msm_cvp_destroy(struct msm_cvp_inst *inst)
 
 	core = inst->core;
 
+	if (inst->session_type == MSM_CVP_DSP) {
+		cvp_dsp_del_sess(inst->dsp_handle, inst);
+		inst->task = NULL;
+	}
+
 	/* Ensure no path has core->clk_lock and core->lock sequence */
 	mutex_lock(&core->lock);
 	mutex_lock(&core->clk_lock);
@@ -404,8 +408,7 @@ int msm_cvp_destroy(struct msm_cvp_inst *inst)
 	__deinit_fence_queue(inst);
 	core->synx_ftbl->cvp_sess_deinit_synx(inst);
 
-	pr_info_ratelimited(
-		CVP_DBG_TAG
+	pr_info(CVP_DBG_TAG
 		"closed cvp instance: %pK session_id = %d type %d %d\n",
 		inst->proc_name, inst, hash32_ptr(inst->session),
 		inst->session_type, core->smem_leak_count);
@@ -447,6 +450,14 @@ int msm_cvp_close(void *instance)
 		return -EINVAL;
 	}
 
+	pr_info(CVP_DBG_TAG
+		"to close instance: %pK session_id = %d type %d state %d\n",
+		inst->proc_name, inst, hash32_ptr(inst->session),
+		inst->session_type, inst->state);
+
+	if (inst->session == 0 || inst->state == MSM_CVP_CORE_UNINIT)
+		return -EINVAL;
+
 	if (inst->session_type != MSM_CVP_BOOT) {
 		msm_cvp_cleanup_instance(inst);
 		msm_cvp_session_deinit(inst);
@@ -461,9 +472,6 @@ int msm_cvp_close(void *instance)
 
 	msm_cvp_comm_session_clean(inst);
 
-	if (inst->session_type == MSM_CVP_DSP)
-		cvp_dsp_del_sess(inst->dsp_handle, inst);
-
 	kref_put(&inst->kref, close_helper);
 	return 0;
 }

+ 29 - 20
msm/eva/msm_cvp_dsp.c

@@ -348,8 +348,9 @@ search_again:
 				mutex_unlock(&me->fastrpc_driver_list.lock);
 				usleep_range(5000, 10000);
 				if (max_count-- == 0) {
-					dprintk(CVP_ERR, "%s timeout\n",
-							__func__);
+					dprintk(CVP_ERR, "%s timeout %d\n",
+						__func__, refcount);
+					WARN_ON(true);
 					goto exit;
 				}
 				goto search_again;
@@ -1516,7 +1517,7 @@ static void print_power(const struct eva_power_req *pwr_req)
 	}
 }
 
-static void __dsp_cvp_sess_create(struct cvp_dsp_cmd_msg *cmd)
+void __dsp_cvp_sess_create(struct cvp_dsp_cmd_msg *cmd)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
 	struct msm_cvp_inst *inst = NULL;
@@ -1547,23 +1548,29 @@ static void __dsp_cvp_sess_create(struct cvp_dsp_cmd_msg *cmd)
 		return;
 	}
 	frpc_node = cvp_get_fastrpc_node_with_handle(dsp2cpu_cmd->pid);
-	if (!frpc_node || !frpc_node->cvp_fastrpc_device) {
-		dprintk(CVP_WARN, "%s cannot get fastrpc node from %x\n",
+	if (!frpc_node) {
+		dprintk(CVP_WARN, "%s cannot get fastrpc node from pid %x\n",
 				__func__, dsp2cpu_cmd->pid);
 		goto fail_lookup;
 	}
+	if (!frpc_node->cvp_fastrpc_device) {
+		dprintk(CVP_WARN, "%s invalid fastrpc device from pid %x\n",
+				__func__, dsp2cpu_cmd->pid);
+		goto fail_pid;
+	}
+
 	frpc_device = frpc_node->cvp_fastrpc_device;
 
 	rc = eva_fastrpc_dev_get_pid(frpc_device, &pid);
 	if (rc) {
 		dprintk(CVP_ERR,
 			"%s Failed to map buffer 0x%x\n", __func__, rc);
-		goto fail_lookup;
+		goto fail_pid;
 	}
 	pid_s = find_get_pid(pid);
 	if (pid_s == NULL) {
 		dprintk(CVP_WARN, "%s incorrect pid %x\n", __func__, pid);
-		goto fail_lookup;
+		goto fail_pid;
 	}
 	dprintk(CVP_DSP, "%s get pid_s 0x%x from hdl 0x%x\n", __func__,
 			pid_s, dsp2cpu_cmd->pid);
@@ -1571,7 +1578,7 @@ static void __dsp_cvp_sess_create(struct cvp_dsp_cmd_msg *cmd)
 	task = get_pid_task(pid_s, PIDTYPE_TGID);
 	if (!task) {
 		dprintk(CVP_WARN, "%s task doesn't exist\n", __func__);
-		goto fail_lookup;
+		goto fail_pid;
 	}
 
 	inst = msm_cvp_open(MSM_CVP_DSP, task);
@@ -1587,10 +1594,11 @@ static void __dsp_cvp_sess_create(struct cvp_dsp_cmd_msg *cmd)
 	inst->prop.is_secure = dsp2cpu_cmd->is_secure;
 	inst->prop.dsp_mask = dsp2cpu_cmd->dsp_access_mask;
 
+	eva_fastrpc_driver_add_sess(frpc_node, inst);
 	rc = msm_cvp_session_create(inst);
 	if (rc) {
 		dprintk(CVP_ERR, "Warning: send Session Create failed\n");
-		goto fail_msm_cvp_open;
+		goto fail_get_session_info;
 	} else {
 		dprintk(CVP_DSP, "%s DSP Session Create done\n", __func__);
 	}
@@ -1606,7 +1614,6 @@ static void __dsp_cvp_sess_create(struct cvp_dsp_cmd_msg *cmd)
 	cmd->session_cpu_high = (uint32_t)((inst_handle & HIGH32) >> 32);
 	cmd->session_cpu_low = (uint32_t)(inst_handle & LOW32);
 
-	eva_fastrpc_driver_add_sess(frpc_node, inst);
 	cvp_put_fastrpc_node(frpc_node);
 
 	inst->task = task;
@@ -1627,13 +1634,15 @@ fail_get_session_info:
 	msm_cvp_close(inst);
 fail_msm_cvp_open:
 	put_task_struct(task);
+fail_pid:
+	cvp_put_fastrpc_node(frpc_node);
 fail_lookup:
 	/* unregister fastrpc driver */
 	eva_fastrpc_driver_unregister(dsp2cpu_cmd->pid, false);
 	cmd->ret = -1;
 }
 
-static void __dsp_cvp_sess_delete(struct cvp_dsp_cmd_msg *cmd)
+void __dsp_cvp_sess_delete(struct cvp_dsp_cmd_msg *cmd)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
 	struct msm_cvp_inst *inst;
@@ -1665,7 +1674,7 @@ static void __dsp_cvp_sess_delete(struct cvp_dsp_cmd_msg *cmd)
 			dsp2cpu_cmd->session_cpu_high,
 			dsp2cpu_cmd->session_cpu_low);
 	if (!inst || !is_cvp_inst_valid(inst)) {
-		dprintk(CVP_ERR, "%s incorrect session ID\n", __func__);
+		dprintk(CVP_ERR, "%s incorrect session ID %llx\n", __func__, inst);
 		cmd->ret = -1;
 		goto dsp_fail_delete;
 	}
@@ -1703,7 +1712,7 @@ dsp_fail_delete:
 	return;
 }
 
-static void __dsp_cvp_power_req(struct cvp_dsp_cmd_msg *cmd)
+void __dsp_cvp_power_req(struct cvp_dsp_cmd_msg *cmd)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
 	struct msm_cvp_inst *inst;
@@ -1759,7 +1768,7 @@ dsp_fail_power_req:
 	return;
 }
 
-static void __dsp_cvp_buf_register(struct cvp_dsp_cmd_msg *cmd)
+void __dsp_cvp_buf_register(struct cvp_dsp_cmd_msg *cmd)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
 	struct msm_cvp_inst *inst;
@@ -1817,7 +1826,7 @@ dsp_fail_buf_reg:
 	kfree(kmd);
 }
 
-static void __dsp_cvp_buf_deregister(struct cvp_dsp_cmd_msg *cmd)
+void __dsp_cvp_buf_deregister(struct cvp_dsp_cmd_msg *cmd)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
 	struct msm_cvp_inst *inst;
@@ -1870,7 +1879,7 @@ fail_dsp_buf_dereg:
 	kfree(kmd);
 }
 
-static void __dsp_cvp_mem_alloc(struct cvp_dsp_cmd_msg *cmd)
+void __dsp_cvp_mem_alloc(struct cvp_dsp_cmd_msg *cmd)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
 	struct msm_cvp_inst *inst;
@@ -1953,7 +1962,7 @@ fail_fastrpc_node:
 
 }
 
-static void __dsp_cvp_mem_free(struct cvp_dsp_cmd_msg *cmd)
+void __dsp_cvp_mem_free(struct cvp_dsp_cmd_msg *cmd)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
 	struct msm_cvp_inst *inst;
@@ -2041,7 +2050,7 @@ fail_fastrpc_dev_unmap_dma:
 	cvp_put_fastrpc_node(frpc_node);
 }
 
-static void __dsp_cvp_sess_start(struct cvp_dsp_cmd_msg *cmd)
+void __dsp_cvp_sess_start(struct cvp_dsp_cmd_msg *cmd)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
 	struct msm_cvp_inst *inst;
@@ -2063,14 +2072,14 @@ static void __dsp_cvp_sess_start(struct cvp_dsp_cmd_msg *cmd)
 
 	rc = msm_cvp_session_start(inst, (struct eva_kmd_arg *)NULL);
 	if (rc) {
-		dprintk(CVP_ERR, "%s Failed to start session\n", __func__);
+		dprintk(CVP_ERR, "%s Failed to start session %llx\n", __func__, inst);
 		cmd->ret = -1;
 		return;
 	}
 	dprintk(CVP_DSP, "%s session started\n", __func__);
 }
 
-static void __dsp_cvp_sess_stop(struct cvp_dsp_cmd_msg *cmd)
+void __dsp_cvp_sess_stop(struct cvp_dsp_cmd_msg *cmd)
 {
 	struct cvp_dsp_apps *me = &gfa_cv;
 	struct msm_cvp_inst *inst;