diff options
| author | Alan Stern <stern@rowland.harvard.edu> | 2005-08-11 10:15:39 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-09-08 19:28:21 -0400 |
| commit | 3ea15966ed59f2bc20928c7b0496b4585f6de206 (patch) | |
| tree | 45c392aa393fe4ad245b6593b5a74f212f010637 /drivers/usb | |
| parent | e52b1d3afe698cb77c080ecbe9e745257ff8c81b (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.c | 10 |
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) | |||
| 912 | * is neither BINDING nor BOUND. Rather than sleeping to wait for the | 912 | * is neither BINDING nor BOUND. Rather than sleeping to wait for the |
| 913 | * lock, the routine polls repeatedly. This is to prevent deadlock with | 913 | * lock, the routine polls repeatedly. This is to prevent deadlock with |
| 914 | * disconnect; in some drivers (such as usb-storage) the disconnect() | 914 | * disconnect; in some drivers (such as usb-storage) the disconnect() |
| 915 | * callback will block waiting for a device reset to complete. | 915 | * or suspend() method will block waiting for a device reset to complete. |
| 916 | * | 916 | * |
| 917 | * Returns a negative error code for failure, otherwise 1 or 0 to indicate | 917 | * Returns a negative error code for failure, otherwise 1 or 0 to indicate |
| 918 | * that the device will or will not have to be unlocked. (0 can be | 918 | * 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 | int usb_lock_device_for_reset(struct usb_device *udev, | 922 | int usb_lock_device_for_reset(struct usb_device *udev, |
| 923 | struct usb_interface *iface) | 923 | struct usb_interface *iface) |
| 924 | { | 924 | { |
| 925 | unsigned long jiffies_expire = jiffies + HZ; | ||
| 926 | |||
| 925 | if (udev->state == USB_STATE_NOTATTACHED) | 927 | if (udev->state == USB_STATE_NOTATTACHED) |
| 926 | return -ENODEV; | 928 | return -ENODEV; |
| 927 | if (udev->state == USB_STATE_SUSPENDED) | 929 | if (udev->state == USB_STATE_SUSPENDED) |
| @@ -938,6 +940,12 @@ int usb_lock_device_for_reset(struct usb_device *udev, | |||
| 938 | } | 940 | } |
| 939 | 941 | ||
| 940 | while (!usb_trylock_device(udev)) { | 942 | while (!usb_trylock_device(udev)) { |
| 943 | |||
| 944 | /* If we can't acquire the lock after waiting one second, | ||
| 945 | * we're probably deadlocked */ | ||
| 946 | if (time_after(jiffies, jiffies_expire)) | ||
| 947 | return -EBUSY; | ||
| 948 | |||
| 941 | msleep(15); | 949 | msleep(15); |
| 942 | if (udev->state == USB_STATE_NOTATTACHED) | 950 | if (udev->state == USB_STATE_NOTATTACHED) |
| 943 | return -ENODEV; | 951 | return -ENODEV; |
