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.
=== 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);
 }
 
_______________________________________________
freebsd-usb@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to "freebsd-usb-unsubscr...@freebsd.org"

Reply via email to