Index: uhci.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/uhci.c,v retrieving revision 1.257 diff -u -p -u -r1.257 uhci.c --- uhci.c 4 Apr 2013 13:27:56 -0000 1.257 +++ uhci.c 7 Sep 2013 10:08:26 -0000 @@ -1455,17 +1460,39 @@ uhci_check_intr(uhci_softc_t *sc, uhci_i usb_syncmem(&std->dma, std->offs + offsetof(uhci_td_t, td_status), sizeof(std->td.td_status), BUS_DMASYNC_PREREAD); + /* If there's an active TD the xfer isn't done. */ if (status & UHCI_TD_ACTIVE) break; /* Any kind of error makes the xfer done. */ if (status & UHCI_TD_STALLED) goto done; + + /* + * If we're a short control, we need to complete the + * status stage + */ + if ((status & UHCI_TD_SPD) && + (xfer->xfertype == UE_CONTROL) { + usbd_xfer_handle xfer = ii->xfer; + struct uhci_pipe *upipe = + (struct uhci_pipe *)xfer.pipe; + uhci_soft_qh_t *sqh = upipe->u.ctl.sqh; + uhci_soft_td_t *stat = upipe->u.ctl.stat; + + sqh->qh.qh_elink = + htole32(stat->physaddr | UHCI_PTR_TD); + usb_syncmem(&sqh->dma, sqh->offs, + sizeof(sqh->qh), BUS_DMASYNC_PREWRITE); + break; + } + /* We want short packets, and it is short: it's done */ usb_syncmem(&std->dma, std->offs + offsetof(uhci_td_t, td_token), sizeof(std->td.td_token), BUS_DMASYNC_POSTWRITE); + if ((status & UHCI_TD_SPD) && UHCI_TD_GET_ACTLEN(status) < UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token))) @@ -2493,7 +2519,7 @@ uhci_device_request(usbd_xfer_handle xfe return (err); next = data; dataend->link.std = stat; - dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_VF | UHCI_PTR_TD); + dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_TD); usb_syncmem(&dataend->dma, dataend->offs + offsetof(uhci_td_t, td_link), sizeof(dataend->td.td_link), @@ -2507,7 +2533,7 @@ uhci_device_request(usbd_xfer_handle xfe usb_syncmem(&upipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREWRITE); setup->link.std = next; - setup->td.td_link = htole32(next->physaddr | UHCI_PTR_VF | UHCI_PTR_TD); + setup->td.td_link = htole32(next->physaddr | UHCI_PTR_TD); setup->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE); setup->td.td_token = htole32(UHCI_TD_SETUP(sizeof *req, endpt, addr));