Browse Source

Merge "video: driver: handle race condition in msm_vidc_core_init"

qctecmdr 4 years ago
parent
commit
849dab200f
3 changed files with 67 additions and 7 deletions
  1. 2 1
      driver/vidc/inc/msm_vidc_core.h
  2. 64 5
      driver/vidc/src/msm_vidc_driver.c
  3. 1 1
      driver/vidc/src/venus_hfi.c

+ 2 - 1
driver/vidc/inc/msm_vidc_core.h

@@ -56,7 +56,8 @@ struct msm_vidc_core_power {
 
 enum msm_vidc_core_state {
 	MSM_VIDC_CORE_DEINIT       = 0,
-	MSM_VIDC_CORE_INIT         = 1,
+	MSM_VIDC_CORE_INIT_WAIT    = 1,
+	MSM_VIDC_CORE_INIT         = 2,
 };
 
 struct msm_vidc_core {

+ 64 - 5
driver/vidc/src/msm_vidc_driver.c

@@ -280,6 +280,7 @@ struct msm_vidc_core_state_name {
 
 static const struct msm_vidc_core_state_name core_state_name_arr[] = {
 	{MSM_VIDC_CORE_DEINIT,           "CORE_DEINIT"                },
+	{MSM_VIDC_CORE_INIT_WAIT,        "CORE_INIT_WAIT"             },
 	{MSM_VIDC_CORE_INIT,             "CORE_INIT"                  },
 };
 
@@ -3776,6 +3777,61 @@ unlock:
 	return rc;
 }
 
+static void __fatal_error(struct msm_vidc_core *core, bool fatal)
+{
+	return;
+	fatal &= core->capabilities[HW_RESPONSE_TIMEOUT].value;
+	MSM_VIDC_ERROR(fatal);
+}
+
+static void __strict_check(struct msm_vidc_core *core)
+{
+	__fatal_error(core, !mutex_is_locked(&core->lock));
+}
+
+static int msm_vidc_core_init_wait(struct msm_vidc_core *core)
+{
+	static const int interval = 40;
+	int max_tries, count = 0, rc = 0;
+
+	if (!core || !core->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	__strict_check(core);
+
+	if (core->state != MSM_VIDC_CORE_INIT_WAIT)
+		return 0;
+
+	d_vpr_h("%s(): waiting for state change\n", __func__);
+	max_tries = core->capabilities[HW_RESPONSE_TIMEOUT].value / interval;
+	/**
+	 * attempt one more time to ensure triggering init_done
+	 * timeout sequence for 1st session, incase response not
+	 * received in reverse thread.
+	 */
+	while (count < max_tries + 1) {
+		if (core->state != MSM_VIDC_CORE_INIT_WAIT)
+			break;
+
+		core_unlock(core, __func__);
+		msleep_interruptible(interval);
+		core_lock(core, __func__);
+		count++;
+	}
+	d_vpr_h("%s: state %s, interval %u, count %u, max_tries %u\n", __func__,
+		core_state_name(core->state), interval, count, max_tries);
+
+	/* treat as fatal and fail session_open */
+	if (core->state == MSM_VIDC_CORE_INIT_WAIT) {
+		d_vpr_e("%s: state change failed\n", __func__);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
 int msm_vidc_core_init(struct msm_vidc_core *core)
 {
 	int rc = 0;
@@ -3786,12 +3842,14 @@ int msm_vidc_core_init(struct msm_vidc_core *core)
 	}
 
 	core_lock(core, __func__);
-	if (core->state == MSM_VIDC_CORE_INIT) {
-		rc = 0;
+	rc = msm_vidc_core_init_wait(core);
+	if (rc)
+		goto unlock;
+
+	if (core->state == MSM_VIDC_CORE_INIT)
 		goto unlock;
-	}
 
-	msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT, __func__);
+	msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT_WAIT, __func__);
 	init_completion(&core->init_done);
 	core->smmu_fault_handled = false;
 	core->ssr.trigger = false;
@@ -3812,6 +3870,7 @@ int msm_vidc_core_init(struct msm_vidc_core *core)
 		d_vpr_e("%s: core init timed out\n", __func__);
 		rc = -ETIMEDOUT;
 	} else {
+		msm_vidc_change_core_state(core, MSM_VIDC_CORE_INIT, __func__);
 		d_vpr_h("%s: system init wait completed\n", __func__);
 		rc = 0;
 	}
@@ -4015,7 +4074,7 @@ void msm_vidc_ssr_handler(struct work_struct *work)
 	ssr = &core->ssr;
 
 	core_lock(core, __func__);
-	if (core->state == MSM_VIDC_CORE_INIT) {
+	if (core->state != MSM_VIDC_CORE_DEINIT) {
 		/*
 		 * In current implementation, user-initiated SSR triggers
 		 * a fatal error from hardware. However, there is no way

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

@@ -189,7 +189,7 @@ static void __strict_check(struct msm_vidc_core *core)
 
 bool __core_in_valid_state(struct msm_vidc_core *core)
 {
-	return core->state == MSM_VIDC_CORE_INIT;
+	return core->state != MSM_VIDC_CORE_DEINIT;
 }
 
 bool is_sys_cache_present(struct msm_vidc_core *core)