On Thu, 5 May 2011, Jan Andersson wrote: > > Then you will need to duplicate somehow the fancy logic in hcd-pci.c > > for associating companion controllers. It is necessary for insuring > > that the controllers, root hubs, and the devices under them are resumed > > in the proper order so that handoffs from EHCI to UHCI can occur > > correctly following hibernation. > > > > Thanks for the heads up. I know very little about PM on Linux so I will > need to read up on the topic. AFAIK it is not common to (attempt to) use > PM with LEON. Anyway, I will look into this but, unless you object, I > will not add that logic to this patchset. It's okay to leave it out for now. The issue is somewhat complicated. It has to do with port handovers from the EHCI controller to the UHCI companions in the case where power was lost during a system sleep. The basic idea is simple: A device attached to a UHCI controller can't be resumed properly unless the corresponding EHCI port OWNER bit is set. That seems obvious. There are two considerations that make this problematic: First, during resume the EHCI OWNER bits get set in only one spot, as part of the EHCI root-hub resume procedure (ehci_handover_companion_ports(), called at the end of ehci_bus_resume()). Second, resetting a UHCI controller clears the corresponding port OWNER bits. This was a surprise to me, but it's not unreasonable. (And it's not documented anywhere, AFAIK.) Back before we had asynchronous suspend/resume, things were simpler. Devices would always be resumed in the order they were originally registered. UHCI-attached devices couldn't be registered before the EHCI root hub, because until the EHCI root hub is registered, the OWNER bits can't get set. Therefore the UHCI-attached devices would always be resumed after the EHCI root hub, so the OWNER bits would already be set correctly, which takes care of the first consideration. The second consideration leads to difficulties if a UHCI controller is reset (because power was lost during suspend) as part of its resume procedure. If this happens after the EHCI root hub is resumed, the OWNER bits will be messed up. This used to be handled by the fact that PCI functions are registered in order by function number, and the EHCI spec says that the EHCI controller in a PCI slot must always have a higher function number than its companion controllers. Therefore the UHCI controllers would be registered first and hence resumed first, so there was no possibility that a UHCI controller would be reset following the EHCI root-hub resume. It's important for the non-async case that this order of controller resgistration be maintained on non-PCI systems. In particular, your platform code must insure that the companion UHCI controllers are registered before their EHCI controller. With async suspend/resume, things get more complicated. We can't rely on devices being resumed in order of registration; instead restrictions on resume order must be enforced explicitly in the code. The considerations above lead us to two restrictions: A device attached to a UHCI companion controller must not be resumed until the EHCI root hub has been resumed. An EHCI root hub must not be resumed until all its companion UHCI controllers have been resumed. (In practice it's easier to make the EHCI controller resume do the waiting, rather than the EHCI root-hub resume.) These restrictions are enforced by calls to device_pm_wait_for_dev(): The first by the call in drivers/usb/core/driver.c:usb_resume_device() and the second by the call in drivers/usb/core/hcd-pci.c:companion_common(), invoked by wait_for_companions() from resume_common(). To make the first work on your systems, you will need to fill in the hcd->self.hs_companion field for the UHCI companion controllers -- although unfortunately this can't be done until the EHCI controller is registered. To make the second work, you will need to make sure that the resume routine in your EHCI platform driver calls device_pm_wait_for_dev() for each of the companion UHCI controllers. Alan Stern -- 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