aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoic Poulain <[email protected]>2021-06-21 21:46:10 +0530
committerGreg Kroah-Hartman <[email protected]>2021-06-24 15:51:49 +0200
commit44b1eba44dc537edf076f131f1eeee7544d0e04f (patch)
tree64d12ce0919b4207c331f3c40126227a00706025
parentab1afed701d2db7eb35c1a2526a29067a38e93d1 (diff)
bus: mhi: core: Fix power down latency
On graceful power-down/disable transition, when an MHI reset is performed, the MHI device loses its context, including interrupt configuration. However, the current implementation is waiting for event(irq) driven state change to confirm reset has been completed, which never happens, and causes reset timeout, leading to unexpected high latency of the mhi_power_down procedure (up to 45 seconds). Fix that by moving to the recently introduced poll_reg_field method, waiting for the reset bit to be cleared, in the same way as the power_on procedure. Cc: [email protected] Fixes: a6e2e3522f29 ("bus: mhi: core: Add support for PM state transitions") Signed-off-by: Loic Poulain <[email protected]> Reviewed-by: Bhaumik Bhatt <[email protected]> Reviewed-by: Manivannan Sadhasivam <[email protected]> Reviewed-by: Hemant Kumar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Manivannan Sadhasivam <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
-rw-r--r--drivers/bus/mhi/core/pm.c18
1 files changed, 5 insertions, 13 deletions
diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
index e2e59a341fef..704a5e225097 100644
--- a/drivers/bus/mhi/core/pm.c
+++ b/drivers/bus/mhi/core/pm.c
@@ -465,23 +465,15 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl)
/* Trigger MHI RESET so that the device will not access host memory */
if (!MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state)) {
- u32 in_reset = -1;
- unsigned long timeout = msecs_to_jiffies(mhi_cntrl->timeout_ms);
-
dev_dbg(dev, "Triggering MHI Reset in device\n");
mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET);
/* Wait for the reset bit to be cleared by the device */
- ret = wait_event_timeout(mhi_cntrl->state_event,
- mhi_read_reg_field(mhi_cntrl,
- mhi_cntrl->regs,
- MHICTRL,
- MHICTRL_RESET_MASK,
- MHICTRL_RESET_SHIFT,
- &in_reset) ||
- !in_reset, timeout);
- if (!ret || in_reset)
- dev_err(dev, "Device failed to exit MHI Reset state\n");
+ ret = mhi_poll_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL,
+ MHICTRL_RESET_MASK, MHICTRL_RESET_SHIFT, 0,
+ 25000);
+ if (ret)
+ dev_err(dev, "Device failed to clear MHI Reset\n");
/*
* Device will clear BHI_INTVEC as a part of RESET processing,