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

Commit baf786b6 authored by Bhaumik Bhatt's avatar Bhaumik Bhatt
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 daa8e902
Loading
Loading
Loading
Loading
+30 −24
Original line number Diff line number Diff line
@@ -1329,6 +1329,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:
@@ -1336,13 +1340,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",
@@ -1523,9 +1520,6 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl,
		goto exit_no_lock;
	}

	if (mhi_cntrl->need_force_m3 && !mhi_cntrl->force_m3_done)
		goto exit_no_lock;

	ret = __mhi_device_get_sync(mhi_cntrl);
	if (ret)
		goto exit_no_lock;
@@ -1706,13 +1700,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,
@@ -1720,20 +1718,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 −16
Original line number Diff line number Diff line
@@ -471,12 +471,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);

@@ -584,8 +588,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 */
@@ -649,8 +651,6 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
	wake_up_all(&mhi_cntrl->state_event);
	flush_work(&mhi_cntrl->special_work);

	mhi_cntrl->force_m3_done = false;

	if (sfr_info && sfr_info->buf_addr) {
		mhi_free_coherent(mhi_cntrl, sfr_info->len, sfr_info->buf_addr,
				  sfr_info->dma_addr);
@@ -837,6 +837,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);
}

@@ -862,14 +866,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:
@@ -956,6 +955,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);
@@ -983,6 +983,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:
@@ -1049,21 +1050,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);

+0 −2
Original line number Diff line number Diff line
@@ -400,8 +400,6 @@ struct mhi_controller {
	/* controller specific data */
	const char *name;
	bool power_down;
	bool need_force_m3;
	bool force_m3_done;
	void *priv_data;
	void *log_buf;
	struct dentry *dentry;