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>