diff options
author | iedowse <iedowse@FreeBSD.org> | 2006-10-03 01:13:26 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2006-10-03 01:13:26 +0000 |
commit | 46a11df83f185c8912cfb74fd035093a0c59cbb0 (patch) | |
tree | e7e61920a2025aff8028ac2d90ee3d6334f442a8 /sys/dev/usb | |
parent | 2698dd58d9e2d00e21dedd1f4638404fcced536a (diff) | |
download | FreeBSD-src-46a11df83f185c8912cfb74fd035093a0c59cbb0.zip FreeBSD-src-46a11df83f185c8912cfb74fd035093a0c59cbb0.tar.gz |
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
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/ehci.c | 11 | ||||
-rw-r--r-- | sys/dev/usb/ohci.c | 10 | ||||
-rw-r--r-- | 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 c17e446..07ae977 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 fecc18f..e002702 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 2ac11e3..a8b8512 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 " |