mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
USB: hub: Fix handling of connect changes during sleep
commit 9f952e26295d977dbfc6fedeaf8c4f112c818d37 upstream.
Commit 8099f58f1ecd ("USB: hub: Don't record a connect-change event
during reset-resume") wasn't very well conceived. The problem it
tried to fix was that if a connect-change event occurred while the
system was asleep (such as a device disconnecting itself from the bus
when it is suspended and then reconnecting when it resumes)
requiring a reset-resume during the system wakeup transition, the hub
port's change_bit entry would remain set afterward. This would cause
the hub driver to believe another connect-change event had occurred
after the reset-resume, which was wrong and would lead the driver to
send unnecessary requests to the device (which could interfere with a
firmware update).
The commit tried to fix this by not setting the change_bit during the
wakeup. But this was the wrong thing to do; it means that when a
device is unplugged while the system is asleep, the hub driver doesn't
realize anything has happened: The change_bit flag which would tell it
to handle the disconnect event is clear.
The commit needs to be reverted and the problem fixed in a different
way. Fortunately an alternative solution was noted in the commit's
Changelog: We can continue to set the change_bit entry in
hub_activate() but then clear it when a reset-resume occurs. That way
the the hub driver will see the change_bit when a device is
disconnected but won't see it when the device is still present.
That's what this patch does.
Reported-and-tested-by: Peter Chen <[email protected]>
Signed-off-by: Alan Stern <[email protected]>
Fixes: 8099f58f1ecd ("USB: hub: Don't record a connect-change event during reset-resume")
Tested-by: Paul Zimmerman <[email protected]>
CC: <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
This commit is contained in:
parent
b48193a7c3
commit
50ad463e20
1 changed files with 14 additions and 0 deletions
|
|
@ -1222,6 +1222,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
|||
#ifdef CONFIG_PM
|
||||
udev->reset_resume = 1;
|
||||
#endif
|
||||
/* Don't set the change_bits when the device
|
||||
* was powered off.
|
||||
*/
|
||||
if (test_bit(port1, hub->power_bits))
|
||||
set_bit(port1, hub->change_bits);
|
||||
|
||||
} else {
|
||||
/* The power session is gone; tell hub_wq */
|
||||
|
|
@ -3087,6 +3092,15 @@ static int check_port_resume_type(struct usb_device *udev,
|
|||
if (portchange & USB_PORT_STAT_C_ENABLE)
|
||||
usb_clear_port_feature(hub->hdev, port1,
|
||||
USB_PORT_FEAT_C_ENABLE);
|
||||
|
||||
/*
|
||||
* Whatever made this reset-resume necessary may have
|
||||
* turned on the port1 bit in hub->change_bits. But after
|
||||
* a successful reset-resume we want the bit to be clear;
|
||||
* if it was on it would indicate that something happened
|
||||
* following the reset-resume.
|
||||
*/
|
||||
clear_bit(port1, hub->change_bits);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
|
|
|||
Loading…
Reference in a new issue