[Cbe-oss-dev] [PATCH 1/5 v2] usb: Fix PS3 EHCI suspend

Geoff Levand geoff at infradead.org
Fri Dec 2 11:19:18 EST 2011


The EHCI USB 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 the ehci-hcd handshake routine will return
-ETIMEDOUT and the USB runtime suspend sequence will fail.

The fix implemented here is to check the result of the handshake
call done in handshake_on_error_set_halt() and if the condition
is found return success to allow the USB suspend to complete.
The STS_HLT bit will not be set, so inspection of the frame index
is used to test for the condition.

Signed-off-by: Geoff Levand <geoff at infradead.org>
---
Alan,

I did the logic so that there would be a minimal overhead
when running on PS3, and should be optimized out when
CONFIG_PPC_PS3=n.

-Geoff

v2: - Put work-around in handshake_on_error_set_halt();

 drivers/usb/host/ehci-hcd.c |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 46dccbf..4a8391c 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -48,6 +48,10 @@
 #include <asm/system.h>
 #include <asm/unaligned.h>
 
+#if defined(CONFIG_PPC_PS3)
+#include <asm/firmware.h>
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -236,6 +240,30 @@ static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
 	int error;
 
 	error = handshake(ehci, ptr, mask, done, usec);
+
+	/*
+	 * 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.
+	 */
+
+#if defined(CONFIG_USB_SUSPEND) && defined(CONFIG_PPC_PS3)
+	if (firmware_has_feature(FW_FEATURE_PS3_LV1) && error == -ETIMEDOUT) {
+#else
+	if (0) {
+#endif
+		unsigned int 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;
+	}
+
 	if (error) {
 		ehci_halt(ehci);
 		ehci->rh_state = EHCI_RH_HALTED;
-- 
1.7.0.4






More information about the cbe-oss-dev mailing list