patch "usb: core: hub: Improved device recognition on remote wakeup" added to usb-linus
Subsystems (2)
This is a note to let you know that I've just added the patch titled
usb: core: hub: Improved device recognition on remote wakeup
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 9c06ac4c83df6d6fbdbf7488fbad822b4002ba19 Mon Sep 17 00:00:00 2001
From: Keiya Nobuta <[email protected]>
Date: Thu, 9 Jan 2020 14:14:48 +0900
Subject: usb: core: hub: Improved device recognition on remote wakeup
If hub_activate() is called before D+ has stabilized after remote wakeup, the following situation might occur:
__ ___________________
/ \ /D+ __/ \__/
Hub _______________________________
| ^ ^ ^
| | | |
Host _____v__|___|___________|______
| | | |
| | | \-- Interrupt Transfer (*3)
| | \-- ClearPortFeature (*2) | \-- GetPortStatus (*1)
\-- Host detects remote wakeup
- D+ goes high, Host starts running by remote wakeup
- D+ is not stable, goes low
- Host requests GetPortStatus at (*1) and gets the following hub status:
- Current Connect Status bit is 0
- Connect Status Change bit is 1
- D+ stabilizes, goes high
- Host requests ClearPortFeature and thus Connect Status Change bit is cleared at (*2)
- After waiting 100 ms, Host starts the Interrupt Transfer at (*3)
- Since the Connect Status Change bit is 0, Hub returns NAK.
In this case, port_event() is not called in hub_event() and Host cannot recognize device. To solve this issue, flag change_bits even if only Connect Status Change bit is 1 when got in the first GetPortStatus.
This issue occurs rarely because it only if D+ changes during a very short time between GetPortStatus and ClearPortFeature. However, it is fatal if it occurs in embedded system.
--- drivers/usb/core/hub.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/core/hub.c +1 -0
@@ -1192,6 +1192,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)* PORT_OVER_CURRENT is not. So check for any of them. */ if (udev || (portstatus &USB_PORT_STAT_CONNECTION ) || + (portchange &USB_PORT_STAT_C_CONNECTION ) || (portstatus &USB_PORT_STAT_OVERCURRENT ) || (portchange &USB_PORT_STAT_C_OVERCURRENT ))set_bit (port1, hub->change_bits);
Signature · 1 line
2.24.1