After successful port reset by set_port_feature, some devices show immediate link connection which generates port connect change interrupt. But, the next step is an unconditional usb_clear_port_feature and this flow always clears USB_PORT_FEAT_C_CONNECTION bit in port status though next kick_khubd is reserved by link connection interrupt. This flow can make an ambiguous state in the next port_evnet operation, port_status is connected state such as 0x203 but port_change is zero value caused by the previous clear port feature. So, port_event can't call hub_port_connect_change and there is no other way to peform connect procedure.
Signed-off-by: hyunho747.kim <[email protected]> --- drivers/usb/core/hub.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 73dfa19..4508aff 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2761,18 +2761,21 @@ static int hub_port_reset(struct usb_hub *hub, int port1, /* Check for disconnect or reset */ if (status == 0 || status == -ENOTCONN || status == -ENODEV) { - usb_clear_port_feature(hub->hdev, port1, + if (status) + usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_RESET); if (!hub_is_superspeed(hub->hdev)) goto done; - usb_clear_port_feature(hub->hdev, port1, + if (status) { + usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_BH_PORT_RESET); - usb_clear_port_feature(hub->hdev, port1, + usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_PORT_LINK_STATE); - usb_clear_port_feature(hub->hdev, port1, + usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_CONNECTION); + } /* * If a USB 3.0 device migrates from reset to an error -- 2.2.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

