On 22/11/13(Fri) 13:48, Stuart Henderson wrote:
> uhub2: port 2, set config at addr 3 failed
> uhub2: device problem, disabling port 2
> 
> When this happens, is there any way to get the port back without rebooting?

Have you tried suspending/resuming the machine?

Apart from that, the diff below is adapted from FreeBSD's r162977 and
should fix most of the cases that generate such "disabling port X"
error.  Miod has recently bugged me about it, but as always I'm
slacking...

Can you give it a try and tell me if it improves your situation?  I
have a hard time finding the right machine/device combinaison to test
it.


Index: ehci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ehci.c,v
retrieving revision 1.138
diff -u -p -r1.138 ehci.c
--- ehci.c      9 Nov 2013 08:46:05 -0000       1.138
+++ ehci.c      25 Nov 2013 14:12:20 -0000
@@ -3052,7 +3052,6 @@ ehci_device_request(struct usbd_xfer *xf
        usb_device_request_t *req = &xfer->request;
        struct usbd_device *dev = epipe->pipe.device;
        struct ehci_softc *sc = (struct ehci_softc *)dev->bus;
-       int addr = dev->address;
        struct ehci_soft_qtd *setup, *stat, *next;
        struct ehci_soft_qh *sqh;
        int isread;
@@ -3066,7 +3065,7 @@ ehci_device_request(struct usbd_xfer *xf
        DPRINTFN(3,("ehci_device_request: type=0x%02x, request=0x%02x, "
            "wValue=0x%04x, wIndex=0x%04x len=%u, addr=%d, endpt=%d\n",
            req->bmRequestType, req->bRequest, UGETW(req->wValue),
-           UGETW(req->wIndex), len, addr,
+           UGETW(req->wIndex), len, dev->address,
            epipe->pipe.endpoint->edesc->bEndpointAddress));
 
        setup = ehci_alloc_sqtd(sc);
@@ -3082,17 +3081,6 @@ ehci_device_request(struct usbd_xfer *xf
 
        sqh = epipe->sqh;
        epipe->u.ctl.length = len;
-
-       /* Update device address and length since they may have changed
-          during the setup of the control pipe in usbd_new_device(). */
-       /* XXX This only needs to be done once, but it's too early in open. */
-       /* XXXX Should not touch ED here! */
-       sqh->qh.qh_endp =
-           (sqh->qh.qh_endp & htole32(~(EHCI_QH_ADDRMASK | EHCI_QH_MPLMASK))) |
-           htole32(
-            EHCI_QH_SET_ADDR(addr) |
-            EHCI_QH_SET_MPL(UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize))
-           );
 
        /* Set up data transaction */
        if (len != 0) {
Index: ohci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ohci.c,v
retrieving revision 1.116
diff -u -p -r1.116 ohci.c
--- ohci.c      9 Nov 2013 08:46:05 -0000       1.116
+++ ohci.c      25 Nov 2013 14:12:20 -0000
@@ -1604,7 +1604,6 @@ ohci_device_request(struct usbd_xfer *xf
        usb_device_request_t *req = &xfer->request;
        struct usbd_device *dev = opipe->pipe.device;
        struct ohci_softc *sc = (struct ohci_softc *)dev->bus;
-       int addr = dev->address;
        struct ohci_soft_td *setup, *stat, *next, *tail;
        struct ohci_soft_ed *sed;
        int isread;
@@ -1618,7 +1617,7 @@ ohci_device_request(struct usbd_xfer *xf
        DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, "
                    "wValue=0x%04x, wIndex=0x%04x len=%u, addr=%d, endpt=%d\n",
                    req->bmRequestType, req->bRequest, UGETW(req->wValue),
-                   UGETW(req->wIndex), len, addr,
+                   UGETW(req->wIndex), len, dev->address,
                    opipe->pipe.endpoint->edesc->bEndpointAddress));
 
        setup = opipe->tail.td;
@@ -1636,15 +1635,6 @@ ohci_device_request(struct usbd_xfer *xf
 
        sed = opipe->sed;
        opipe->u.ctl.length = len;
-
-       /* Update device address and length since they may have changed
-          during the setup of the control pipe in usbd_new_device(). */
-       /* XXX This only needs to be done once, but it's too early in open. */
-       /* XXXX Should not touch ED here! */
-       sed->ed.ed_flags = htole32(
-        (letoh32(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
-        OHCI_ED_SET_FA(addr) |
-        OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize)));
 
        next = stat;
 
Index: usb_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usb_subr.c,v
retrieving revision 1.95
diff -u -p -r1.95 usb_subr.c
--- usb_subr.c  19 Nov 2013 14:04:07 -0000      1.95
+++ usb_subr.c  25 Nov 2013 14:12:20 -0000
@@ -1164,6 +1164,15 @@ usbd_new_device(struct device *parent, s
 
        USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
 
+       /* Re-establish the default pipe with the new max packet size. */
+       usbd_abort_pipe(dev->default_pipe);
+       err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+           &dev->default_pipe);
+       if (err) {
+               usb_free_device(dev, up);
+               return (err);
+       }
+
        err = usbd_reload_device_desc(dev);
        if (err) {
                DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
@@ -1187,9 +1196,17 @@ usbd_new_device(struct device *parent, s
        dev->address = addr;    /* New device address now */
        bus->devices[addr] = dev;
 
+       /* Re-establish the default pipe with the new address. */
+       usbd_abort_pipe(dev->default_pipe);
+       err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+           &dev->default_pipe);
+       if (err) {
+               usb_free_device(dev, up);
+               return (err);
+       }
+
        /* send disown request to handover 2.0 to 1.1. */
        if (dev->quirks->uq_flags & UQ_EHCI_NEEDTO_DISOWN) {
-               
                /* only effective when the target device is on ehci */
                if (dev->bus->usbrev == USBREV_2_0) {
                        DPRINTF(("%s: disown request issues to dev:%p on usb2.0 
bus\n",

Reply via email to