summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2006-05-28 23:52:28 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2006-05-28 23:52:28 +0000
commit404ee465a85d4279109b767b5a1f39cc390012a4 (patch)
treed41c47a6feb825ad98b948a0080c67211a91a319 /sys/dev
parent539abeda35c1281656f73efa5990f655b0521794 (diff)
Make sure to honor the USBD_FORCE_SHORT_XFER flag and generate an empty
transfer when necessary. From Dan Ellis via NetBSD rev 1.102
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/ehci.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
index 7e459c04ed0..e3f88a607b5 100644
--- a/sys/dev/usb/ehci.c
+++ b/sys/dev/usb/ehci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehci.c,v 1.53 2005/12/03 03:40:52 brad Exp $ */
+/* $OpenBSD: ehci.c,v 1.54 2006/05/28 23:52:27 pascoe Exp $ */
/* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */
/*
@@ -2240,6 +2240,7 @@ ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc, int alen,
int len, curlen, mps;
int i, tog;
usb_dma_t *dma = &xfer->dmabuf;
+ u_int16_t flags = xfer->flags;
DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen));
@@ -2292,7 +2293,14 @@ ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc, int alen,
dataphys, dataphyslastpage, len, curlen));
len -= curlen;
- if (len != 0) {
+ /*
+ * Allocate another transfer if there's more data left,
+ * or if force last short transfer flag is set and we're
+ * allocating a multiple of the max packet size.
+ */
+ if (len != 0 ||
+ ((curlen % mps) == 0 && !rd && curlen != 0 &&
+ (flags & USBD_FORCE_SHORT_XFER))) {
next = ehci_alloc_sqtd(sc);
if (next == NULL)
goto nomem;
@@ -2329,7 +2337,7 @@ ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc, int alen,
tog ^= 1;
qtdstatus ^= EHCI_QTD_TOGGLE_MASK;
}
- if (len == 0)
+ if (next == NULL)
break;
DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n"));
dataphys += curlen;