ChangeSet 1.1043.1.24, 2003/02/18 15:52:11-08:00, greg@kroah.com

[PATCH] USB: add "present" flag to usb_device structure.

This solves lots of races when drivers hold a reference to the usb_device
after the device is physically removed from the system (like when a user
has a open handle.)  This now prevents any new urbs being submitted or
canceled for the device.


diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
--- a/drivers/usb/core/urb.c	Tue Feb 18 16:37:09 2003
+++ b/drivers/usb/core/urb.c	Tue Feb 18 16:37:09 2003
@@ -195,7 +195,7 @@
 
 	if (!urb || urb->hcpriv || !urb->complete)
 		return -EINVAL;
-	if (!(dev = urb->dev) || !dev->bus || dev->devnum <= 0)
+	if (!(dev = urb->dev) || !dev->present || !dev->bus || dev->devnum <= 0)
 		return -ENODEV;
 	if (!(op = dev->bus->op) || !op->submit_urb)
 		return -ENODEV;
@@ -376,7 +376,7 @@
  */
 int usb_unlink_urb(struct urb *urb)
 {
-	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
+	if (urb && urb->dev && urb->dev->present && urb->dev->bus && urb->dev->bus->op)
 		return urb->dev->bus->op->unlink_urb(urb);
 	else
 		return -ENODEV;
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Tue Feb 18 16:37:09 2003
+++ b/drivers/usb/core/usb.c	Tue Feb 18 16:37:09 2003
@@ -679,6 +679,7 @@
 	memset(dev, 0, sizeof(*dev));
 
 	device_initialize(&dev->dev);
+	dev->present = 1;
 
 	usb_bus_get(bus);
 
@@ -853,6 +854,10 @@
 		usbfs_remove_device(dev);
 	}
 	device_unregister(&dev->dev);
+
+	/* mark the device as not present so any further urb submissions for
+	 * this device will fail. */
+	dev->present = 0;
 
 	/* Decrement the reference count, it'll auto free everything when */
 	/* it hits 0 which could very well be now */
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Tue Feb 18 16:37:09 2003
+++ b/include/linux/usb.h	Tue Feb 18 16:37:09 2003
@@ -239,6 +239,7 @@
 
 	int have_langid;		/* whether string_langid is valid yet */
 	int string_langid;		/* language ID for strings */
+	int present;			/* if device is present or not */
 
 	void *hcpriv;			/* Host Controller private data */
 	
