aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2008-06-30 11:14:43 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-07-21 18:16:48 -0400
commit86c57edf60f5c98adb496880f56cd0e5a3423153 (patch)
treee95742e71c85f85549d3be390803d1fa5328853f /drivers/usb/core
parentac90e36592ea5171c4e70f58b39a782d871a7d9f (diff)
USB: use reset_resume when normal resume fails
This patch (as1109b) makes USB-Persist more resilient to errors. With the current code, if a normal resume fails, it's an unrecoverable error. With the patch, if a normal resume fails (and if the device is enabled for USB-Persist) then a reset-resume is tried. This fixes the problem reported in Bugzilla #10977. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/hub.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f1efabbc1ca..107e1d25dde 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1822,9 +1822,15 @@ static int check_port_resume_type(struct usb_device *udev,
1822 status = -ENODEV; 1822 status = -ENODEV;
1823 } 1823 }
1824 1824
1825 /* Can't do a normal resume if the port isn't enabled */ 1825 /* Can't do a normal resume if the port isn't enabled,
1826 else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume) 1826 * so try a reset-resume instead.
1827 status = -ENODEV; 1827 */
1828 else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume) {
1829 if (udev->persist_enabled)
1830 udev->reset_resume = 1;
1831 else
1832 status = -ENODEV;
1833 }
1828 1834
1829 if (status) { 1835 if (status) {
1830 dev_dbg(hub->intfdev, 1836 dev_dbg(hub->intfdev,
@@ -1973,6 +1979,7 @@ static int finish_port_resume(struct usb_device *udev)
1973 * resumed. 1979 * resumed.
1974 */ 1980 */
1975 if (udev->reset_resume) 1981 if (udev->reset_resume)
1982 retry_reset_resume:
1976 status = usb_reset_and_verify_device(udev); 1983 status = usb_reset_and_verify_device(udev);
1977 1984
1978 /* 10.5.4.5 says be sure devices in the tree are still there. 1985 /* 10.5.4.5 says be sure devices in the tree are still there.
@@ -1984,6 +1991,13 @@ static int finish_port_resume(struct usb_device *udev)
1984 status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); 1991 status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
1985 if (status >= 0) 1992 if (status >= 0)
1986 status = (status > 0 ? 0 : -ENODEV); 1993 status = (status > 0 ? 0 : -ENODEV);
1994
1995 /* If a normal resume failed, try doing a reset-resume */
1996 if (status && !udev->reset_resume && udev->persist_enabled) {
1997 dev_dbg(&udev->dev, "retry with reset-resume\n");
1998 udev->reset_resume = 1;
1999 goto retry_reset_resume;
2000 }
1987 } 2001 }
1988 2002
1989 if (status) { 2003 if (status) {