summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2013-06-25 09:24:35 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2013-06-25 09:24:35 +0000
commit3791d73cae48d9978e29ca8bcdd5ffaabafe2c29 (patch)
treefcb7511e085359d81667a4dfdda0400b29f2779e
parent1092258311b4488efe6b317745090fff7f08bb93 (diff)
Bring ohci(4) and uhci(4) in sync with ehci(4) by ensuring that a
transfer is submitted when a zero-length bulk or interrupt transfer is requested. This is the missing part of FreeBSD's svn r159024 that should have been committed with ehci's r1.57. ok uebayasi@
-rw-r--r--sys/dev/usb/ohci.c17
-rw-r--r--sys/dev/usb/uhci.c9
2 files changed, 12 insertions, 14 deletions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 4b2074cf7a2..f84fc8739af 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohci.c,v 1.113 2013/05/30 16:15:02 deraadt Exp $ */
+/* $OpenBSD: ohci.c,v 1.114 2013/06/25 09:24:34 mpi Exp $ */
/* $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $ */
/* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */
@@ -503,7 +503,7 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, struct ohci_softc *sc,
u_int alen, int rd, struct usbd_xfer *xfer,
struct ohci_soft_td *sp, struct ohci_soft_td **ep)
{
- struct ohci_soft_td *next, *cur;
+ struct ohci_soft_td *next, *cur, *end;
ohci_physaddr_t dataphys, dataphysend;
u_int32_t tdflags;
u_int len, curlen;
@@ -514,6 +514,8 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, struct ohci_softc *sc,
len = alen;
cur = sp;
+ end = NULL;
+
dataphys = DMAADDR(dma, 0);
dataphysend = OHCI_PAGE(dataphys + len - 1);
tdflags = htole32(
@@ -521,7 +523,7 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, struct ohci_softc *sc,
(flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR);
- for (;;) {
+ while (len > 0) {
next = ohci_alloc_std(sc);
if (next == NULL)
goto nomem;
@@ -558,17 +560,15 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, struct ohci_softc *sc,
cur->xfer = xfer;
DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
dataphys, dataphys + curlen - 1));
- if (len == 0)
- break;
DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
dataphys += curlen;
+ end = cur;
cur = next;
}
- if (!rd && (flags & USBD_FORCE_SHORT_XFER) &&
+ if (!rd && ((flags & USBD_FORCE_SHORT_XFER) || alen == 0) &&
alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
/* Force a 0 length transfer at the end. */
- cur = next;
next = ohci_alloc_std(sc);
if (next == NULL)
goto nomem;
@@ -582,8 +582,9 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, struct ohci_softc *sc,
cur->flags = 0;
cur->xfer = xfer;
DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
+ end = cur;
}
- *ep = cur;
+ *ep = end;
return (USBD_NORMAL_COMPLETION);
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index d2168f094ce..ab345c2cbc5 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhci.c,v 1.98 2013/05/30 16:15:02 deraadt Exp $ */
+/* $OpenBSD: uhci.c,v 1.99 2013/06/25 09:24:34 mpi Exp $ */
/* $NetBSD: uhci.c,v 1.172 2003/02/23 04:19:26 simonb Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */
@@ -1647,14 +1647,11 @@ uhci_alloc_std_chain(struct uhci_pipe *upipe, struct uhci_softc *sc, u_int len,
return (USBD_INVAL);
}
ntd = (len + maxp - 1) / maxp;
+ if (len == 0)
+ flags |= USBD_FORCE_SHORT_XFER;
if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0)
ntd++;
DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd));
- if (ntd == 0) {
- *sp = *ep = 0;
- DPRINTFN(-1,("uhci_alloc_std_chain: ntd=0\n"));
- return (USBD_NORMAL_COMPLETION);
- }
tog = upipe->nexttoggle;
if (ntd % 2 == 0)
tog ^= 1;