It is very common that hub status endpoint has a long 'bInterval', for example, it may be 11(128ms for HS device) or 12(256ms for HS device), so the device connection change may be reported a bit later via status pipe. So there may have device connection changes happened already on the downstream ports, and no status URB completes when it is killed in hub auto-suspend path, which may miss the connection change event and let hub suspend successfully. This patch introduces check_ports_changed() to check port change event in auto-suspend path, and recover hub state and return -EBUSY if change events are found. The disadvantage is that some delay may be introduced in hub auto-suspend path. Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxxxxx> --- drivers/usb/core/hub.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6dc41c6..382dc41 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3158,6 +3158,21 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) #endif +static int check_ports_changed(struct usb_hub *hub) +{ + int port1; + + for (port1 = 1; port1 <= hub->hdev->maxchild; ++port1) { + u16 portstatus, portchange; + int status; + + status = hub_port_status(hub, port1, &portstatus, &portchange); + if (!status && portchange) + return 1; + } + return 0; +} + static int hub_suspend(struct usb_interface *intf, pm_message_t msg) { struct usb_hub *hub = usb_get_intfdata (intf); @@ -3192,6 +3207,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) /* stop khubd and related activity */ hub_quiesce(hub, HUB_SUSPEND); + + if (PMSG_IS_AUTO(msg)) { + /* check if there are changes pending on hub ports */ + if (check_ports_change(hub)) { + hub_activate(hub, HUB_RESUME); + return -EBUSY; + } + } + return 0; } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html