Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 6 Nov 2010 10:31:33 +0100
From:      Hans Petter Selasky <hselasky@c2i.net>
To:        Michael Martin <mgmartin@comcast.net>
Cc:        freebsd-usb@freebsd.org
Subject:   Re: USB 3.0 Fails To Attach Western Digital My Book 3.0
Message-ID:  <201011061031.33986.hselasky@c2i.net>
In-Reply-To: <4CD4ACC9.8040405@comcast.net>
References:  <4CBFEBF5.30203@comcast.net> <201011042037.20274.hselasky@c2i.net> <4CD4ACC9.8040405@comcast.net>

next in thread | previous in thread | raw e-mail | index | archive | help
--Boundary-00=_1BS1MPIyq+BfUSV
Content-Type: Text/Plain;
  charset="iso-8859-15"
Content-Transfer-Encoding: 7bit

Hi,

Can you revert the last patch I sent an apply the attached one?

Then repeat the testing like last time.

--HPS

> 
> I captured several debug outputs here:
> http://appliedtechnicalknowledge.com/freebsd/usb3-patch-214808/ .  Maybe
> something in these can help.

--Boundary-00=_1BS1MPIyq+BfUSV
Content-Type: text/plain; charset="iso-8859-15"; name="usb_30_hub_patch.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
	filename="usb_30_hub_patch.txt"

=== usb_hub.c
==================================================================
--- usb_hub.c	(revision 214808)
+++ usb_hub.c	(local)
@@ -126,9 +126,10 @@
 
 static usb_callback_t uhub_intr_callback;
 
-static void usb_dev_resume_peer(struct usb_device *udev);
-static void usb_dev_suspend_peer(struct usb_device *udev);
-static uint8_t usb_peer_should_wakeup(struct usb_device *udev);
+static void usb_dev_resume_peer(struct usb_device *);
+static void usb_dev_suspend_peer(struct usb_device *);
+static uint8_t usb_peer_should_wakeup(struct usb_device *);
+static uint8_t usb_device_20_compatible(struct usb_device *);
 
 static const struct usb_config uhub_config[UHUB_N_TRANSFER] = {
 
@@ -394,13 +395,29 @@
 		usb_pause_mtx(NULL, 
 		    USB_MS_TO_TICKS(USB_PORT_POWERUP_DELAY));
 
-		/* reset port, which implies enabling it */
+		if (usb_device_20_compatible(udev)) {
+			/* reset port, which implies enabling it */
+			err = usbd_req_reset_port(udev, NULL, portno);
+		} else {
+			switch (UPS_PORT_LINK_STATE_GET(sc->sc_st.port_status)) {
+			case UPS_PORT_LS_U0:
+			case UPS_PORT_LS_U1:
+			case UPS_PORT_LS_U2:
+			case UPS_PORT_LS_U3:
+				/* no reset needed, link is already UP */
+				break;
+			case UPS_PORT_LS_SS_INA:
+				/* try to recover link using a warm reset */
+				goto error;
+			default:
+				/* reset port, which implies enabling it */
+				err = usbd_req_reset_port(udev, NULL, portno);
+				break;
+			}
+		}
 
-		err = usbd_req_reset_port(udev, NULL, portno);
-
 		if (err) {
-			DPRINTFN(0, "port %d reset "
-			    "failed, error=%s\n",
+			DPRINTFN(0, "port %d reset failed, error=%s\n",
 			    portno, usbd_errstr(err));
 			goto error;
 		}
@@ -517,17 +534,43 @@
 		usb_free_device(child, 0);
 		child = NULL;
 	}
-	if (err == 0) {
+	if (err) {
+		DPRINTFN(0, "device problem (%s), "
+		    "port %u\n", usbd_errstr(err), portno);
+		goto error_ret;
+	}
+	if (usb_device_20_compatible(udev)) {
+		/* disable the port, if enabled */
 		if (sc->sc_st.port_status & UPS_PORT_ENABLED) {
 			err = usbd_req_clear_port_feature(
-			    sc->sc_udev, NULL,
-			    portno, UHF_PORT_ENABLE);
+			    udev, NULL, portno, UHF_PORT_ENABLE);
 		}
+	} else {
+		/* get fresh status again */
+		err = uhub_read_port_status(sc, portno);
+		if (err)
+			goto error_ret;
+
+		switch (UPS_PORT_LINK_STATE_GET(sc->sc_st.port_status)) {
+		case UPS_PORT_LS_SS_INA:
+			/* Try a warm port reset to recover the port. */
+			err = usbd_req_warm_reset_port(udev, NULL, portno);
+			if (err) {
+				DPRINTF("warm port reset failed.\n");
+				goto error_ret;
+			}
+			break;
+		default:
+			/* disable the port, if enabled */
+			if (sc->sc_st.port_status & UPS_PORT_ENABLED) {
+				err = usbd_req_clear_port_feature(
+				  udev, NULL, portno, UHF_PORT_ENABLE);
+			}
+			break;
+		}
 	}
-	if (err) {
-		DPRINTFN(0, "device problem (%s), "
-		    "disabling port %d\n", usbd_errstr(err), portno);
-	}
+
+error_ret:
 	return (err);
 }
 

--Boundary-00=_1BS1MPIyq+BfUSV--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201011061031.33986.hselasky>