Date: Mon, 25 Nov 2002 16:45:51 +0300 From: Yar Tikhiy <yar@freebsd.org> To: freebsd-hackers@freebsd.org Subject: Review by USB wizard wanted Message-ID: <20021125164551.A26800@comp.chem.msu.su>
next in thread | raw e-mail | index | archive | help
Hi folks,
I'm playing with a Sony USB memory stick reader/writer. It's a
pretty slow device, so it triggers some bugs in the FreeBSD USB
code unnoticed before. I'm new to USB programming, so I submit
my notes to a discussion or review.
First, sometimes (especially, if twitching a memory stick out of
the reader while the device is being detected) a transfer to the
umass device is initiated *after* the device is already gone. System
panic follows. The transfer is initiated when destroying the default
pipe to the device. Indeed, the current usb_subr.c code will detach
child devices first and destroy the default pipe then. Reverting
this order eliminates the panic.
Second, twitching a memory stick can cause CAM jam. That happens
because the umass detach routine won't wake up the upper layer when
processing a device with a pending transfer on it.
Patches addressing the above problems are attached below.
--
Yar
--- usb_subr.c.orig Sat Nov 16 12:07:50 2002
+++ usb_subr.c Fri Nov 22 15:45:35 2002
@@ -1292,8 +1292,6 @@
{
int ifcidx, nifc;
- if (dev->default_pipe != NULL)
- usbd_kill_pipe(dev->default_pipe);
if (dev->ifaces != NULL) {
nifc = dev->cdesc->bNumInterface;
for (ifcidx = 0; ifcidx < nifc; ifcidx++)
@@ -1340,6 +1338,9 @@
return;
}
#endif
+
+ if (dev->default_pipe != NULL)
+ usbd_kill_pipe(dev->default_pipe);
if (dev->subdevs != NULL) {
DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
--- umass.c.orig Sat Nov 16 12:07:50 2002
+++ umass.c Fri Nov 22 21:42:10 2002
@@ -1033,6 +1033,13 @@
/* detach the device from the SCSI host controller (SIM) */
err = umass_cam_detach(sc);
+ /* if upper layer is waiting for a transfer to finish, wake it up */
+ if (sc->transfer_state != TSTATE_IDLE) {
+ sc->transfer_state = TSTATE_IDLE;
+ sc->transfer_cb(sc, sc->transfer_priv,
+ sc->transfer_datalen, STATUS_WIRE_FAILED);
+ }
+
for (i = 0; i < XFER_NR; i++)
if (sc->transfer_xfer[i])
usbd_free_xfer(sc->transfer_xfer[i]);
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021125164551.A26800>
