Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a71b4133 authored by Bhaumik Bhatt's avatar Bhaumik Bhatt Committed by Hemant Kumar
Browse files

mhi: core: serialize execution environment and power off changes



Execution environment and power off changes can be serialized
to avoid changing these important controller variables from
multiple places and serialize handling of all state transitions.

Change-Id: I394e5ff4992d7c911e3889f96057d8467d79509c
Signed-off-by: default avatarBhaumik Bhatt <bbhatt@codeaurora.org>
parent 6bc53ff9
Loading
Loading
Loading
Loading
+30 −21
Original line number Diff line number Diff line
@@ -1294,6 +1294,10 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
				TO_MHI_EXEC_STR(event));
			switch (event) {
			case MHI_EE_SBL:
				write_lock_irq(&mhi_cntrl->pm_lock);
				mhi_cntrl->ee = MHI_EE_SBL;
				write_unlock_irq(&mhi_cntrl->pm_lock);
				wake_up_all(&mhi_cntrl->state_event);
				st = MHI_ST_TRANSITION_SBL;
				break;
			case MHI_EE_WFW:
@@ -1301,13 +1305,6 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
				st = MHI_ST_TRANSITION_MISSION_MODE;
				break;
			case MHI_EE_RDDM:
				mhi_cntrl->status_cb(mhi_cntrl,
						     mhi_cntrl->priv_data,
						     MHI_CB_EE_RDDM);
				write_lock_irq(&mhi_cntrl->pm_lock);
				mhi_cntrl->ee = event;
				write_unlock_irq(&mhi_cntrl->pm_lock);
				wake_up_all(&mhi_cntrl->state_event);
				break;
			default:
				MHI_ERR("Unhandled EE event:%s\n",
@@ -1674,13 +1671,17 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev)
	}

	state = mhi_get_mhi_state(mhi_cntrl);
	ee = mhi_cntrl->ee;
	mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl);
	ee = mhi_get_exec_env(mhi_cntrl);
	MHI_LOG("local ee:%s device ee:%s dev_state:%s\n",
		TO_MHI_EXEC_STR(ee),
		TO_MHI_EXEC_STR(mhi_cntrl->ee),
		TO_MHI_EXEC_STR(ee),
		TO_MHI_STATE_STR(state));

	if (mhi_cntrl->power_down) {
		write_unlock_irq(&mhi_cntrl->pm_lock);
		goto exit_intvec;
	}

	if (state == MHI_STATE_SYS_ERR) {
		MHI_ERR("MHI system error detected\n");
		pm_state = mhi_tryset_pm_state(mhi_cntrl,
@@ -1688,20 +1689,28 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev)
	}
	write_unlock_irq(&mhi_cntrl->pm_lock);

	/* if device in rddm don't bother processing sys error */
	if (mhi_cntrl->ee == MHI_EE_RDDM && ee != MHI_EE_DISABLE_TRANSITION) {
		if (mhi_cntrl->ee != ee) {
	if (ee == MHI_EE_RDDM) {
		write_lock_irq(&mhi_cntrl->pm_lock);
		if (mhi_cntrl->ee == MHI_EE_RDDM) {
			write_unlock_irq(&mhi_cntrl->pm_lock);
			goto exit_intvec;
		}
		mhi_cntrl->ee = MHI_EE_RDDM;
		write_unlock_irq(&mhi_cntrl->pm_lock);

		MHI_ERR("RDDM event occurred!\n");
		mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data,
				     MHI_CB_EE_RDDM);
		wake_up_all(&mhi_cntrl->state_event);

		/* notify critical clients with early notifications */
		mhi_control_error(mhi_cntrl);
		}

		goto exit_intvec;
	}

	if (pm_state == MHI_PM_SYS_ERR_DETECT) {
	/* if device is in RDDM, don't bother processing SYS_ERR */
	if (ee != MHI_EE_RDDM && pm_state == MHI_PM_SYS_ERR_DETECT) {
		wake_up_all(&mhi_cntrl->state_event);

		/* for fatal errors, we let controller decide next step */
+19 −14
Original line number Diff line number Diff line
@@ -474,12 +474,16 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl)
		ee = mhi_get_exec_env(mhi_cntrl);
	write_unlock_irq(&mhi_cntrl->pm_lock);

	if (!MHI_IN_MISSION_MODE(ee))
	if (!MHI_IN_MISSION_MODE(ee)) {
		MHI_ERR("Invalid EE:%s\n", TO_MHI_EXEC_STR(ee));
		return -EIO;
	}

	mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data,
			     MHI_CB_EE_MISSION_MODE);
	write_lock_irq(&mhi_cntrl->pm_lock);
	mhi_cntrl->ee = ee;
	write_unlock_irq(&mhi_cntrl->pm_lock);

	wake_up_all(&mhi_cntrl->state_event);

