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

Commit 57bb869e authored by Bhaumik Bhatt's avatar Bhaumik Bhatt
Browse files

mhi: core: handle disable transitions in EE state worker



It is possible that device asserts or is powered off while
handling mission mode transition. Synchronize device shutdown
or assert handling with processing of other execution
environments to avoid race conditions.

Change-Id: I5253de16b0b6438013b0588d835e65b7a1eea307
Signed-off-by: default avatarBhaumik Bhatt <bbhatt@codeaurora.org>
parent eca47d45
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ const char * const mhi_state_tran_str[MHI_ST_TRANSITION_MAX] = {
	[MHI_ST_TRANSITION_READY] = "READY",
	[MHI_ST_TRANSITION_SBL] = "SBL",
	[MHI_ST_TRANSITION_MISSION_MODE] = "MISSION MODE",
	[MHI_ST_TRANSITION_DISABLE] = "DISABLE",
};

const char * const mhi_state_str[MHI_STATE_MAX] = {
+2 −0
Original line number Diff line number Diff line
@@ -429,6 +429,7 @@ enum MHI_ST_TRANSITION {
	MHI_ST_TRANSITION_READY,
	MHI_ST_TRANSITION_SBL,
	MHI_ST_TRANSITION_MISSION_MODE,
	MHI_ST_TRANSITION_DISABLE,
	MHI_ST_TRANSITION_MAX,
};

@@ -586,6 +587,7 @@ struct mhi_pm_transitions {
struct state_transition {
	struct list_head node;
	enum MHI_ST_TRANSITION state;
	enum MHI_PM_STATE pm_state;
};

struct mhi_ctxt {
+30 −3
Original line number Diff line number Diff line
@@ -626,7 +626,6 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,

	MHI_LOG("Waiting for all pending threads to complete\n");
	wake_up_all(&mhi_cntrl->state_event);
	flush_work(&mhi_cntrl->st_worker);
	flush_work(&mhi_cntrl->fw_worker);
	flush_work(&mhi_cntrl->low_priority_worker);

@@ -721,6 +720,27 @@ int mhi_debugfs_trigger_reset(void *data, u64 val)
	return 0;
}

/* queue disable transition work item */
int mhi_queue_disable_transition(struct mhi_controller *mhi_cntrl,
				 enum MHI_PM_STATE pm_state)
{
	struct state_transition *item = kmalloc(sizeof(*item), GFP_ATOMIC);
	unsigned long flags;

	if (!item)
		return -ENOMEM;

	item->pm_state = pm_state;
	item->state = MHI_ST_TRANSITION_DISABLE;
	spin_lock_irqsave(&mhi_cntrl->transition_lock, flags);
	list_add_tail(&item->node, &mhi_cntrl->transition_list);
	spin_unlock_irqrestore(&mhi_cntrl->transition_lock, flags);

	schedule_work(&mhi_cntrl->st_worker);

	return 0;
}

/* queue a new work item and scheduler work */
int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl,
			       enum MHI_ST_TRANSITION state)
@@ -789,7 +809,7 @@ void mhi_pm_sys_err_worker(struct work_struct *work)
		to_mhi_pm_state_str(mhi_cntrl->pm_state),
		TO_MHI_STATE_STR(mhi_cntrl->dev_state));

	mhi_pm_disable_transition(mhi_cntrl, MHI_PM_SYS_ERR_PROCESS);
	mhi_queue_disable_transition(mhi_cntrl, MHI_PM_SYS_ERR_PROCESS);
}

void mhi_pm_st_worker(struct work_struct *work)
@@ -830,6 +850,9 @@ void mhi_pm_st_worker(struct work_struct *work)
		case MHI_ST_TRANSITION_READY:
			mhi_ready_state_transition(mhi_cntrl);
			break;
		case MHI_ST_TRANSITION_DISABLE:
			mhi_pm_disable_transition(mhi_cntrl, itr->pm_state);
			break;
		default:
			break;
		}
@@ -1006,7 +1029,11 @@ void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)

		transition_state = MHI_PM_SHUTDOWN_NO_ACCESS;
	}
	mhi_pm_disable_transition(mhi_cntrl, transition_state);

	mhi_queue_disable_transition(mhi_cntrl, transition_state);

	MHI_LOG("Wait for shutdown to complete\n");
	flush_work(&mhi_cntrl->st_worker);

	mhi_deinit_debugfs(mhi_cntrl);