linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] usb: chipidea: host: Disable port power only if previously enabled
@ 2019-12-26 15:57 Guenter Roeck
  2019-12-26 19:46 ` Alan Stern
  2019-12-27  1:45 ` Peter Chen
  0 siblings, 2 replies; 12+ messages in thread
From: Guenter Roeck @ 2019-12-26 15:57 UTC (permalink / raw)
  To: Peter Chen
  Cc: Greg Kroah-Hartman, linux-usb, linux-kernel, Guenter Roeck,
	Michael Grzeschik, stable

On shutdown, ehci_power_off() is called unconditionally to power off
each port, even if it was never called to power on the port.
For chipidea, this results in a call to ehci_ci_portpower() with a request
to power off ports even if the port was never powered on.
This results in the following warning from the regulator code.

WARNING: CPU: 0 PID: 182 at drivers/regulator/core.c:2596 _regulator_disable+0x1a8/0x210
unbalanced disables for usb_otg2_vbus
Modules linked in:
CPU: 0 PID: 182 Comm: init Not tainted 5.4.6 #1
Hardware name: Freescale i.MX7 Dual (Device Tree)
[<c0313658>] (unwind_backtrace) from [<c030d698>] (show_stack+0x10/0x14)
[<c030d698>] (show_stack) from [<c1133afc>] (dump_stack+0xe0/0x10c)
[<c1133afc>] (dump_stack) from [<c0349098>] (__warn+0xf4/0x10c)
[<c0349098>] (__warn) from [<c0349128>] (warn_slowpath_fmt+0x78/0xbc)
[<c0349128>] (warn_slowpath_fmt) from [<c09f36ac>] (_regulator_disable+0x1a8/0x210)
[<c09f36ac>] (_regulator_disable) from [<c09f374c>] (regulator_disable+0x38/0xe8)
[<c09f374c>] (regulator_disable) from [<c0df7bac>] (ehci_ci_portpower+0x38/0xdc)
[<c0df7bac>] (ehci_ci_portpower) from [<c0db4fa4>] (ehci_port_power+0x50/0xa4)
[<c0db4fa4>] (ehci_port_power) from [<c0db5420>] (ehci_silence_controller+0x5c/0xc4)
[<c0db5420>] (ehci_silence_controller) from [<c0db7644>] (ehci_stop+0x3c/0xcc)
[<c0db7644>] (ehci_stop) from [<c0d5bdc4>] (usb_remove_hcd+0xe0/0x19c)
[<c0d5bdc4>] (usb_remove_hcd) from [<c0df7638>] (host_stop+0x38/0xa8)
[<c0df7638>] (host_stop) from [<c0df2f34>] (ci_hdrc_remove+0x44/0xe4)
...

Keeping track of the power enable state avoids the warning and traceback.

Fixes: c8679a2fb8dec ("usb: chipidea: host: add portpower override")
Cc: Michael Grzeschik <m.grzeschik@pengutronix.de>
Cc: Peter Chen <peter.chen@freescale.com>
Cc: stable@vger.kernel.org
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/usb/chipidea/host.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index b45ceb91c735..48e4a5ca1835 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -26,6 +26,7 @@ static int (*orig_bus_suspend)(struct usb_hcd *hcd);
 
 struct ehci_ci_priv {
 	struct regulator *reg_vbus;
+	bool enabled;
 };
 
 static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
@@ -37,7 +38,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
 	int ret = 0;
 	int port = HCS_N_PORTS(ehci->hcs_params);
 
-	if (priv->reg_vbus) {
+	if (priv->reg_vbus && enable != priv->enabled) {
 		if (port > 1) {
 			dev_warn(dev,
 				"Not support multi-port regulator control\n");
@@ -53,6 +54,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
 				enable ? "enable" : "disable", ret);
 			return ret;
 		}
+		priv->enabled = enable;
 	}
 
 	if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-26 15:57 [PATCH] usb: chipidea: host: Disable port power only if previously enabled Guenter Roeck
@ 2019-12-26 19:46 ` Alan Stern
  2019-12-27  1:45   ` Peter Chen
  2019-12-27 16:55   ` Guenter Roeck
  2019-12-27  1:45 ` Peter Chen
  1 sibling, 2 replies; 12+ messages in thread
