summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-08-11 10:15:39 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-08 16:28:21 -0700
commit3ea15966ed59f2bc20928c7b0496b4585f6de206 (patch)
tree45c392aa393fe4ad245b6593b5a74f212f010637 /drivers/usb
parente52b1d3afe698cb77c080ecbe9e745257ff8c81b (diff)
[PATCH] USB: Add timeout to usb_lock_device_for_reset
This patch (as555) modifies the already-awkward usb_lock_device_for_reset routine in usbcore by adding a timeout. The whole point of the routine is that the caller wants to acquire some semaphores in the wrong order; protecting against the possibility of deadlock by timing out seems only prudent. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/usb.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index bc966dbc6021..109f7558167a 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -912,7 +912,7 @@ int usb_trylock_device(struct usb_device *udev)
* is neither BINDING nor BOUND. Rather than sleeping to wait for the
* lock, the routine polls repeatedly. This is to prevent deadlock with
* disconnect; in some drivers (such as usb-storage) the disconnect()
- * callback will block waiting for a device reset to complete.
+ * or suspend() method will block waiting for a device reset to complete.
*
* Returns a negative error code for failure, otherwise 1 or 0 to indicate
* that the device will or will not have to be unlocked. (0 can be
@@ -922,6 +922,8 @@ int usb_trylock_device(struct usb_device *udev)
int usb_lock_device_for_reset(struct usb_device *udev,
struct usb_interface *iface)
{
+ unsigned long jiffies_expire = jiffies + HZ;
+
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
if (udev->state == USB_STATE_SUSPENDED)
@@ -938,6 +940,12 @@ int usb_lock_device_for_reset(struct usb_device *udev,
}
while (!usb_trylock_device(udev)) {
+
+ /* If we can't acquire the lock after waiting one second,
+ * we're probably deadlocked */
+ if (time_after(jiffies, jiffies_expire))
+ return -EBUSY;
+
msleep(15);
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;