aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-pci.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-05-04 11:52:40 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-12 19:29:47 -0400
commit383975d765523a56dc43a6cd6d52e9b376800cf2 (patch)
treed6ecbfe620d7d5fba372211d7af185e7c44e5097 /drivers/usb/host/ohci-pci.c
parent0458d5b4c9cc4ca0f62625d0144ddc4b4bc97a3c (diff)
USB: EHCI, OHCI: handover changes
This patch (as887) changes the way ehci-hcd and ohci-hcd handle a loss of VBUS power during suspend. In order for the USB-persist facility to work correctly, it is necessary for low- and full-speed devices attached to a high-speed port to be handed back to the companion controller during resume processing. This entails three changes: adding code to ehci-hcd to perform the handover, removing code from ohci-hcd to turn off ports during root-hub reinit, and adding code to ohci-hcd to turn on ports during PCI controller resume. (Other bus glue resume methods for platforms supporting high-speed controllers would need a similar change, if any existed.) Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ohci-pci.c')
-rw-r--r--drivers/usb/host/ohci-pci.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index ca62cb583221..15013f4519ad 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -202,6 +202,42 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
202 return ret; 202 return ret;
203} 203}
204 204
205#if defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \
206 defined(CONFIG_USB_EHCI_HCD_MODULE))
207
208/* Following a power loss, we must prepare to regain control of the ports
209 * we used to own. This means turning on the port power before ehci-hcd
210 * tries to switch ownership.
211 *
212 * This isn't a 100% perfect solution. On most systems the OHCI controllers
213 * lie at lower PCI addresses than the EHCI controller, so they will be
214 * discovered (and hence resumed) first. But there is no guarantee things
215 * will always work this way. If the EHCI controller is resumed first and
216 * the OHCI ports are unpowered, then the handover will fail.
217 */
218static void prepare_for_handover(struct usb_hcd *hcd)
219{
220 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
221 int port;
222
223 /* Here we "know" root ports should always stay powered */
224 ohci_dbg(ohci, "powerup ports\n");
225 for (port = 0; port < ohci->num_ports; port++)
226 ohci_writel(ohci, RH_PS_PPS,
227 &ohci->regs->roothub.portstatus[port]);
228
229 /* Flush those writes */
230 ohci_readl(ohci, &ohci->regs->control);
231 msleep(20);
232}
233
234#else
235
236static inline void prepare_for_handover(struct usb_hcd *hcd)
237{ }
238
239#endif /* CONFIG_USB_PERSIST etc. */
240
205#ifdef CONFIG_PM 241#ifdef CONFIG_PM
206 242
207static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) 243static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
@@ -241,7 +277,10 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
241static int ohci_pci_resume (struct usb_hcd *hcd) 277static int ohci_pci_resume (struct usb_hcd *hcd)
242{ 278{
243 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 279 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
244 usb_hcd_resume_root_hub(hcd); 280
281 /* FIXME: we should try to detect loss of VBUS power here */
282 prepare_for_handover(hcd);
283
245 return 0; 284 return 0;
246} 285}
247 286