From: Alan Stern @ 2019-12-26 19:46 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Peter Chen, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Michael Grzeschik, stable

On Thu, 26 Dec 2019, Guenter Roeck wrote:

> On shutdown, ehci_power_off() is called unconditionally to power off
> each port, even if it was never called to power on the port.
> For chipidea, this results in a call to ehci_ci_portpower() with a request
> to power off ports even if the port was never powered on.
> This results in the following warning from the regulator code.

That's weird -- we should always power-on every port during hub 
initialization.

It looks like there's a bug in hub.c:hub_activate(): The line under
HUB_INIT which calls hub_power_on() should call
usb_hub_set_port_power() instead.  In fact, the comment near the start
of hub_power_on() is wrong.  It says "Enable power on each port", but
in fact it only enables power for ports that had been powered-on
previously (i.e., the port's bit in hub->power_bits was set).  
Apparently this got messed up in commit ad493e5e5805 ("usb: add usb
port auto power off mechanism").

Now, the chipidea driver may still need to be updated, because 
ehci_turn_off_all_ports() will still be called during shutdown and it 
will try to power-down all ports, even those which are already powered 
down (for example, because the port is suspended).

Alan Stern


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-26 19:46 ` Alan Stern
@ 2019-12-27  1:45   ` Peter Chen
  2019-12-27 14:47     ` Alan Stern
  2019-12-27 16:55   ` Guenter Roeck
  1 sibling, 1 reply; 12+ messages in thread
From: Peter Chen @ 2019-12-27  1:45 UTC (permalink / raw)
  To: Alan Stern
  Cc: Guenter Roeck, Peter Chen, Greg Kroah-Hartman, linux-usb,
	linux-kernel, Michael Grzeschik, stable

On 19-12-26 14:46:15, Alan Stern wrote:
> On Thu, 26 Dec 2019, Guenter Roeck wrote:
> 
> > On shutdown, ehci_power_off() is called unconditionally to power off
> > each port, even if it was never called to power on the port.
> > For chipidea, this results in a call to ehci_ci_portpower() with a request
> > to power off ports even if the port was never powered on.
> > This results in the following warning from the regulator code.
> 
> That's weird -- we should always power-on every port during hub 
> initialization.
> 
> It looks like there's a bug in hub.c:hub_activate(): The line under
> HUB_INIT which calls hub_power_on() should call
> usb_hub_set_port_power() instead.  In fact, the comment near the start
> of hub_power_on() is wrong.  It says "Enable power on each port", but
> in fact it only enables power for ports that had been powered-on
> previously (i.e., the port's bit in hub->power_bits was set).  
> Apparently this got messed up in commit ad493e5e5805 ("usb: add usb
> port auto power off mechanism").
> 
> Now, the chipidea driver may still need to be updated, because 
> ehci_turn_off_all_ports() will still be called during shutdown and it 
> will try to power-down all ports, even those which are already powered 
> down (for example, because the port is suspended).
> 

Hi Alan,

When the port is suspended, why it was turned off? If it was turned
off, how could respond wakeup event?

-- 

Thanks,
Peter Chen

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-26 15:57 [PATCH] usb: chipidea: host: Disable port power only if previously enabled Guenter Roeck
  2019-12-26 19:46 ` Alan Stern
@ 2019-12-27  1:45 ` Peter Chen
  1 sibling, 0 replies; 12+ messages in thread
From: Peter Chen @ 2019-12-27  1:45 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Peter Chen, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Michael Grzeschik, stable

On 19-12-26 07:57:54, Guenter Roeck wrote:
> On shutdown, ehci_power_off() is called unconditionally to power off
> each port, even if it was never called to power on the port.
> For chipidea, this results in a call to ehci_ci_portpower() with a request
> to power off ports even if the port was never powered on.
> This results in the following warning from the regulator code.
> 
> WARNING: CPU: 0 PID: 182 at drivers/regulator/core.c:2596 _regulator_disable+0x1a8/0x210
> unbalanced disables for usb_otg2_vbus
> Modules linked in:
> CPU: 0 PID: 182 Comm: init Not tainted 5.4.6 #1
> Hardware name: Freescale i.MX7 Dual (Device Tree)
> [<c0313658>] (unwind_backtrace) from [<c030d698>] (show_stack+0x10/0x14)
> [<c030d698>] (show_stack) from [<c1133afc>] (dump_stack+0xe0/0x10c)
> [<c1133afc>] (dump_stack) from [<c0349098>] (__warn+0xf4/0x10c)
> [<c0349098>] (__warn) from [<c0349128>] (warn_slowpath_fmt+0x78/0xbc)
> [<c0349128>] (warn_slowpath_fmt) from [<c09f36ac>] (_regulator_disable+0x1a8/0x210)
> [<c09f36ac>] (_regulator_disable) from [<c09f374c>] (regulator_disable+0x38/0xe8)
> [<c09f374c>] (regulator_disable) from [<c0df7bac>] (ehci_ci_portpower+0x38/0xdc)
> [<c0df7bac>] (ehci_ci_portpower) from [<c0db4fa4>] (ehci_port_power+0x50/0xa4)
> [<c0db4fa4>] (ehci_port_power) from [<c0db5420>] (ehci_silence_controller+0x5c/0xc4)
> [<c0db5420>] (ehci_silence_controller) from [<c0db7644>] (ehci_stop+0x3c/0xcc)
> [<c0db7644>] (ehci_stop) from [<c0d5bdc4>] (usb_remove_hcd+0xe0/0x19c)
> [<c0d5bdc4>] (usb_remove_hcd) from [<c0df7638>] (host_stop+0x38/0xa8)
> [<c0df7638>] (host_stop) from [<c0df2f34>] (ci_hdrc_remove+0x44/0xe4)
> ...
> 
> Keeping track of the power enable state avoids the warning and traceback.
> 
> Fixes: c8679a2fb8dec ("usb: chipidea: host: add portpower override")
> Cc: Michael Grzeschik <m.grzeschik@pengutronix.de>
> Cc: Peter Chen <peter.chen@freescale.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> ---
>  drivers/usb/chipidea/host.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
> index b45ceb91c735..48e4a5ca1835 100644
> --- a/drivers/usb/chipidea/host.c
> +++ b/drivers/usb/chipidea/host.c
> @@ -26,6 +26,7 @@ static int (*orig_bus_suspend)(struct usb_hcd *hcd);
>  
>  struct ehci_ci_priv {
>  	struct regulator *reg_vbus;
> +	bool enabled;
>  };
>  
>  static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
> @@ -37,7 +38,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
>  	int ret = 0;
>  	int port = HCS_N_PORTS(ehci->hcs_params);
>  
> -	if (priv->reg_vbus) {
> +	if (priv->reg_vbus && enable != priv->enabled) {
>  		if (port > 1) {
>  			dev_warn(dev,
>  				"Not support multi-port regulator control\n");
> @@ -53,6 +54,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
>  				enable ? "enable" : "disable", ret);
>  			return ret;
>  		}
> +		priv->enabled = enable;
>  	}
>  
>  	if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
> -- 

Acked-by: Peter Chen <peter.chen@nxp.com>

-- 

Thanks,
Peter Chen

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-27  1:45   ` Peter Chen
@ 2019-12-27 14:47     ` Alan Stern
  0 siblings, 0 replies; 12+ messages in thread
From: Alan Stern @ 2019-12-27 14:47 UTC (permalink / raw)
  To: Peter Chen
  Cc: Guenter Roeck, Peter Chen, Greg Kroah-Hartman, linux-usb,
	linux-kernel, Michael Grzeschik, stable

On Fri, 27 Dec 2019, Peter Chen wrote:

> On 19-12-26 14:46:15, Alan Stern wrote:
> > On Thu, 26 Dec 2019, Guenter Roeck wrote:
> > 
> > > On shutdown, ehci_power_off() is called unconditionally to power off
> > > each port, even if it was never called to power on the port.
> > > For chipidea, this results in a call to ehci_ci_portpower() with a request
> > > to power off ports even if the port was never powered on.
> > > This results in the following warning from the regulator code.
> > 
> > That's weird -- we should always power-on every port during hub 
> > initialization.
> > 
> > It looks like there's a bug in hub.c:hub_activate(): The line under
> > HUB_INIT which calls hub_power_on() should call
> > usb_hub_set_port_power() instead.  In fact, the comment near the start
> > of hub_power_on() is wrong.  It says "Enable power on each port", but
> > in fact it only enables power for ports that had been powered-on
> > previously (i.e., the port's bit in hub->power_bits was set).  
> > Apparently this got messed up in commit ad493e5e5805 ("usb: add usb
> > port auto power off mechanism").
> > 
> > Now, the chipidea driver may still need to be updated, because 
> > ehci_turn_off_all_ports() will still be called during shutdown and it 
> > will try to power-down all ports, even those which are already powered 
> > down (for example, because the port is suspended).
> > 
> 
> Hi Alan,
> 
> When the port is suspended, why it was turned off? If it was turned
> off, how could respond wakeup event?

You're right; if a port is powered off then it can't respond to wakeup 
events.

But if the power/wakeup attribute is set to "disabled" then the port 
doesn't need to respond to wakeup events.  In that situation, usbcore 
may decide to power-down the port.

Alan Stern


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-26 19:46 ` Alan Stern
  2019-12-27  1:45   ` Peter Chen
@ 2019-12-27 16:55   ` Guenter Roeck
  2019-12-28 19:33     ` Alan Stern
  1 sibling, 1 reply; 12+ messages in thread
From: Guenter Roeck @ 2019-12-27 16:55 UTC (permalink / raw)
  To: Alan Stern
  Cc: Peter Chen, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Michael Grzeschik, stable

On Thu, Dec 26, 2019 at 02:46:15PM -0500, Alan Stern wrote:
> On Thu, 26 Dec 2019, Guenter Roeck wrote:
> 
> > On shutdown, ehci_power_off() is called unconditionally to power off
> > each port, even if it was never called to power on the port.
> > For chipidea, this results in a call to ehci_ci_portpower() with a request
> > to power off ports even if the port was never powered on.
> > This results in the following warning from the regulator code.
> 
> That's weird -- we should always power-on every port during hub 
> initialization.
> 
That is what I would have assumed, but test code shows that it doesn't
happen.

> It looks like there's a bug in hub.c:hub_activate(): The line under
> HUB_INIT which calls hub_power_on() should call
> usb_hub_set_port_power() instead.  In fact, the comment near the start

usb_hub_set_port_power() operates on a port of the hub. hub_activate()
operates on the hub itself, or at least I think it does. I don't know
how to convert the calls. Also, there are more calls to hub_power_on()
in the same function.  Can you provide more details on what to do,
or even better a patch for me to test ?

Thanks,
Guenter

> of hub_power_on() is wrong.  It says "Enable power on each port", but
> in fact it only enables power for ports that had been powered-on
> previously (i.e., the port's bit in hub->power_bits was set).  
> Apparently this got messed up in commit ad493e5e5805 ("usb: add usb
> port auto power off mechanism").
> 
> Now, the chipidea driver may still need to be updated, because 
> ehci_turn_off_all_ports() will still be called during shutdown and it 
> will try to power-down all ports, even those which are already powered 
> down (for example, because the port is suspended).
> 
> Alan Stern
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-27 16:55   ` Guenter Roeck
@ 2019-12-28 19:33     ` Alan Stern
  2019-12-29 16:28       ` Guenter Roeck
  0 siblings, 1 reply; 12+ messages in thread
From: Alan Stern @ 2019-12-28 19:33 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Peter Chen, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Michael Grzeschik, stable

On Fri, 27 Dec 2019, Guenter Roeck wrote:

> On Thu, Dec 26, 2019 at 02:46:15PM -0500, Alan Stern wrote:
> > On Thu, 26 Dec 2019, Guenter Roeck wrote:
> > 
> > > On shutdown, ehci_power_off() is called unconditionally to power off
> > > each port, even if it was never called to power on the port.
> > > For chipidea, this results in a call to ehci_ci_portpower() with a request
> > > to power off ports even if the port was never powered on.
> > > This results in the following warning from the regulator code.
> > 
> > That's weird -- we should always power-on every port during hub 
> > initialization.
> > 
> That is what I would have assumed, but test code shows that it doesn't
> happen.
> 
> > It looks like there's a bug in hub.c:hub_activate(): The line under
> > HUB_INIT which calls hub_power_on() should call
> > usb_hub_set_port_power() instead.  In fact, the comment near the start
> 
> usb_hub_set_port_power() operates on a port of the hub. hub_activate()
> operates on the hub itself, or at least I think it does. I don't know
> how to convert the calls. Also, there are more calls to hub_power_on()
> in the same function.  Can you provide more details on what to do,
> or even better a patch for me to test ?

Let's try a slightly different approach.  What happens with this patch?

Alan Stern


Index: usb-devel/drivers/usb/core/hub.c
===================================================================
--- usb-devel.orig/drivers/usb/core/hub.c
+++ usb-devel/drivers/usb/core/hub.c
@@ -1065,6 +1065,7 @@ static void hub_activate(struct usb_hub
 		if (type == HUB_INIT) {
 			delay = hub_power_on_good_delay(hub);
 
+			hub->power_bits[0] = ~0UL;	/* All ports on */
 			hub_power_on(hub, false);
 			INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
 			queue_delayed_work(system_power_efficient_wq,


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-28 19:33     ` Alan Stern
@ 2019-12-29 16:28       ` Guenter Roeck
  2019-12-29 16:40         ` Alan Stern
  0 siblings, 1 reply; 12+ messages in thread
From: Guenter Roeck @ 2019-12-29 16:28 UTC (permalink / raw)
  To: Alan Stern
  Cc: Peter Chen, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Michael Grzeschik, stable

On Sat, Dec 28, 2019 at 02:33:01PM -0500, Alan Stern wrote:
> 
> Let's try a slightly different approach.  What happens with this patch?
> 
> Alan Stern
> 
> 
> Index: usb-devel/drivers/usb/core/hub.c
> ===================================================================
> --- usb-devel.orig/drivers/usb/core/hub.c
> +++ usb-devel/drivers/usb/core/hub.c
> @@ -1065,6 +1065,7 @@ static void hub_activate(struct usb_hub
>  		if (type == HUB_INIT) {
>  			delay = hub_power_on_good_delay(hub);
>  
> +			hub->power_bits[0] = ~0UL;	/* All ports on */
>  			hub_power_on(hub, false);
>  			INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
>  			queue_delayed_work(system_power_efficient_wq,
> 

That doesn't make a difference - the traceback is still seen with this patch
applied.

Guenter

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-29 16:28       ` Guenter Roeck
@ 2019-12-29 16:40         ` Alan Stern
  2019-12-30  0:57           ` Guenter Roeck
  2020-01-01 22:09           ` Guenter Roeck
  0 siblings, 2 replies; 12+ messages in thread
From: Alan Stern @ 2019-12-29 16:40 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Greg Kroah-Hartman, USB list, Kernel development list,
	Michael Grzeschik, stable

On Sun, 29 Dec 2019, Guenter Roeck wrote:

> On Sat, Dec 28, 2019 at 02:33:01PM -0500, Alan Stern wrote:
> > 
> > Let's try a slightly different approach.  What happens with this patch?
> > 
> > Alan Stern
> > 
> > 
> > Index: usb-devel/drivers/usb/core/hub.c
> > ===================================================================
> > --- usb-devel.orig/drivers/usb/core/hub.c
> > +++ usb-devel/drivers/usb/core/hub.c
> > @@ -1065,6 +1065,7 @@ static void hub_activate(struct usb_hub
> >  		if (type == HUB_INIT) {
> >  			delay = hub_power_on_good_delay(hub);
> >  
> > +			hub->power_bits[0] = ~0UL;	/* All ports on */
> >  			hub_power_on(hub, false);
> >  			INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
> >  			queue_delayed_work(system_power_efficient_wq,
> > 
> 
> That doesn't make a difference - the traceback is still seen with this patch
> applied.

Can you trace what's going on?  Does this code pathway now end up
calling ehci_port_power() for each root-hub port, and from there down
into the chipidea driver?  If not, can you find where it gets
sidetracked?

Alan Stern


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-29 16:40         ` Alan Stern
@ 2019-12-30  0:57           ` Guenter Roeck
  2020-01-01 22:09           ` Guenter Roeck
  1 sibling, 0 replies; 12+ messages in thread
From: Guenter Roeck @ 2019-12-30  0:57 UTC (permalink / raw)
  To: Alan Stern
  Cc: Greg Kroah-Hartman, USB list, Kernel development list,
	Michael Grzeschik, stable

On Sun, Dec 29, 2019 at 11:40:52AM -0500, Alan Stern wrote:
> On Sun, 29 Dec 2019, Guenter Roeck wrote:
> 
> > On Sat, Dec 28, 2019 at 02:33:01PM -0500, Alan Stern wrote:
> > > 
> > > Let's try a slightly different approach.  What happens with this patch?
> > > 
> > > Alan Stern
> > > 
> > > 
> > > Index: usb-devel/drivers/usb/core/hub.c
> > > ===================================================================
> > > --- usb-devel.orig/drivers/usb/core/hub.c
> > > +++ usb-devel/drivers/usb/core/hub.c
> > > @@ -1065,6 +1065,7 @@ static void hub_activate(struct usb_hub
> > >  		if (type == HUB_INIT) {
> > >  			delay = hub_power_on_good_delay(hub);
> > >  
> > > +			hub->power_bits[0] = ~0UL;	/* All ports on */
> > >  			hub_power_on(hub, false);
> > >  			INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
> > >  			queue_delayed_work(system_power_efficient_wq,
> > > 
> > 
> > That doesn't make a difference - the traceback is still seen with this patch
> > applied.
> 
> Can you trace what's going on?  Does this code pathway now end up
> calling ehci_port_power() for each root-hub port, and from there down
> into the chipidea driver?  If not, can you find where it gets
> sidetracked?
> 
Sure, I'll do that. It will have to wait for the new year, though -
internet connectivity is terrible where I am right now,

Guenter

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2019-12-29 16:40         ` Alan Stern
  2019-12-30  0:57           ` Guenter Roeck
@ 2020-01-01 22:09           ` Guenter Roeck
  2020-01-02  2:30             ` Alan Stern
  1 sibling, 1 reply; 12+ messages in thread
From: Guenter Roeck @ 2020-01-01 22:09 UTC (permalink / raw)
  To: Alan Stern
  Cc: Greg Kroah-Hartman, USB list, Kernel development list,
	Michael Grzeschik, stable

On 12/29/19 8:40 AM, Alan Stern wrote:
> On Sun, 29 Dec 2019, Guenter Roeck wrote:
> 
>> On Sat, Dec 28, 2019 at 02:33:01PM -0500, Alan Stern wrote:
>>>
>>> Let's try a slightly different approach.  What happens with this patch?
>>>
>>> Alan Stern
>>>
>>>
>>> Index: usb-devel/drivers/usb/core/hub.c
>>> ===================================================================
>>> --- usb-devel.orig/drivers/usb/core/hub.c
>>> +++ usb-devel/drivers/usb/core/hub.c
>>> @@ -1065,6 +1065,7 @@ static void hub_activate(struct usb_hub
>>>   		if (type == HUB_INIT) {
>>>   			delay = hub_power_on_good_delay(hub);
>>>   
>>> +			hub->power_bits[0] = ~0UL;	/* All ports on */
>>>   			hub_power_on(hub, false);
>>>   			INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
>>>   			queue_delayed_work(system_power_efficient_wq,
>>>
>>
>> That doesn't make a difference - the traceback is still seen with this patch
>> applied.
> 
> Can you trace what's going on?  Does this code pathway now end up
> calling ehci_port_power() for each root-hub port, and from there down
> into the chipidea driver?  If not, can you find where it gets
> sidetracked?
> 

A complete traceback is attached below, so, yes, I think it is safe to say that
ehci_port_power() is called unconditionally for each root-hub port on shutdown.

The only mystery to me was why ehci_port_power() isn't called to enable port power
when the port comes up. As it turns out, HCS_PPC(ehci->hcs_params) is false on my
simulated hardware, and thus ehci_port_power(..., true) is not called from
ehci_hub_control().

Given that, it may well be that the problem is not seen on "real" hardware,
at least not with real mcimx7d-sabre hardware, if the hub on that hardware does
support power control. To test this idea, I modified qemu to claim hub power
control support by setting the "power control support" capability bit. With
that, the traceback is gone.

Any suggestion how to proceed ?

Thanks,
Guenter

---
[   31.916567] ------------[ cut here ]------------
[   31.917178] WARNING: CPU: 0 PID: 182 at drivers/regulator/core.c:2598 _regulator_disable+0x1a8/0x210
[   31.917331] unbalanced disables for usb_otg2_vbus
[   31.917468] Modules linked in:
[   31.917877] CPU: 0 PID: 182 Comm: init Not tainted 5.4.8-rc1-00003-gb8e36d27e314 #1
[   31.918032] Hardware name: Freescale i.MX7 Dual (Device Tree)
[   31.918246] [<c0313658>] (unwind_backtrace) from [<c030d698>] (show_stack+0x10/0x14)
[   31.918397] [<c030d698>] (show_stack) from [<c113439c>] (dump_stack+0xe0/0x10c)
[   31.918522] [<c113439c>] (dump_stack) from [<c0349098>] (__warn+0xf4/0x10c)
[   31.918641] [<c0349098>] (__warn) from [<c0349128>] (warn_slowpath_fmt+0x78/0xbc)
[   31.918768] [<c0349128>] (warn_slowpath_fmt) from [<c09f3c3c>] (_regulator_disable+0x1a8/0x210)
[   31.918900] [<c09f3c3c>] (_regulator_disable) from [<c09f3cdc>] (regulator_disable+0x38/0xe8)
[   31.919032] [<c09f3cdc>] (regulator_disable) from [<c0df837c>] (ehci_ci_portpower+0x38/0xdc)
	ehci_ci_portpower() calls regulator_enable() or regulator_disable()
	if priv->reg_vbus is not NULL
[   31.919166] [<c0df837c>] (ehci_ci_portpower) from [<c0db5724>] (ehci_port_power+0x50/0xa4)
	ehci_port_power() calls hcd->driver->port_power(), which is ehci_ci_portpower()
[   31.919296] [<c0db5724>] (ehci_port_power) from [<c0db5ba0>] (ehci_silence_controller+0x5c/0xc4)
	ehci_silence_controller() calls ehci_turn_off_all_ports(), which calls
	ehci_port_power() for each port
[   31.919430] [<c0db5ba0>] (ehci_silence_controller) from [<c0db7dc4>] (ehci_stop+0x3c/0xcc)
	ehci_silence_controller() called unconditionally from ehci_stop()
[   31.919560] [<c0db7dc4>] (ehci_stop) from [<c0d5c504>] (usb_remove_hcd+0xe0/0x19c)	
	ehci_stop() called unconditionally from usb_remove_hcd() with hcd->driver->stop(hcd);
[   31.919685] [<c0d5c504>] (usb_remove_hcd) from [<c0df7e08>] (host_stop+0x38/0xa8)
[   31.919809] [<c0df7e08>] (host_stop) from [<c0df3704>] (ci_hdrc_remove+0x44/0xe4)
[   31.919932] [<c0df3704>] (ci_hdrc_remove) from [<c0b1a5e4>] (platform_drv_remove+0x20/0x40)
[   31.920062] [<c0b1a5e4>] (platform_drv_remove) from [<c0b18a50>] (device_release_driver_internal+0xe8/0x1b8)
[   31.920210] [<c0b18a50>] (device_release_driver_internal) from [<c0b17464>] (bus_remove_device+0xd0/0xfc)
[   31.920351] [<c0b17464>] (bus_remove_device) from [<c0b1401c>] (device_del+0x140/0x374)
[   31.920477] [<c0b1401c>] (device_del) from [<c0b1aaf8>] (platform_device_del.part.3+0x10/0x74)
[   31.920608] [<c0b1aaf8>] (platform_device_del.part.3) from [<c0b1ab8c>] (platform_device_unregister+0x1c/0x28)
[   31.920758] [<c0b1ab8c>] (platform_device_unregister) from [<c0df22f4>] (ci_hdrc_remove_device+0xc/0x20)
[   31.920898] [<c0df22f4>] (ci_hdrc_remove_device) from [<c0df9ea4>] (ci_hdrc_imx_remove+0x28/0x110)
[   31.921033] [<c0df9ea4>] (ci_hdrc_imx_remove) from [<c0b15ac4>] (device_shutdown+0x180/0x224)
[   31.921166] [<c0b15ac4>] (device_shutdown) from [<c037652c>] (kernel_restart+0xc/0x50)
[   31.921292] [<c037652c>] (kernel_restart) from [<c03767d0>] (__do_sys_reboot+0x15c/0x1ec)
[   31.921444] [<c03767d0>] (__do_sys_reboot) from [<c0301000>] (ret_fast_syscall+0x0/0x28)
[   31.921595] Exception stack(0xc93c1fa8 to 0xc93c1ff0)

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] usb: chipidea: host: Disable port power only if previously enabled
  2020-01-01 22:09           ` Guenter Roeck
@ 2020-01-02  2:30             ` Alan Stern
  0 siblings, 0 replies; 12+ messages in thread
From: Alan Stern @ 2020-01-02  2:30 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Greg Kroah-Hartman, USB list, Kernel development list,
	Michael Grzeschik, stable

On Wed, 1 Jan 2020, Guenter Roeck wrote:

> On 12/29/19 8:40 AM, Alan Stern wrote:
> > On Sun, 29 Dec 2019, Guenter Roeck wrote:
> > 
> >> On Sat, Dec 28, 2019 at 02:33:01PM -0500, Alan Stern wrote:
> >>>
> >>> Let's try a slightly different approach.  What happens with this patch?
> >>>
> >>> Alan Stern
> >>>
> >>>
> >>> Index: usb-devel/drivers/usb/core/hub.c
> >>> ===================================================================
> >>> --- usb-devel.orig/drivers/usb/core/hub.c
> >>> +++ usb-devel/drivers/usb/core/hub.c
> >>> @@ -1065,6 +1065,7 @@ static void hub_activate(struct usb_hub
> >>>   		if (type == HUB_INIT) {
> >>>   			delay = hub_power_on_good_delay(hub);
> >>>   
> >>> +			hub->power_bits[0] = ~0UL;	/* All ports on */
> >>>   			hub_power_on(hub, false);
> >>>   			INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
> >>>   			queue_delayed_work(system_power_efficient_wq,
> >>>
> >>
> >> That doesn't make a difference - the traceback is still seen with this patch
> >> applied.
> > 
> > Can you trace what's going on?  Does this code pathway now end up
> > calling ehci_port_power() for each root-hub port, and from there down
> > into the chipidea driver?  If not, can you find where it gets
> > sidetracked?
> > 
> 
> A complete traceback is attached below, so, yes, I think it is safe to say that
> ehci_port_power() is called unconditionally for each root-hub port on shutdown.

I was really asking about hub activation and powering-up, but you found 
the answer to that too, so okay.

> The only mystery to me was why ehci_port_power() isn't called to enable port power
> when the port comes up. As it turns out, HCS_PPC(ehci->hcs_params) is false on my
> simulated hardware, and thus ehci_port_power(..., true) is not called from
> ehci_hub_control().
> 
> Given that, it may well be that the problem is not seen on "real" hardware,
> at least not with real mcimx7d-sabre hardware, if the hub on that hardware does
> support power control. To test this idea, I modified qemu to claim hub power
> control support by setting the "power control support" capability bit. With
> that, the traceback is gone.
> 
> Any suggestion how to proceed ?

Given that HCS_PPC(ehci_hcs_params) is false, I would say that
ehci_turn_off_all_ports() shouldn't call ehci_port_power().  You should
add that test there.  (Although to tell the truth, I'm not really sure 
we need to test HCS_PPC anywhere...)

Did you check what happens without the patch I sent you?  I would like
to know if that patch really does make a difference.  If we don't send
the Set-Port-Feature(power) request during hub activation without the
patch then it does need to be merged.

Alan Stern


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-01-02  2:30 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-26 15:57 [PATCH] usb: chipidea: host: Disable port power only if previously enabled Guenter Roeck
2019-12-26 19:46 ` Alan Stern
2019-12-27  1:45   ` Peter Chen
2019-12-27 14:47     ` Alan Stern
2019-12-27 16:55   ` Guenter Roeck
2019-12-28 19:33     ` Alan Stern
2019-12-29 16:28       ` Guenter Roeck
2019-12-29 16:40         ` Alan Stern
2019-12-30  0:57           ` Guenter Roeck
2020-01-01 22:09           ` Guenter Roeck
2020-01-02  2:30             ` Alan Stern
2019-12-27  1:45 ` Peter Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).