Remove a hack to update the address and packet length for every device
authormpi <mpi@openbsd.org>
Wed, 15 Jan 2014 11:10:40 +0000 (11:10 +0000)
committermpi <mpi@openbsd.org>
Wed, 15 Jan 2014 11:10:40 +0000 (11:10 +0000)
request and instead re-open the default pipe with updated values when
attaching a new device, adapted from FreeBSD r162977.

This fixes a problem where the controller could have cached the previous
values and would fail to get the device descriptor, leaving the device
unrecognized with a message like: "device problem, disabling port n".

sys/dev/usb/ehci.c
sys/dev/usb/ohci.c
sys/dev/usb/usb_subr.c

index 68809c3..ed6dcb2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ehci.c,v 1.139 2013/12/06 21:03:04 deraadt Exp $ */
+/*     $OpenBSD: ehci.c,v 1.140 2014/01/15 11:10:40 mpi Exp $ */
 /*     $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $        */
 
 /*
@@ -3052,7 +3052,6 @@ ehci_device_request(struct usbd_xfer *xfer)
        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 *xfer)
        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);
@@ -3083,17 +3082,6 @@ ehci_device_request(struct usbd_xfer *xfer)
        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) {
                struct ehci_soft_qtd *end;
index b76fb02..29b7c30 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ohci.c,v 1.118 2013/12/09 01:02:06 brad Exp $ */
+/*     $OpenBSD: ohci.c,v 1.119 2014/01/15 11:10:40 mpi Exp $ */
 /*     $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $       */
 
@@ -1607,7 +1607,6 @@ ohci_device_request(struct usbd_xfer *xfer)
        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;
@@ -1621,7 +1620,7 @@ ohci_device_request(struct usbd_xfer *xfer)
        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;
@@ -1640,15 +1639,6 @@ ohci_device_request(struct usbd_xfer *xfer)
        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;
 
        /* Set up data transaction */
index ad96f4e..b14092c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usb_subr.c,v 1.95 2013/11/19 14:04:07 pirofti Exp $ */
+/*     $OpenBSD: usb_subr.c,v 1.96 2014/01/15 11:10:40 mpi Exp $ */
 /*     $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $  */
 /*     $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $   */
 
@@ -1164,6 +1164,15 @@ usbd_new_device(struct device *parent, struct usbd_bus *bus, int depth,
 
        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, struct usbd_bus *bus, int depth,
        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",