2017-07-24 23:12:07

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH] PM / USB: hcd_pci: Skip secondary root hub check for HCD_DEAD()

From: Rafael J. Wysocki <[email protected]>

If HCD_DEAD(hcd) is "true" in check_root_hub_suspended(), it is
rather pointless to check the secondary root hub, so return early
then.

This actually fixes occasional suspend failures on one of my test
machines.

Signed-off-by: Rafael J. Wysocki <[email protected]>
---
drivers/usb/core/hcd-pci.c | 3 +++
1 file changed, 3 insertions(+)

Index: linux-pm/drivers/usb/core/hcd-pci.c
===================================================================
--- linux-pm.orig/drivers/usb/core/hcd-pci.c
+++ linux-pm/drivers/usb/core/hcd-pci.c
@@ -427,6 +427,9 @@ static int check_root_hub_suspended(stru
dev_warn(dev, "Root hub is not suspended\n");
return -EBUSY;
}
+ if (HCD_DEAD(hcd))
+ return 0;
+
if (hcd->shared_hcd) {
hcd = hcd->shared_hcd;
if (HCD_RH_RUNNING(hcd)) {


2017-07-25 14:05:05

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH] PM / USB: hcd_pci: Skip secondary root hub check for HCD_DEAD()

On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:

> From: Rafael J. Wysocki <[email protected]>
>
> If HCD_DEAD(hcd) is "true" in check_root_hub_suspended(), it is
> rather pointless to check the secondary root hub, so return early
> then.
>
> This actually fixes occasional suspend failures on one of my test
> machines.
>
> Signed-off-by: Rafael J. Wysocki <[email protected]>
> ---
> drivers/usb/core/hcd-pci.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> Index: linux-pm/drivers/usb/core/hcd-pci.c
> ===================================================================
> --- linux-pm.orig/drivers/usb/core/hcd-pci.c
> +++ linux-pm/drivers/usb/core/hcd-pci.c
> @@ -427,6 +427,9 @@ static int check_root_hub_suspended(stru
> dev_warn(dev, "Root hub is not suspended\n");
> return -EBUSY;
> }
> + if (HCD_DEAD(hcd))
> + return 0;
> +
> if (hcd->shared_hcd) {
> hcd = hcd->shared_hcd;
> if (HCD_RH_RUNNING(hcd)) {

While this is an okay solution, IMO it would be more reliable and more
general to have usb_hc_died() clear the HCD_FLAG_RH_RUNNING bit and set
the HCD_FLAG_DEAD bit in the shared hcd. Right now it only does these
things for the primary.

Would you like to write and test a patch to do that?

Incidentally, if this fixes occasional suspend failures on your test
machine, does that mean the test machine's host controller occasionally
dies? Maybe that should be fixed too...

Alan Stern

2017-07-25 16:07:05

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [PATCH] PM / USB: hcd_pci: Skip secondary root hub check for HCD_DEAD()

On Tuesday, July 25, 2017 10:05:03 AM Alan Stern wrote:
> On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:
>
> > From: Rafael J. Wysocki <[email protected]>
> >
> > If HCD_DEAD(hcd) is "true" in check_root_hub_suspended(), it is
> > rather pointless to check the secondary root hub, so return early
> > then.
> >
> > This actually fixes occasional suspend failures on one of my test
> > machines.
> >
> > Signed-off-by: Rafael J. Wysocki <[email protected]>
> > ---
> > drivers/usb/core/hcd-pci.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > Index: linux-pm/drivers/usb/core/hcd-pci.c
> > ===================================================================
> > --- linux-pm.orig/drivers/usb/core/hcd-pci.c
> > +++ linux-pm/drivers/usb/core/hcd-pci.c
> > @@ -427,6 +427,9 @@ static int check_root_hub_suspended(stru
> > dev_warn(dev, "Root hub is not suspended\n");
> > return -EBUSY;
> > }
> > + if (HCD_DEAD(hcd))
> > + return 0;
> > +
> > if (hcd->shared_hcd) {
> > hcd = hcd->shared_hcd;
> > if (HCD_RH_RUNNING(hcd)) {
>
> While this is an okay solution, IMO it would be more reliable and more
> general to have usb_hc_died() clear the HCD_FLAG_RH_RUNNING bit and set
> the HCD_FLAG_DEAD bit in the shared hcd. Right now it only does these
> things for the primary.
>
> Would you like to write and test a patch to do that?

I can do that.

> Incidentally, if this fixes occasional suspend failures on your test
> machine, does that mean the test machine's host controller occasionally
> dies? Maybe that should be fixed too...

Yes, it does sometimes.

What appears to happen is that the platform does not initialize properly
sometimes after a reset and then the HCD dies during suspend.

So reproduction may be somewhat tricky, but oh well.

Thanks,
Rafael

2017-07-25 20:43:40

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [PATCH] PM / USB: hcd_pci: Skip secondary root hub check for HCD_DEAD()

On Tuesday, July 25, 2017 05:59:04 PM Rafael J. Wysocki wrote:
> On Tuesday, July 25, 2017 10:05:03 AM Alan Stern wrote:
> > On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:
> >
> > > From: Rafael J. Wysocki <[email protected]>
> > >
> > > If HCD_DEAD(hcd) is "true" in check_root_hub_suspended(), it is
> > > rather pointless to check the secondary root hub, so return early
> > > then.
> > >
> > > This actually fixes occasional suspend failures on one of my test
> > > machines.
> > >
> > > Signed-off-by: Rafael J. Wysocki <[email protected]>
> > > ---
> > > drivers/usb/core/hcd-pci.c | 3 +++
> > > 1 file changed, 3 insertions(+)
> > >
> > > Index: linux-pm/drivers/usb/core/hcd-pci.c
> > > ===================================================================
> > > --- linux-pm.orig/drivers/usb/core/hcd-pci.c
> > > +++ linux-pm/drivers/usb/core/hcd-pci.c
> > > @@ -427,6 +427,9 @@ static int check_root_hub_suspended(stru
> > > dev_warn(dev, "Root hub is not suspended\n");
> > > return -EBUSY;
> > > }
> > > + if (HCD_DEAD(hcd))
> > > + return 0;
> > > +
> > > if (hcd->shared_hcd) {
> > > hcd = hcd->shared_hcd;
> > > if (HCD_RH_RUNNING(hcd)) {
> >
> > While this is an okay solution, IMO it would be more reliable and more
> > general to have usb_hc_died() clear the HCD_FLAG_RH_RUNNING bit and set
> > the HCD_FLAG_DEAD bit in the shared hcd. Right now it only does these
> > things for the primary.
> >
> > Would you like to write and test a patch to do that?
>
> I can do that.

Just to make sure that we are on the same page, is the below what you mean?

---
drivers/usb/core/hcd.c | 2 ++
1 file changed, 2 insertions(+)

Index: linux-pm/drivers/usb/core/hcd.c
===================================================================
--- linux-pm.orig/drivers/usb/core/hcd.c
+++ linux-pm/drivers/usb/core/hcd.c
@@ -2485,6 +2485,8 @@ void usb_hc_died (struct usb_hcd *hcd)
}
if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
hcd = hcd->shared_hcd;
+ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+ set_bit(HCD_FLAG_DEAD, &hcd->flags);
if (hcd->rh_registered) {
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);


2017-07-25 21:06:45

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH] PM / USB: hcd_pci: Skip secondary root hub check for HCD_DEAD()

On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:

> On Tuesday, July 25, 2017 05:59:04 PM Rafael J. Wysocki wrote:
> > On Tuesday, July 25, 2017 10:05:03 AM Alan Stern wrote:
> > > On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:
> > >
> > > > From: Rafael J. Wysocki <[email protected]>
> > > >
> > > > If HCD_DEAD(hcd) is "true" in check_root_hub_suspended(), it is
> > > > rather pointless to check the secondary root hub, so return early
> > > > then.
> > > >
> > > > This actually fixes occasional suspend failures on one of my test
> > > > machines.
> > > >
> > > > Signed-off-by: Rafael J. Wysocki <[email protected]>
> > > > ---
> > > > drivers/usb/core/hcd-pci.c | 3 +++
> > > > 1 file changed, 3 insertions(+)
> > > >
> > > > Index: linux-pm/drivers/usb/core/hcd-pci.c
> > > > ===================================================================
> > > > --- linux-pm.orig/drivers/usb/core/hcd-pci.c
> > > > +++ linux-pm/drivers/usb/core/hcd-pci.c
> > > > @@ -427,6 +427,9 @@ static int check_root_hub_suspended(stru
> > > > dev_warn(dev, "Root hub is not suspended\n");
> > > > return -EBUSY;
> > > > }
> > > > + if (HCD_DEAD(hcd))
> > > > + return 0;
> > > > +
> > > > if (hcd->shared_hcd) {
> > > > hcd = hcd->shared_hcd;
> > > > if (HCD_RH_RUNNING(hcd)) {
> > >
> > > While this is an okay solution, IMO it would be more reliable and more
> > > general to have usb_hc_died() clear the HCD_FLAG_RH_RUNNING bit and set
> > > the HCD_FLAG_DEAD bit in the shared hcd. Right now it only does these
> > > things for the primary.
> > >
> > > Would you like to write and test a patch to do that?
> >
> > I can do that.
>
> Just to make sure that we are on the same page, is the below what you mean?
>
> ---
> drivers/usb/core/hcd.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> Index: linux-pm/drivers/usb/core/hcd.c
> ===================================================================
> --- linux-pm.orig/drivers/usb/core/hcd.c
> +++ linux-pm/drivers/usb/core/hcd.c
> @@ -2485,6 +2485,8 @@ void usb_hc_died (struct usb_hcd *hcd)
> }
> if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
> hcd = hcd->shared_hcd;
> + clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
> + set_bit(HCD_FLAG_DEAD, &hcd->flags);
> if (hcd->rh_registered) {
> clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);

Yes, exactly. Does it fix your suspend problem?

Alan Stern

2017-07-25 21:44:45

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [PATCH] PM / USB: hcd_pci: Skip secondary root hub check for HCD_DEAD()

On Tuesday, July 25, 2017 05:06:40 PM Alan Stern wrote:
> On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:
>
> > On Tuesday, July 25, 2017 05:59:04 PM Rafael J. Wysocki wrote:
> > > On Tuesday, July 25, 2017 10:05:03 AM Alan Stern wrote:
> > > > On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:
> > > >
> > > > > From: Rafael J. Wysocki <[email protected]>
> > > > >
> > > > > If HCD_DEAD(hcd) is "true" in check_root_hub_suspended(), it is
> > > > > rather pointless to check the secondary root hub, so return early
> > > > > then.
> > > > >
> > > > > This actually fixes occasional suspend failures on one of my test
> > > > > machines.
> > > > >
> > > > > Signed-off-by: Rafael J. Wysocki <[email protected]>
> > > > > ---
> > > > > drivers/usb/core/hcd-pci.c | 3 +++
> > > > > 1 file changed, 3 insertions(+)
> > > > >
> > > > > Index: linux-pm/drivers/usb/core/hcd-pci.c
> > > > > ===================================================================
> > > > > --- linux-pm.orig/drivers/usb/core/hcd-pci.c
> > > > > +++ linux-pm/drivers/usb/core/hcd-pci.c
> > > > > @@ -427,6 +427,9 @@ static int check_root_hub_suspended(stru
> > > > > dev_warn(dev, "Root hub is not suspended\n");
> > > > > return -EBUSY;
> > > > > }
> > > > > + if (HCD_DEAD(hcd))
> > > > > + return 0;
> > > > > +
> > > > > if (hcd->shared_hcd) {
> > > > > hcd = hcd->shared_hcd;
> > > > > if (HCD_RH_RUNNING(hcd)) {
> > > >
> > > > While this is an okay solution, IMO it would be more reliable and more
> > > > general to have usb_hc_died() clear the HCD_FLAG_RH_RUNNING bit and set
> > > > the HCD_FLAG_DEAD bit in the shared hcd. Right now it only does these
> > > > things for the primary.
> > > >
> > > > Would you like to write and test a patch to do that?
> > >
> > > I can do that.
> >
> > Just to make sure that we are on the same page, is the below what you mean?
> >
> > ---
> > drivers/usb/core/hcd.c | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > Index: linux-pm/drivers/usb/core/hcd.c
> > ===================================================================
> > --- linux-pm.orig/drivers/usb/core/hcd.c
> > +++ linux-pm/drivers/usb/core/hcd.c
> > @@ -2485,6 +2485,8 @@ void usb_hc_died (struct usb_hcd *hcd)
> > }
> > if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
> > hcd = hcd->shared_hcd;
> > + clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
> > + set_bit(HCD_FLAG_DEAD, &hcd->flags);
> > if (hcd->rh_registered) {
> > clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
>
> Yes, exactly. Does it fix your suspend problem?

Yes, it does.

I guess I should resend it with a changelog and tags, then.

Thanks,
Rafael

2017-07-25 22:06:52

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH] USB: hcd: Mark secondary HCD as dead if the primary one died

From: Rafael J. Wysocki <[email protected]>

Make usb_hc_died() clear the HCD_FLAG_RH_RUNNING flag for the shared
HCD and set HCD_FLAG_DEAD for it, in analogy with what is done for
the primary one.

Among other thigs, this prevents check_root_hub_suspended() from
returning -EBUSY for dead HCDs which helps to work around system
suspend issues in some situations.

This actually fixes occasional suspend failures on one of my test
machines.

Suggested-by: Alan Stern <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
---
drivers/usb/core/hcd.c | 2 ++
1 file changed, 2 insertions(+)

Index: linux-pm/drivers/usb/core/hcd.c
===================================================================
--- linux-pm.orig/drivers/usb/core/hcd.c
+++ linux-pm/drivers/usb/core/hcd.c
@@ -2485,6 +2485,8 @@ void usb_hc_died (struct usb_hcd *hcd)
}
if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
hcd = hcd->shared_hcd;
+ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+ set_bit(HCD_FLAG_DEAD, &hcd->flags);
if (hcd->rh_registered) {
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);


2017-07-26 14:21:57

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH] USB: hcd: Mark secondary HCD as dead if the primary one died

On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:

> From: Rafael J. Wysocki <[email protected]>
>
> Make usb_hc_died() clear the HCD_FLAG_RH_RUNNING flag for the shared
> HCD and set HCD_FLAG_DEAD for it, in analogy with what is done for
> the primary one.
>
> Among other thigs, this prevents check_root_hub_suspended() from
> returning -EBUSY for dead HCDs which helps to work around system
> suspend issues in some situations.
>
> This actually fixes occasional suspend failures on one of my test
> machines.
>
> Suggested-by: Alan Stern <[email protected]>
> Signed-off-by: Rafael J. Wysocki <[email protected]>
> ---
> drivers/usb/core/hcd.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> Index: linux-pm/drivers/usb/core/hcd.c
> ===================================================================
> --- linux-pm.orig/drivers/usb/core/hcd.c
> +++ linux-pm/drivers/usb/core/hcd.c
> @@ -2485,6 +2485,8 @@ void usb_hc_died (struct usb_hcd *hcd)
> }
> if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
> hcd = hcd->shared_hcd;
> + clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
> + set_bit(HCD_FLAG_DEAD, &hcd->flags);
> if (hcd->rh_registered) {
> clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);

Acked-by: Alan Stern <[email protected]>

2017-07-26 17:15:54

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [PATCH] USB: hcd: Mark secondary HCD as dead if the primary one died

On Wednesday, July 26, 2017 10:21:54 AM Alan Stern wrote:
> On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:
>
> > From: Rafael J. Wysocki <[email protected]>
> >
> > Make usb_hc_died() clear the HCD_FLAG_RH_RUNNING flag for the shared
> > HCD and set HCD_FLAG_DEAD for it, in analogy with what is done for
> > the primary one.
> >
> > Among other thigs, this prevents check_root_hub_suspended() from
> > returning -EBUSY for dead HCDs which helps to work around system
> > suspend issues in some situations.
> >
> > This actually fixes occasional suspend failures on one of my test
> > machines.
> >
> > Suggested-by: Alan Stern <[email protected]>
> > Signed-off-by: Rafael J. Wysocki <[email protected]>
> > ---
> > drivers/usb/core/hcd.c | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > Index: linux-pm/drivers/usb/core/hcd.c
> > ===================================================================
> > --- linux-pm.orig/drivers/usb/core/hcd.c
> > +++ linux-pm/drivers/usb/core/hcd.c
> > @@ -2485,6 +2485,8 @@ void usb_hc_died (struct usb_hcd *hcd)
> > }
> > if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
> > hcd = hcd->shared_hcd;
> > + clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
> > + set_bit(HCD_FLAG_DEAD, &hcd->flags);
> > if (hcd->rh_registered) {
> > clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
>
> Acked-by: Alan Stern <[email protected]>
>

Thanks!

I guess this should go in via USB, so Felipe & Greg, please apply or let me
know if you prefer me to handle it.

Thanks,
Rafael

2017-07-30 17:05:27

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH] USB: hcd: Mark secondary HCD as dead if the primary one died

On Wed, Jul 26, 2017 at 07:07:51PM +0200, Rafael J. Wysocki wrote:
> On Wednesday, July 26, 2017 10:21:54 AM Alan Stern wrote:
> > On Tue, 25 Jul 2017, Rafael J. Wysocki wrote:
> >
> > > From: Rafael J. Wysocki <[email protected]>
> > >
> > > Make usb_hc_died() clear the HCD_FLAG_RH_RUNNING flag for the shared
> > > HCD and set HCD_FLAG_DEAD for it, in analogy with what is done for
> > > the primary one.
> > >
> > > Among other thigs, this prevents check_root_hub_suspended() from
> > > returning -EBUSY for dead HCDs which helps to work around system
> > > suspend issues in some situations.
> > >
> > > This actually fixes occasional suspend failures on one of my test
> > > machines.
> > >
> > > Suggested-by: Alan Stern <[email protected]>
> > > Signed-off-by: Rafael J. Wysocki <[email protected]>
> > > ---
> > > drivers/usb/core/hcd.c | 2 ++
> > > 1 file changed, 2 insertions(+)
> > >
> > > Index: linux-pm/drivers/usb/core/hcd.c
> > > ===================================================================
> > > --- linux-pm.orig/drivers/usb/core/hcd.c
> > > +++ linux-pm/drivers/usb/core/hcd.c
> > > @@ -2485,6 +2485,8 @@ void usb_hc_died (struct usb_hcd *hcd)
> > > }
> > > if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
> > > hcd = hcd->shared_hcd;
> > > + clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
> > > + set_bit(HCD_FLAG_DEAD, &hcd->flags);
> > > if (hcd->rh_registered) {
> > > clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
> >
> > Acked-by: Alan Stern <[email protected]>
> >
>
> Thanks!
>
> I guess this should go in via USB, so Felipe & Greg, please apply or let me
> know if you prefer me to handle it.

I'll take it, thanks.

greg k-h