Subject: kern/8083: Short transfers from bulk ugen devices lose
To: None <gnats-bugs@gnats.netbsd.org>
From: Ed Gould <ed@pa.dec.com>
List: netbsd-bugs
Date: 07/26/1999 15:06:58
>Number: 8083
>Category: kern
>Synopsis: Short transfers from bulk ugen devices lose
>Confidential: yes
>Severity: serious
>Priority: high
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Jul 26 15:05:00 1999
>Last-Modified:
>Originator: Ed Gould
>Organization:
--
Ed Gould Palo Alto Advanced Development Compaq Computer Corp.
+1 650 853 2108 ed@pa.dec.com 130 Lytton Avenue
ed.gould@compaq.com Palo Alto, CA 94301
>Release: 20 July 1999 (but not changed in 26 July sources)
>Environment:
System: NetBSD toblerone.pa.dec.com 1.4G NetBSD 1.4G (TOBLERONE) #19: Mon Jul 26 14:25:04 PDT 1999 ed@toblerone.pa.dec.com:/usr/src/current/sys/arch/i386/compile/TOBLERONE i386
>Description:
Reads from bulk-transfer USB devices using the ugen driver hang
if the data offered is shorter than requested. There is an
ioctl to enable short transfers, but it doesn't do anything.
>How-To-Repeat:
Attempt to read data from a ugen bulk device.
>Fix:
It looked like the fix would be to propogate the flag set by
USB_SET_SHORT_XFER down into the lower layers of the driver,
but this doesn't quite work. If the code in the UE_BULK
branch within ugen_do_read() that reads
r = usbd_bulk_transfer(reqh, sce->pipeh, 0, buf,
&tn, "ugenrb");
is changed to
r = usbd_bulk_transfer(reqh, sce->pipeh,
sce->state & UGEN_SHORT_OK ? USBD_SHORT_XFER_OK : 0,
buf, &tn, "ugenrb");
things get slightly better, but don't work right. In
particular, the first read completes, but the second read
issued never sees its interrupt.
If, instead, uhci_device_bulk_start() is kludged to always
request that the short-transfer bit be set in the TD chain by
changing the code that reads
r = uhci_alloc_std_chain(upipe, sc, len, isread,
reqh->flags & USBD_SHORT_XFER_OK,
dmap, &xfer, &xferend);
to
r = uhci_alloc_std_chain(upipe, sc, len, isread,
1 || reqh->flags & USBD_SHORT_XFER_OK,
dmap, &xfer, &xferend);
and ugen_do_read() is hacked to accept short transfers by
changing
if (r != USBD_NORMAL_COMPLETION) {
...
}
to
if ((r != USBD_NORMAL_COMPLETION) &&
(r != USBD_SHORT_XFER)) {
...
}
then - modulo complaints about short transfers from
uhbd_transfer_cb() - it works as expected.
I have not spent enough time in this code to undersstand why
the "correct" fix of passing the flag set by USB_SET_SHORT_XFER
down to lower levels doesn't work. Either it should be made
to work, or the restriction on unsolicited short transfers
removed.
>Audit-Trail:
>Unformatted: