Jesse: Could you please try out the patch below in place of the controversial one I sent you back on July 7? You're the only person I know who has run up against the problem these two patches address.
Oh, yes -- this patch also needs that one-line correction from July 6 applied. Thanks, Alan Stern ===== drivers/usb/core/devices.c 1.38 vs edited ===== --- 1.38/drivers/usb/core/devices.c Thu Jun 24 12:44:16 2004 +++ edited/drivers/usb/core/devices.c Mon Jul 12 14:01:04 2004 @@ -555,10 +555,10 @@ struct usb_device *childdev = usbdev->children[chix]; if (childdev) { - usb_lock_device(childdev); + down(&childdev->serialize); ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev, bus, level + 1, chix, ++cnt); - usb_unlock_device(childdev); + up(&childdev->serialize); if (ret == -EFAULT) return total_written; total_written += ret; ===== drivers/usb/core/hub.c 1.182 vs edited ===== --- 1.182/drivers/usb/core/hub.c Thu Jul 1 10:53:20 2004 +++ edited/drivers/usb/core/hub.c Mon Jul 12 14:10:07 2004 @@ -965,9 +965,11 @@ usb_set_device_state(udev, USB_STATE_NOTATTACHED); /* lock the bus list on behalf of HCDs unregistering their root hubs */ - if (!udev->parent) + if (!udev->parent) { down(&usb_bus_list_lock); - usb_lock_device(udev); + usb_lock_device(udev); + } else + down(&udev->serialize); dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); @@ -996,9 +998,11 @@ *pdev = NULL; spin_unlock_irq(&device_state_lock); - usb_unlock_device(udev); - if (!udev->parent) + if (!udev->parent) { + usb_unlock_device(udev); up(&usb_bus_list_lock); + } else + up(&udev->serialize); device_unregister(&udev->dev); } @@ -1693,7 +1697,7 @@ * udev becomes globally accessible, although presumably * no one will look at it until hdev is unlocked. */ - usb_lock_device (udev); + down(&udev->serialize); status = 0; /* We mustn't add new devices if the parent hub has @@ -1717,7 +1721,7 @@ } } - usb_unlock_device (udev); + up(&udev->serialize); if (status) goto loop; ===== drivers/usb/core/usb.c 1.282 vs edited ===== --- 1.282/drivers/usb/core/usb.c Tue Jul 6 08:00:32 2004 +++ edited/drivers/usb/core/usb.c Mon Jul 12 14:00:12 2004 @@ -845,6 +845,43 @@ put_device(&intf->dev); } + +/* USB device locking + * + * Although locking USB devices should be straightforward, it is + * complicated by the way the driver-model core works. When a new USB + * driver is registered or unregistered, the core will automatically + * probe or disconnect all matching interfaces on all USB devices while + * holding the USB subsystem writelock. There's no good way for us to + * tell which devices will be used or to lock them beforehand. Our only + * option is to effectively lock all the USB devices. + * + * We do that by using a private rw-semaphore, usb_all_devices_rwsem. + * When locking an individual device you must first acquire the rwsem's + * readlock. When a driver is registered or unregistered the writelock + * must be held. These actions are encapsulated in the subroutines + * below, so all a driver needs to do is call usb_lock_device() and + * usb_unlock_device(). + * + * Complications arise when several devices are to be locked at the + * same time. Only hub-aware drivers that are part of usbcore ever have + * to do this; nobody else needs to worry about it. The problem is that + * usb_lock_device() must not be called to lock a second device since it + * would acquire the rwsem's readlock reentrantly, leading to deadlock if + * another thread was waiting for the writelock. The solution is simple: + * + * When locking more than one device, call usb_lock_device() + * to lock the first one. Lock the others by calling + * down(&udev->serialize) directly. + * + * When unlocking multiple devices, use up(&udev->serialize) + * to unlock all but the last one. Unlock the last one by + * calling usb_unlock_device(). + * + * When locking more than one device, always lock the parent + * before locking the child. + */ + /** * usb_lock_device - acquire the lock for a usb device structure * @udev: device that's being locked @@ -976,10 +1013,10 @@ /* look through all of the children of this device */ for (child = 0; child < dev->maxchild; ++child) { if (dev->children[child]) { - usb_lock_device(dev->children[child]); + down(&dev->children[child]->serialize); ret_dev = match_device(dev->children[child], vendor_id, product_id); - usb_unlock_device(dev->children[child]); + up(&dev->children[child]->serialize); if (ret_dev) goto exit; } ------------------------------------------------------- This SF.Net email sponsored by Black Hat Briefings & Training. Attend Black Hat Briefings & Training, Las Vegas July 24-29 - digital self defense, top technical experts, no vendor pitches, unmatched networking opportunities. Visit www.blackhat.com _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel