Commit 3ea15966 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e52b1d3a
...@@ -912,7 +912,7 @@ int usb_trylock_device(struct usb_device *udev) ...@@ -912,7 +912,7 @@ int usb_trylock_device(struct usb_device *udev)
* is neither BINDING nor BOUND. Rather than sleeping to wait for the * is neither BINDING nor BOUND. Rather than sleeping to wait for the
* lock, the routine polls repeatedly. This is to prevent deadlock with * lock, the routine polls repeatedly. This is to prevent deadlock with
* disconnect; in some drivers (such as usb-storage) the disconnect() * 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 * 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 * 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) ...@@ -922,6 +922,8 @@ int usb_trylock_device(struct usb_device *udev)
int usb_lock_device_for_reset(struct usb_device *udev, int usb_lock_device_for_reset(struct usb_device *udev,
struct usb_interface *iface) struct usb_interface *iface)
{ {
unsigned long jiffies_expire = jiffies + HZ;
if (udev->state == USB_STATE_NOTATTACHED) if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV; return -ENODEV;
if (udev->state == USB_STATE_SUSPENDED) if (udev->state == USB_STATE_SUSPENDED)
...@@ -938,6 +940,12 @@ int usb_lock_device_for_reset(struct usb_device *udev, ...@@ -938,6 +940,12 @@ int usb_lock_device_for_reset(struct usb_device *udev,
} }
while (!usb_trylock_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); msleep(15);
if (udev->state == USB_STATE_NOTATTACHED) if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV; return -ENODEV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment