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

Commit 1958a17f authored by Hemant Kumar's avatar Hemant Kumar
Browse files

mhi: core: Prevent suspend until channel operation is complete



Host allows to go to fast suspend while waiting for channel operations
such as start/stop to complete. Upon completion of channel ops host is
unable to respond back to remote clients in time because it is suspended.
Fix this issue by incrementing pending packet count as well as blocking
runtime/system suspend until channel operation is completed.

CRs-Fixed: 2528767
Change-Id: I9c2cff94cdc256ad529688ffbfd05883af9fb85f
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
parent cd914bbc
Loading
Loading
Loading
Loading
+22 −11
Original line number Diff line number Diff line
@@ -1731,15 +1731,16 @@ int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
		goto error_pm_state;
	}

	atomic_inc(&mhi_cntrl->pending_pkts);
	mhi_cntrl->wake_toggle(mhi_cntrl);
	if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state))
		mhi_trigger_resume(mhi_cntrl);
	read_unlock_bh(&mhi_cntrl->pm_lock);
	mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data);
	mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data);

	ret = mhi_send_cmd(mhi_cntrl, mhi_chan, MHI_CMD_START_CHAN);
	if (ret) {
		MHI_ERR("Failed to send start chan cmd\n");
		goto error_pm_state;
		goto error_dec_pendpkt;
	}

	ret = wait_for_completion_timeout(&mhi_chan->completion,
@@ -1748,9 +1749,11 @@ int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
		MHI_ERR("Failed to receive cmd completion for chan:%d\n",
			mhi_chan->chan);
		ret = -EIO;
		goto error_pm_state;
		goto error_dec_pendpkt;
	}

	atomic_dec(&mhi_cntrl->pending_pkts);

	write_lock_irq(&mhi_chan->lock);
	mhi_chan->ch_state = MHI_CH_STATE_ENABLED;
	write_unlock_irq(&mhi_chan->lock);
@@ -1796,6 +1799,8 @@ int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,

	return 0;

error_dec_pendpkt:
	atomic_dec(&mhi_cntrl->pending_pkts);
error_pm_state:
	if (!mhi_chan->offload_ch)
		mhi_deinit_chan_ctxt(mhi_cntrl, mhi_chan);
@@ -1954,15 +1959,16 @@ static void __mhi_unprepare_channel(struct mhi_controller *mhi_cntrl,
		goto error_invalid_state;
	}

	atomic_inc(&mhi_cntrl->pending_pkts);
	mhi_cntrl->wake_toggle(mhi_cntrl);
	if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state))
		mhi_trigger_resume(mhi_cntrl);
	read_unlock_bh(&mhi_cntrl->pm_lock);

	mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data);
	mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data);
	ret = mhi_send_cmd(mhi_cntrl, mhi_chan, MHI_CMD_RESET_CHAN);
	if (ret) {
		MHI_ERR("Failed to send reset chan cmd\n");
		goto error_invalid_state;
		goto error_dec_pendpkt;
	}

	/* even if it fails we will still reset */
@@ -1971,6 +1977,8 @@ static void __mhi_unprepare_channel(struct mhi_controller *mhi_cntrl,
	if (!ret || mhi_chan->ccs != MHI_EV_CC_SUCCESS)
		MHI_ERR("Failed to receive cmd completion, still resetting\n");

error_dec_pendpkt:
	atomic_dec(&mhi_cntrl->pending_pkts);
error_invalid_state:
	if (!mhi_chan->offload_ch) {
		mhi_reset_chan(mhi_cntrl, mhi_chan);
@@ -2145,15 +2153,16 @@ static int mhi_update_channel_state(struct mhi_controller *mhi_cntrl,
		goto error_chan_state;
	}

	atomic_inc(&mhi_cntrl->pending_pkts);
	mhi_cntrl->wake_toggle(mhi_cntrl);
	if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state))
		mhi_trigger_resume(mhi_cntrl);
	read_unlock_bh(&mhi_cntrl->pm_lock);
	mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data);
	mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data);

	ret = mhi_send_cmd(mhi_cntrl, mhi_chan, cmd);
	if (ret) {
		MHI_ERR("Failed to send start chan cmd\n");
		goto error_chan_state;
		goto error_dec_pendpkt;
	}

	ret = wait_for_completion_timeout(&mhi_chan->completion,
@@ -2162,7 +2171,7 @@ static int mhi_update_channel_state(struct mhi_controller *mhi_cntrl,
		MHI_ERR("Failed to receive cmd completion for chan:%d\n",
			mhi_chan->chan);
		ret = -EIO;
		goto error_chan_state;
		goto error_dec_pendpkt;
	}

	ret = 0;
@@ -2170,6 +2179,8 @@ static int mhi_update_channel_state(struct mhi_controller *mhi_cntrl,
	MHI_VERB("chan:%d successfully transition to state:%s\n",
		 mhi_chan->chan, cmd == MHI_CMD_START_CHAN ? "START" : "STOP");

error_dec_pendpkt:
	atomic_dec(&mhi_cntrl->pending_pkts);
error_chan_state:
	mutex_unlock(&mhi_chan->mutex);