patch "USB: hub: Fix handling of connect changes during sleep" added to usb-linus
Subsystems (2)
This is a note to let you know that I've just added the patch titled
USB: hub: Fix handling of connect changes during sleep
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From 9f952e26295d977dbfc6fedeaf8c4f112c818d37 Mon Sep 17 00:00:00 2001
From: Alan Stern <[email protected]>
Date: Wed, 22 Apr 2020 16:09:51 -0400
Subject: USB: hub: Fix handling of connect changes during sleep
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.
--- drivers/usb/core/hub.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
drivers/usb/core/hub.c +14 -0
@@ -1223,6 +1223,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 */
@@ -3088,6 +3093,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;
Signature · 1 line
2.26.2