Skip to content

Commit

Permalink
bus: mhi: core: Fix power down latency
Browse files Browse the repository at this point in the history
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: a6e2e35 ("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]>
  • Loading branch information
Loic Poulain authored and gregkh committed Jun 24, 2021
1 parent ab1afed commit 44b1eba
Showing 1 changed file with 5 additions and 13 deletions.
18 changes: 5 additions & 13 deletions drivers/bus/mhi/core/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 44b1eba

Please sign in to comment.