summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2006-10-03 01:13:26 +0000
committeriedowse <iedowse@FreeBSD.org>2006-10-03 01:13:26 +0000
commit46a11df83f185c8912cfb74fd035093a0c59cbb0 (patch)
treee7e61920a2025aff8028ac2d90ee3d6334f442a8 /sys/dev/usb
parent2698dd58d9e2d00e21dedd1f4638404fcced536a (diff)
downloadFreeBSD-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.c11
-rw-r--r--sys/dev/usb/ohci.c10
-rw-r--r--sys/dev/usb/usb_subr.c18
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 "
OpenPOWER on IntegriCloud