usb: core: hub: ensure power on hcd if attempt power cycle
When do USB hot plug test in USB EHCI/OHIC interface, we meet a problem that USB HS device can't be recognized with the following error log: Cannot enable. Maybe the USB cable is bad? Cannot enable. Maybe the USB cable is bad? attempt power cycle Cannot enable. Maybe the USB cable is bad? Cannot enable. Maybe the USB cable is bad? It's hard to reproduce this issue, but the "attempt power cycle" logic does have a problem for EHCI. When do USB hot plug test with a USB HS device, the HS handshake may fail at some time due to unknown reason, and the USB controller driver will set the PORT_OWNER flag in EHCI register to change to OHCI companion first. Then hub_port_connect() calls the usb_hub_set_port_power() to attempt power cycle the EHCI. However, it fail to power on the EHCI because the EHCI driver check the PORT_OWNER flag is true and return immediately. This patch adds a HCD_FLAG_POWER_ON flag to ensure power on the EHCI in this case. Change-Id: I33f5fbaca5d9fbaa978f831db18ff7b20ea70bd8 Signed-off-by: William Wu <william.wu@rock-chips.com>
This commit is contained in:
@ -5188,6 +5188,7 @@ loop:
|
||||
dev_info(&port_dev->dev, "attempt power cycle\n");
|
||||
usb_hub_set_port_power(hdev, hub, port1, false);
|
||||
msleep(2 * hub_power_on_good_delay(hub));
|
||||
set_bit(HCD_FLAG_POWER_ON, &hcd->flags);
|
||||
usb_hub_set_port_power(hdev, hub, port1, true);
|
||||
msleep(hub_power_on_good_delay(hub));
|
||||
}
|
||||
|
||||
@ -1174,7 +1174,7 @@ int ehci_hub_control(
|
||||
goto error;
|
||||
wIndex--;
|
||||
temp = ehci_readl(ehci, status_reg);
|
||||
if (temp & PORT_OWNER)
|
||||
if ((temp & PORT_OWNER) && (!HCD_POWER_ON(hcd)))
|
||||
break;
|
||||
|
||||
temp &= ~PORT_RWC_BITS;
|
||||
@ -1217,6 +1217,7 @@ int ehci_hub_control(
|
||||
if (HCS_PPC(ehci->hcs_params)) {
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
ehci_port_power(ehci, wIndex, true);
|
||||
clear_bit(HCD_FLAG_POWER_ON, &hcd->flags);
|
||||
spin_lock_irqsave(&ehci->lock, flags);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -119,6 +119,7 @@ struct usb_hcd {
|
||||
#define HCD_FLAG_DEAD 6 /* controller has died? */
|
||||
#define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */
|
||||
#define HCD_FLAG_DEV_AUTHORIZED 8 /* authorize devices? */
|
||||
#define HCD_FLAG_POWER_ON 9 /* power on */
|
||||
|
||||
/* The flags can be tested using these macros; they are likely to
|
||||
* be slightly faster than test_bit().
|
||||
@ -146,6 +147,8 @@ struct usb_hcd {
|
||||
#define HCD_DEV_AUTHORIZED(hcd) \
|
||||
((hcd)->flags & (1U << HCD_FLAG_DEV_AUTHORIZED))
|
||||
|
||||
#define HCD_POWER_ON(hcd) ((hcd)->flags & (1U << HCD_FLAG_POWER_ON))
|
||||
|
||||
/* Flags that get set only during HCD registration or removal. */
|
||||
unsigned rh_registered:1;/* is root hub registered? */
|
||||
unsigned rh_pollable:1; /* may we poll the root hub? */
|
||||
|
||||
Reference in New Issue
Block a user