Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+9 −1
Original line number Original line Diff line number Diff line
@@ -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)
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,
	}
	}


	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;