提交 5e467f6e 编写于 作者: A Andiry Xu 提交者: Sarah Sharp

usbcore: warm reset USB3 port in SS.Inactive state

Some USB3.0 devices go to SS.Inactive state when hot plug to USB3 ports.
Warm reset the port to transition it to U0 state.

This patch fixes the issue that Kingston USB3.0 flash drive can not be
recognized when hot plug to USB3 port.
Signed-off-by: NAndiry Xu <andiry.xu@amd.com>
Signed-off-by: NSarah Sharp <sarah.a.sharp@linux.intel.com>
上级 a7114230
...@@ -2151,6 +2151,42 @@ static int hub_port_reset(struct usb_hub *hub, int port1, ...@@ -2151,6 +2151,42 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
return status; return status;
} }
/* Warm reset a USB3 protocol port */
static int hub_port_warm_reset(struct usb_hub *hub, int port)
{
int ret;
u16 portstatus, portchange;
if (!hub_is_superspeed(hub->hdev)) {
dev_err(hub->intfdev, "only USB3 hub support warm reset\n");
return -EINVAL;
}
/* Warm reset the port */
ret = set_port_feature(hub->hdev,
port, USB_PORT_FEAT_BH_PORT_RESET);
if (ret) {
dev_err(hub->intfdev, "cannot warm reset port %d\n", port);
return ret;
}
msleep(20);
ret = hub_port_status(hub, port, &portstatus, &portchange);
if (portchange & USB_PORT_STAT_C_RESET)
clear_port_feature(hub->hdev, port, USB_PORT_FEAT_C_RESET);
if (portchange & USB_PORT_STAT_C_BH_RESET)
clear_port_feature(hub->hdev, port,
USB_PORT_FEAT_C_BH_PORT_RESET);
if (portchange & USB_PORT_STAT_C_LINK_STATE)
clear_port_feature(hub->hdev, port,
USB_PORT_FEAT_C_PORT_LINK_STATE);
return ret;
}
/* Check if a port is power on */ /* Check if a port is power on */
static int port_is_power_on(struct usb_hub *hub, unsigned portstatus) static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
{ {
...@@ -3519,6 +3555,16 @@ static void hub_events(void) ...@@ -3519,6 +3555,16 @@ static void hub_events(void)
USB_PORT_FEAT_C_PORT_CONFIG_ERROR); USB_PORT_FEAT_C_PORT_CONFIG_ERROR);
} }
/* Warm reset a USB3 protocol port if it's in
* SS.Inactive state.
*/
if (hub_is_superspeed(hub->hdev) &&
(portstatus & USB_PORT_STAT_LINK_STATE)
== USB_SS_PORT_LS_SS_INACTIVE) {
dev_dbg(hub_dev, "warm reset port %d\n", i);
hub_port_warm_reset(hub, i);
}
if (connect_change) if (connect_change)
hub_port_connect_change(hub, i, hub_port_connect_change(hub, i,
portstatus, portchange); portstatus, portchange);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册