@@ -585,8 +589,6 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
		mhi_cntrl->ee = MHI_EE_DISABLE_TRANSITION;
		mhi_cntrl->dev_state = MHI_STATE_RESET;
	}
	/* notify controller of power down regardless of state transitions */
	mhi_cntrl->power_down = true;
	write_unlock_irq(&mhi_cntrl->pm_lock);

	/* wake up any threads waiting for state transitions */
@@ -830,6 +832,10 @@ void mhi_process_sys_err(struct mhi_controller *mhi_cntrl)
		return;
	}

	write_lock_irq(&mhi_cntrl->pm_lock);
	mhi_cntrl->power_down = true;
	write_unlock_irq(&mhi_cntrl->pm_lock);

	mhi_queue_disable_transition(mhi_cntrl, MHI_PM_SYS_ERR_PROCESS);
}

@@ -855,14 +861,9 @@ void mhi_pm_st_worker(struct work_struct *work)
			if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state))
				mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl);
			write_unlock_irq(&mhi_cntrl->pm_lock);
			if (MHI_IN_PBL(mhi_cntrl->ee))
			mhi_fw_load_handler(mhi_cntrl);
			break;
		case MHI_ST_TRANSITION_SBL:
			write_lock_irq(&mhi_cntrl->pm_lock);
			mhi_cntrl->ee = MHI_EE_SBL;
			write_unlock_irq(&mhi_cntrl->pm_lock);
			wake_up_all(&mhi_cntrl->state_event);
			mhi_create_devices(mhi_cntrl);
			break;
		case MHI_ST_TRANSITION_MISSION_MODE:
@@ -949,6 +950,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
	}

	mhi_cntrl->write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, 0);
	mhi_cntrl->power_down = false;
	mhi_cntrl->pm_state = MHI_PM_POR;
	mhi_cntrl->ee = MHI_EE_MAX;
	current_ee = mhi_get_exec_env(mhi_cntrl);
@@ -976,6 +978,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
	return 0;

error_bhi_offset:
	mhi_cntrl->power_down = true;
	mhi_deinit_free_irq(mhi_cntrl);

error_setup_irq:
@@ -1034,21 +1037,23 @@ void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)
	enum MHI_PM_STATE cur_state;
	enum MHI_PM_STATE transition_state = MHI_PM_SHUTDOWN_PROCESS;

	/* if it's not graceful shutdown, force MHI to a linkdown state */
	if (!graceful) {
	mutex_lock(&mhi_cntrl->pm_mutex);

	write_lock_irq(&mhi_cntrl->pm_lock);
	mhi_cntrl->power_down = true;
	/* if it's not graceful shutdown, force MHI to a linkdown state */
	if (!graceful) {
		cur_state = mhi_tryset_pm_state(mhi_cntrl,
						MHI_PM_LD_ERR_FATAL_DETECT);
		write_unlock_irq(&mhi_cntrl->pm_lock);
		mutex_unlock(&mhi_cntrl->pm_mutex);
		if (cur_state != MHI_PM_LD_ERR_FATAL_DETECT)
			MHI_ERR("Failed to move to state:%s from:%s\n",
				to_mhi_pm_state_str(MHI_PM_LD_ERR_FATAL_DETECT),
				to_mhi_pm_state_str(mhi_cntrl->pm_state));

		transition_state = MHI_PM_SHUTDOWN_NO_ACCESS;
	}
	write_unlock_irq(&mhi_cntrl->pm_lock);

	mutex_unlock(&mhi_cntrl->pm_mutex);

	mhi_queue_disable_transition(mhi_cntrl, transition_state);