From db85beb00c9de8555415a1c5d99623d35eb6b59a Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Wed, 30 Nov 2011 16:40:57 -0800 Subject: [PATCH] --- yaml --- r: 280791 b: refs/heads/master c: df7c1ca229ebffe14a6fb3f13d16b1dd2a1731cb h: refs/heads/master i: 280789: a5213381f136dee366ceee53f72fe0a657d3ee9e 280787: aad70ac37121747185f33207878eb12c7854b0cb 280783: ac02f1b7c9f102499e9a6ac577d8250acc3c72ef v: v3 --- [refs] | 2 +- trunk/drivers/usb/host/ehci-hcd.c | 50 +++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index b7e5b24845c8..5e2208d8062e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9187bef2fa395e85d5e22c4792b553d98410ccd6 +refs/heads/master: df7c1ca229ebffe14a6fb3f13d16b1dd2a1731cb diff --git a/trunk/drivers/usb/host/ehci-hcd.c b/trunk/drivers/usb/host/ehci-hcd.c index 46dccbf85c1a..e0ca9955880b 100644 --- a/trunk/drivers/usb/host/ehci-hcd.c +++ b/trunk/drivers/usb/host/ehci-hcd.c @@ -48,6 +48,10 @@ #include #include +#if defined(CONFIG_PPC_PS3) +#include +#endif + /*-------------------------------------------------------------------------*/ /* @@ -230,12 +234,58 @@ static int ehci_halt (struct ehci_hcd *ehci) STS_HALT, STS_HALT, 16 * 125); } +#if defined(CONFIG_USB_SUSPEND) && defined(CONFIG_PPC_PS3) + +/* + * The EHCI controller of the Cell Super Companion Chip used in the + * PS3 will stop the root hub after all root hub ports are suspended. + * When in this condition handshake will return -ETIMEDOUT. The + * STS_HLT bit will not be set, so inspection of the frame index is + * used here to test for the condition. If the condition is found + * return success to allow the USB suspend to complete. + */ + +static int handshake_for_broken_root_hub(struct ehci_hcd *ehci, + void __iomem *ptr, u32 mask, u32 done, + int usec) +{ + unsigned int old_index; + int error; + + if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) + return -ETIMEDOUT; + + old_index = ehci_read_frame_index(ehci); + + error = handshake(ehci, ptr, mask, done, usec); + + if (error == -ETIMEDOUT && ehci_read_frame_index(ehci) == old_index) + return 0; + + return error; +} + +#else + +static int handshake_for_broken_root_hub(struct ehci_hcd *ehci, + void __iomem *ptr, u32 mask, u32 done, + int usec) +{ + return -ETIMEDOUT; +} + +#endif + static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr, u32 mask, u32 done, int usec) { int error; error = handshake(ehci, ptr, mask, done, usec); + if (error == -ETIMEDOUT) + error = handshake_for_broken_root_hub(ehci, ptr, mask, done, + usec); + if (error) { ehci_halt(ehci); ehci->rh_state = EHCI_RH_HALTED;