From 46a11df83f185c8912cfb74fd035093a0c59cbb0 Mon Sep 17 00:00:00 2001 From: iedowse Date: Tue, 3 Oct 2006 01:13:26 +0000 Subject: [PATCH] When changing the device address and max packet size in usbd_new_device(), close and re-open the default pipe instead of relying on the host controller driver to notice the changes. Remove the unreliable code that attempted to update these fields while the pipe was active. This fixes a case where the hardware could cache and continue to use the old address, resulting in a "getting first desc failed" error. PR: usb/103167 --- sys/dev/usb/ehci.c | 11 ----------- sys/dev/usb/ohci.c | 10 ---------- sys/dev/usb/usb_subr.c | 18 ++++++++++++++++++ 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index c17e4462205a..07ae977cc118 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -2903,17 +2903,6 @@ ehci_device_request(usbd_xfer_handle xfer) sqh->inactivesqtd = newinactive; 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) { ehci_soft_qtd_t *end; diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index fecc18f63957..e00270204be3 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1765,16 +1765,6 @@ ohci_device_request(usbd_xfer_handle 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( - (le32toh(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 */ diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index 2ac11e3056dd..a8b8512abe6f 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -1110,6 +1110,15 @@ usbd_new_device(device_t parent, usbd_bus_handle bus, int depth, dev->address = addr; /* New device address now */ bus->devices[addr] = dev; + /* Re-establish the default pipe with the new address. */ + usbd_kill_pipe(dev->default_pipe); + err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, + &dev->default_pipe); + if (err) { + usbd_remove_device(dev, up); + return (err); + } + dd = &dev->ddesc; /* Get the first 8 bytes of the device descriptor. */ err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); @@ -1153,6 +1162,15 @@ usbd_new_device(device_t parent, usbd_bus_handle bus, int depth, USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize); + /* Re-establish the default pipe with the new max packet size. */ + usbd_kill_pipe(dev->default_pipe); + err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, + &dev->default_pipe); + if (err) { + usbd_remove_device(dev, up); + return (err); + } + err = usbd_reload_device_desc(dev); if (err) { DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "