diff mbox series

bus: mhi: core: Fix power down latency

Message ID 1619598574-11928-1-git-send-email-loic.poulain@linaro.org
State Superseded
Headers show
Series bus: mhi: core: Fix power down latency | expand

Commit Message

Loic Poulain April 28, 2021, 8:29 a.m. UTC
On gracefull power-down/disable transition, a MHI reset is performed,
the MHI device then looses its context, including interrupt config.
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.

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.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>

---
 drivers/bus/mhi/core/pm.c | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

-- 
2.7.4

Comments

Bhaumik Bhatt April 28, 2021, 8:09 p.m. UTC | #1
On 2021-04-28 01:29 AM, Loic Poulain wrote:
> On gracefull power-down/disable transition, a MHI reset is performed,

On _graceful_ power-down/disable transition, _when an_ MHI reset is 
performed,
> the MHI device then looses its context, including interrupt config.

the MHI device _loses_ its context, including interrupt configuration.
> However the current implementation is waiting for event(irq) driven

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.

> 

> 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.

> 

> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>

> ---

>  drivers/bus/mhi/core/pm.c | 17 +++++------------

>  1 file changed, 5 insertions(+), 12 deletions(-)

> 

> diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c

> index e2e59a3..9c61d3f 100644

> --- a/drivers/bus/mhi/core/pm.c

> +++ b/drivers/bus/mhi/core/pm.c

> @@ -3,7 +3,6 @@

>   * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.

>   *

>   */

> -

>  #include <linux/delay.h>

>  #include <linux/device.h>

>  #include <linux/dma-direction.h>

> @@ -471,17 +470,11 @@ static void mhi_pm_disable_transition(struct

> mhi_controller *mhi_cntrl)

>  		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,


Thanks,
Bhaumik
---
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum,
a Linux Foundation Collaborative Project
diff mbox series

Patch

diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
index e2e59a3..9c61d3f 100644
--- a/drivers/bus/mhi/core/pm.c
+++ b/drivers/bus/mhi/core/pm.c
@@ -3,7 +3,6 @@ 
  * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
  *
  */
-
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dma-direction.h>
@@ -471,17 +470,11 @@  static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl)
 		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,