From 41ded75b517eb123e8055a89c0af2354e9a3976e Mon Sep 17 00:00:00 2001 From: Bhaumik Bhatt Date: Thu, 11 Jun 2020 18:26:07 -0700 Subject: [PATCH] mhi: core: Add extra checks for RDDM event handling If the device enters RDDM when the host is in a fast/DRV suspended state, MHI host may end up skipping the check from BHI interrupt handling as a host resume may remain pending for a while. Once the host resume is triggered by the controller, MHI host can either walk the primary event ring to discover the RDDM EE event or check the execution environment post the DRV resume and notify the controller of the error condition as fallbacks to the original method of using the BHI interrupt. Change-Id: I93b678981a5ffd640c1dce15b90bf7bcd2e24971 Signed-off-by: Bhaumik Bhatt --- drivers/bus/mhi/core/mhi_main.c | 16 ++++++++++++++++ drivers/bus/mhi/core/mhi_pm.c | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/drivers/bus/mhi/core/mhi_main.c b/drivers/bus/mhi/core/mhi_main.c index cb0ba6b6e4f3..b2c98d9890df 100644 --- a/drivers/bus/mhi/core/mhi_main.c +++ b/drivers/bus/mhi/core/mhi_main.c @@ -1259,6 +1259,22 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, st = MHI_ST_TRANSITION_MISSION_MODE; break; case MHI_EE_RDDM: + if (mhi_cntrl->ee == MHI_EE_RDDM || + mhi_cntrl->power_down) + break; + + MHI_ERR("RDDM event occurred!\n"); + write_lock_irq(&mhi_cntrl->pm_lock); + mhi_cntrl->ee = MHI_EE_RDDM; + write_unlock_irq(&mhi_cntrl->pm_lock); + + /* notify critical clients */ + mhi_control_error(mhi_cntrl); + + mhi_cntrl->status_cb(mhi_cntrl, + mhi_cntrl->priv_data, + MHI_CB_EE_RDDM); + wake_up_all(&mhi_cntrl->state_event); break; default: MHI_ERR("Unhandled EE event:%s\n", diff --git a/drivers/bus/mhi/core/mhi_pm.c b/drivers/bus/mhi/core/mhi_pm.c index a54903307b8d..08d33c9aa1e9 100644 --- a/drivers/bus/mhi/core/mhi_pm.c +++ b/drivers/bus/mhi/core/mhi_pm.c @@ -1488,6 +1488,26 @@ int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_client) return -EIO; } + if (mhi_cntrl->rddm_supported) { + if (mhi_get_exec_env(mhi_cntrl) == MHI_EE_RDDM && + !mhi_cntrl->power_down) { + mhi_cntrl->ee = MHI_EE_RDDM; + write_unlock_irq(&mhi_cntrl->pm_lock); + + MHI_ERR("RDDM event occurred!\n"); + + /* notify critical clients with early notifications */ + mhi_control_error(mhi_cntrl); + + mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, + MHI_CB_EE_RDDM); + wake_up_all(&mhi_cntrl->state_event); + + tasklet_enable(&mhi_cntrl->mhi_event->task); + goto exit_pm_fast_resume; + } + } + /* restore the states */ mhi_cntrl->pm_state = mhi_cntrl->saved_pm_state; mhi_cntrl->dev_state = mhi_cntrl->saved_dev_state; @@ -1531,6 +1551,7 @@ int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_client) /* schedules worker if any special purpose events need to be handled */ mhi_special_events_pending(mhi_cntrl); +exit_pm_fast_resume: MHI_LOG("Exit with pm_state:%s dev_state:%s\n", to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_STATE_STR(mhi_cntrl->dev_state));