Skip to content

Commit 5257d97

Browse files
AlanSterngregkh
authored andcommitted
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: Alan Stern <[email protected]> Tested-by: Frans Pop <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent af747c4 commit 5257d97

File tree

1 file changed

+17
-22
lines changed

1 file changed

+17
-22
lines changed

drivers/usb/core/hub.c

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2683,35 +2683,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
26832683
USB_PORT_STAT_C_ENABLE);
26842684
#endif
26852685

2686-
/* Try to use the debounce delay for protection against
2687-
* port-enable changes caused, for example, by EMI.
2688-
*/
2689-
if (portchange & (USB_PORT_STAT_C_CONNECTION |
2690-
USB_PORT_STAT_C_ENABLE)) {
2691-
status = hub_port_debounce(hub, port1);
2692-
if (status < 0) {
2693-
if (printk_ratelimit())
2694-
dev_err (hub_dev, "connect-debounce failed, "
2695-
"port %d disabled\n", port1);
2696-
portstatus &= ~USB_PORT_STAT_CONNECTION;
2697-
} else {
2698-
portstatus = status;
2699-
}
2700-
}
2701-
27022686
/* Try to resuscitate an existing device */
27032687
udev = hdev->children[port1-1];
27042688
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
27052689
udev->state != USB_STATE_NOTATTACHED) {
2706-
27072690
usb_lock_device(udev);
27082691
if (portstatus & USB_PORT_STAT_ENABLE) {
27092692
status = 0; /* Nothing to do */
2710-
} else if (!udev->persist_enabled) {
2711-
status = -ENODEV; /* Mustn't resuscitate */
27122693

27132694
#ifdef CONFIG_USB_SUSPEND
2714-
} else if (udev->state == USB_STATE_SUSPENDED) {
2695+
} else if (udev->state == USB_STATE_SUSPENDED &&
2696+
udev->persist_enabled) {
27152697
/* For a suspended device, treat this as a
27162698
* remote wakeup event.
27172699
*/
@@ -2726,7 +2708,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
27262708
#endif
27272709

27282710
} else {
2729-
status = usb_reset_device(udev);
2711+
status = -ENODEV; /* Don't resuscitate */
27302712
}
27312713
usb_unlock_device(udev);
27322714

@@ -2741,14 +2723,27 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
27412723
usb_disconnect(&hdev->children[port1-1]);
27422724
clear_bit(port1, hub->change_bits);
27432725

2726+
if (portchange & (USB_PORT_STAT_C_CONNECTION |
2727+
USB_PORT_STAT_C_ENABLE)) {
2728+
status = hub_port_debounce(hub, port1);
2729+
if (status < 0) {
2730+
if (printk_ratelimit())
2731+
dev_err(hub_dev, "connect-debounce failed, "
2732+
"port %d disabled\n", port1);
2733+
portstatus &= ~USB_PORT_STAT_CONNECTION;
2734+
} else {
2735+
portstatus = status;
2736+
}
2737+
}
2738+
27442739
/* Return now if debouncing failed or nothing is connected */
27452740
if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
27462741

27472742
/* maybe switch power back on (e.g. root hub was reset) */
27482743
if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
27492744
&& !(portstatus & (1 << USB_PORT_FEAT_POWER)))
27502745
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
2751-
2746+
27522747
if (portstatus & USB_PORT_STAT_ENABLE)
27532748
goto done;
27542749
return;

0 commit comments

Comments
 (0)