Re: USB hot-plug not working (ASUS TP301UA-C4028T)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[+cc Rafael, Lukas]

On Wed, Oct 05, 2016 at 10:45:22AM -0400, Alan Stern wrote:
> [Adding Bjorn and linux-pci to the CC: list]
> 
> In short, Pierre's USB host controller doesn't send wakeup signals from
> runtime suspend, because the firmware limits the runtime-suspend state
> to D0 and the controller can't issue PME# from the D0 state.  In this
> situation we would prefer to avoid suspending the controller at all,
> rather than have it go into runtime suspend and then stop working.
> 
> On Wed, 5 Oct 2016, Mathias Nyman wrote:
> 
> > On 04.10.2016 17:11, Alan Stern wrote:
> > > On Tue, 4 Oct 2016, Mathias Nyman wrote:
> > >
> > >> On 03.10.2016 23:54, Pierre de Villemereuil wrote:
> > >>> Hi Mathias,
> > >>>
> > >>> Just to know: does that mean the firmware from Asus is faulty in here? Do you
> > >>> think I should contact Asus about this?
> > >>>
> > >>
> > >> Probably, _S0W, _DSM  and XFLT code for xHCI are useless in that ACPI DSDT firmware version.
> > >>
> > >> But we still want the driver to handle cases like this.
> > >> Just wrote the patch.
> > >> Adding Alan Stern to CC for PM sanity feedback on it:
> > >>
> > >> ---
> > >>
> > >> Author: Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx>
> > >> Date:   Tue Oct 4 13:07:59 2016 +0300
> > >>
> > >>       xhci: Prevent a non-responsive xhci suspend state.
> > >>
> > >>       ACPI may limit the lowest possible runtime suspend PCI D-state to D0.
> > >>       If xHC is not capable of generating PME# events in D0 we end
> > >>       up with a non-responsive runtime suspended host without PME# capability
> > >>       and with interrupts disabled, unable to detect or wake up when a
> > >>       new usb device is connected.
> > >>
> > >>       This was triggered on a ASUS TP301UA machine.
> > >>
> > >>       Reported-by: Pierre de Villemereuil <flyos@xxxxxxxxxx>
> > >>       Signed-off-by: Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx>
> > >>
> > >> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> > >> index d7b0f97..08b021c 100644
> > >> --- a/drivers/usb/host/xhci-pci.c
> > >> +++ b/drivers/usb/host/xhci-pci.c
> > >> @@ -396,6 +396,11 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
> > >>           if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
> > >>                   xhci_ssic_port_unused_quirk(hcd, true);
> > >>
> > >> +       /* Prevent a non-responsive PCI D0 state without PME# wake capability */
> > >> +       if (pci_choose_state(pdev, PMSG_AUTO_SUSPEND) == PCI_D0)
> > >> +               if (!pci_pme_capable(pdev, PCI_D0))
> > >> +                       return -EBUSY;
> > >> +
> > >>           ret = xhci_suspend(xhci, do_wakeup);
> > >>           if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED))
> > >>                   xhci_ssic_port_unused_quirk(hcd, false);
> > >
> > > I've got three comments about this proposal.
> > >
> > > First, this logic should not apply during system suspend, only during
> > > runtime suspend.  You don't want to abort putting a laptop to sleep
> > > just because the xHCI controller can't generate wakeup signals.
> > 
> > Yes, I assume it would be ok change usb core to pass down something like
> > pm_message_t to suspend_common() so that we could do this.
> > hcd_pci_runetime_suspend()  -> suspend_common()  -> hcd->driver->pci_suspend()
> > 
> > Assuming this workaround should stay in xhci-pci.c
> 
> If necessary, it could be moved into hcd_pci_runtime_suspend().  But I 
> would prefer to put it in the PCI core.
> 
> > > Second, this really has nothing to do with the D0 state.  The same
> > > logic should apply to whatever state is chosen for runtime suspend: If
> > > the controller can't generate PME# wakeup signals in that state then
> > > the suspend should be aborted.
> > 
> > PCI code actually does this for us, it will walk down the D-states until
> > it finds one that support PME#, but stop at D0 end return D0 even if D0
> > does not support PME#.
> 
> That sounds like a bug.  Or rather, accepting D0 as the target state
> when it doesn't support PME# is the bug.
> 
> > Unfortunately that is done in a static function in pci/pci.c.
> > 
> > static pci_power_t pci_target_state(struct pci_dev *dev)
> > {
> >          pci_power_t target_state = PCI_D3hot;
> > 
> > 	if (platform_pci_power_manageable(dev)) {
> >                  /*
> >                   * Call the platform to choose the target state of the device
> >                   * and enable wake-up from this state if supported.
> >                   */
> >                  pci_power_t state = platform_pci_choose_state(dev);
> > 
> > 	        switch (state) {
> > 	        case PCI_POWER_ERROR:
> >                  case PCI_UNKNOWN:
> >                          break;
> >                  case PCI_D1:
> >                  case PCI_D2:
> >                          if (pci_no_d1d2(dev))
> > 	                        break;
> >                  default:
> > 	                target_state = state;
> >                  }
> >          } else if (!dev->pm_cap) {
> >                  target_state = PCI_D0;
> >          } else if (device_may_wakeup(&dev->dev)) {
> >                  /*
> >                   * Find the deepest state from which the device can generate
> >                   * wake-up events, make it the target state and enable device
> >                   * to generate PME#.
> >                   */
> >                  if (dev->pme_support) {
> >                          while (target_state
> >                                && !(dev->pme_support & (1 << target_state)))
> >                                  target_state--;
> >                  }
> >          }
> > 
> >          return target_state;
> > }
> > 
> > The best I can do from xhci is call pci_choose_state() which will call
> > platform_pci_choose_state(), but won't do the PME# checking and
> > D-state decrement to D0 .
> > 
> > If pci_choose_state() returns D0 from a runtime suspend callback
> > (and yes, should make sure its runtime suspend, not system suspend)
> > I can pretty much assume pci_target_state will do the same.
> > 
> > >
> > > Third, the same reasoning applies to every PCI device that relies on
> > > PME#, not just to xHCI controllers.  Therefore the new code should be
> > > added to drivers/pci/pci-driver.c:pci_pm_runtime_suspend(), not to
> > > xhci-pci.c.
> > 
> > Yes, that would be the preferred solution.
> > I was not sure we can do that. pci-driver.c pci_pm_runtime_suspend() will call
> > pci_finish_runtime_suspend()
> >    pci_target_state()        // returns D0,
> >    pci_set_power_state()    // to D0, which is the state we probably are already in.
> > 
> > So it won't really do much. The device PCI device is disabled in usb hcd suspend
> > hcd-pci.c:
> > suspend_common()
> >    ...
> >    pci_disable_device(pci_dev)
> > 
> > Should we anyway disable runtime PM in PCI if the PCI device has wakeup enabled
> > and the target state is D0 without PME# support?
> 
> First, the device_may_wakeup() test applies only to suspend suspend, 
> not to runtime suspend.  The current PM design assumes that wakeup will 
> always be enabled during runtime suspend (if the device supports it).
> 
> Second, there is a potential problem because some PCI devices have
> other platform-based mechanisms for sending wakeup signals, instead of
> using PME#.  Such devices probably don't support standard PCI wakeup at
> all.  (A good example is the UHCI controllers on Intel's old chipsets.)
> We don't want to prevent them from going into runtime suspend.
> 
> Now, maybe this isn't an issue -- I don't know enough about the details
> of how the PCI core handles runtime suspend and how it coordinates with
> the platform code.
> 
> Hopefully Bjorn can fill in the missing details.
> 
> Alan Stern
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux