Skip site navigation (1)Skip section navigation (2)
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>