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
This commit is contained in:
iedowse 2006-10-03 01:13:26 +00:00
parent 2698dd58d9
commit 46a11df83f
3 changed files with 18 additions and 21 deletions

View File

@ -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;

View File

@ -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 */

View File

@ -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 "