Commit 5257d97a authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

USB: revert recovery from transient errors

This patch (as1135) essentially reverts the major parts of two earlier
patches to usbcore, because they ended up causing a regression.

Trying to recover from transient communication errors can lead to
other problems, because operations that failed during the error period
are not always retried.  The simplest example is the initial
Set-Config request sent after device enumeration; if it gets lost then
it will not be retried and the device will remain unconfigured.

This patch restores the old behavior in which any port disconnect or
port disable causes the entire device structure to be removed, fixing a
reported regression.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Tested-by: default avatarFrans Pop <elendil@planet.nl>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent af747c46
...@@ -2683,35 +2683,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -2683,35 +2683,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
USB_PORT_STAT_C_ENABLE); USB_PORT_STAT_C_ENABLE);
#endif #endif
/* Try to use the debounce delay for protection against
* port-enable changes caused, for example, by EMI.
*/
if (portchange & (USB_PORT_STAT_C_CONNECTION |
USB_PORT_STAT_C_ENABLE)) {
status = hub_port_debounce(hub, port1);
if (status < 0) {
if (printk_ratelimit())
dev_err (hub_dev, "connect-debounce failed, "
"port %d disabled\n", port1);
portstatus &= ~USB_PORT_STAT_CONNECTION;
} else {
portstatus = status;
}
}
/* Try to resuscitate an existing device */ /* Try to resuscitate an existing device */
udev = hdev->children[port1-1]; udev = hdev->children[port1-1];
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
udev->state != USB_STATE_NOTATTACHED) { udev->state != USB_STATE_NOTATTACHED) {
usb_lock_device(udev); usb_lock_device(udev);
if (portstatus & USB_PORT_STAT_ENABLE) { if (portstatus & USB_PORT_STAT_ENABLE) {
status = 0; /* Nothing to do */ status = 0; /* Nothing to do */
} else if (!udev->persist_enabled) {
status = -ENODEV; /* Mustn't resuscitate */
#ifdef CONFIG_USB_SUSPEND #ifdef CONFIG_USB_SUSPEND
} else if (udev->state == USB_STATE_SUSPENDED) { } else if (udev->state == USB_STATE_SUSPENDED &&
udev->persist_enabled) {
/* For a suspended device, treat this as a /* For a suspended device, treat this as a
* remote wakeup event. * remote wakeup event.
*/ */
...@@ -2726,7 +2708,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -2726,7 +2708,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
#endif #endif
} else { } else {
status = usb_reset_device(udev); status = -ENODEV; /* Don't resuscitate */
} }
usb_unlock_device(udev); usb_unlock_device(udev);
...@@ -2741,6 +2723,19 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -2741,6 +2723,19 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
usb_disconnect(&hdev->children[port1-1]); usb_disconnect(&hdev->children[port1-1]);
clear_bit(port1, hub->change_bits); clear_bit(port1, hub->change_bits);
if (portchange & (USB_PORT_STAT_C_CONNECTION |
USB_PORT_STAT_C_ENABLE)) {
status = hub_port_debounce(hub, port1);
if (status < 0) {
if (printk_ratelimit())
dev_err(hub_dev, "connect-debounce failed, "
"port %d disabled\n", port1);
portstatus &= ~USB_PORT_STAT_CONNECTION;
} else {
portstatus = status;
}
}
/* Return now if debouncing failed or nothing is connected */ /* Return now if debouncing failed or nothing is connected */
if (!(portstatus & USB_PORT_STAT_CONNECTION)) { if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
...@@ -2748,7 +2743,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -2748,7 +2743,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2 if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
&& !(portstatus & (1 << USB_PORT_FEAT_POWER))) && !(portstatus & (1 << USB_PORT_FEAT_POWER)))
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
if (portstatus & USB_PORT_STAT_ENABLE) if (portstatus & USB_PORT_STAT_ENABLE)
goto done; goto done;
return; return;
......
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