From: yinbo.zhu <yinbo.zhu@xxxxxxx> This issue is observed in USB 2.0 mode when the USB 3.0 host controller is connected to a FS/LS device via a hub. The host controller issues start-split (SSPLIT) and (CSPLIT) tokens to accomplish a split-transaction. A split-transaction consists of a SSPLIT token, token/data consists of a SSPLIT token, token/data packets, CSPLIT token and token/data/handshake packets. A SSPLIT token is issued by the host controller to the hub followed by token/data/ handshake packets. The hub then relays the token/data/ handshake packets to the FS /LS device. Sometime later, the host controller issues a CSPLIT token followed by the same token/data/handshake packets to the hub to complete the split-transaction. As an example scenario, when the xHCI driver issues an Address device command with BSR=0, the host controller sends SETUP(SET_ADDRESS) tokens on the USB as part of splittransactions. If the host controller receives a NYET response from the hub for the CSPLIT SETUP, it means that the split-transaction has not yet been completed or the hub is not able to handle the split transaction. In such a case, the host controller keeps retrying the splittransactions until such time an ACK response is received from the hub for the CSPLIT SETUP token . If the split-transactions do not complete in a time bound manner, the xHCI driver may issue a Stop Endpoint Command. The host controller does not service the Stop Endpoint Command and eventually the xHCI driver times out waiting for the Stop Endpoint Command to complete. Impact: Stop Endpoint Command does not complete. Workaround: Instead of issuing a Stop Endpoint Command, issue a Disable Slot Command with the corresponding slot ID. Alternately, you can issue an Address Device Command with BSR=1. Configs Affected: LS1012A-R1.0, LS1012A-R2.0, LS1021-20-22A-R1.0, LS1021-20-22A-R2.0, LS1043-23A-R1.0, LS1043-23A-R1.1, LS1046-26A-R1.0, LS1088-48A-R1.0, LS2080-40A-R1.0, LS2081A-R1.1, LS2085-45A-R1.0, LS2088-48A-R1.0, LS2088-48A-R1.1, LX2160-2120-2080A-R1.0. Signed-off-by: yinbo zhu <yinbo.zhu@xxxxxxx> --- Change in v4: Remove the point in "yinbo.zhu" drivers/usb/dwc3/core.c | 2 ++ drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/host.c | 3 +++ drivers/usb/host/xhci-plat.c | 3 +++ drivers/usb/host/xhci.c | 12 ++++++++++++ drivers/usb/host/xhci.h | 1 + 6 files changed, 23 insertions(+), 0 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 863f2c0..90b097c 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1059,6 +1059,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) "snps,quirk_reverse_in_out"); dwc->quirk_stop_transfer_in_block = device_property_read_bool(dev, "snps,quirk_stop_transfer_in_block"); + dwc->quirk_stop_ep_in_u1 = device_property_read_bool(dev, + "snps,quirk_stop_ep_in_u1"); device_property_read_u8(dev, "snps,tx_de_emphasis", &tx_de_emphasis); device_property_read_string(dev, "snps,hsphy_interface", diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 6276678..b55a443 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -860,6 +860,7 @@ struct dwc3_scratchpad_array { * @quirk_reverse_in_out: prevent tx fifo reverse the data direction * @quirk_stop_transfer_in_block: prevent block transmission from being * interrupted + * @quirk_stop_ep_in_u1: replace stop commad with disable slot command * @imod_interval: set the interrupt moderation interval in 250ns * increments or 0 to disable. */ @@ -1014,6 +1015,7 @@ struct dwc3 { unsigned tx_de_emphasis:2; unsigned quirk_reverse_in_out:1; unsigned quirk_stop_transfer_in_block:1; + unsigned quirk_stop_ep_in_u1:1; u16 imod_interval; }; diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index 78cb7bb..0a34274 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -96,6 +96,9 @@ int dwc3_host_init(struct dwc3 *dwc) if (dwc->quirk_stop_transfer_in_block) props[prop_idx++].name = "quirk-stop-transfer-in-block"; + if (dwc->quirk_stop_ep_in_u1) + props[prop_idx++].name = "quirk-stop-ep-in-u1"; + if (dwc->usb3_lpm_capable) props[prop_idx++].name = "usb3-lpm-capable"; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 35e0fc8..49d6cb4 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -273,6 +273,9 @@ static int xhci_plat_probe(struct platform_device *pdev) "quirk-stop-transfer-in-block")) xhci->quirks |= XHCI_STOP_TRANSFER_IN_BLOCK; + if (device_property_read_bool(&pdev->dev, "quirk-stop-ep-in-u1")) + xhci->quirks |= XHCI_STOP_EP_IN_U1; + if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped")) xhci->quirks |= XHCI_BROKEN_PORT_PED; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5141856..20c9af4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1521,6 +1521,18 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) xhci_ring_cmd_db(xhci); } + /* + *erratum A-009668: Stop Endpoint Command does not complete. + *Workaround: Instead of issuing a Stop Endpoint Command, + *issue a Disable Slot Command with the corresponding slot ID. + *Alternately, you can issue an Address Device Command with + *BSR=1 + */ + if ((urb->dev->speed <= USB_SPEED_HIGH) && + (xhci->quirks & XHCI_STOP_EP_IN_U1)) { + xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT, + urb->dev->slot_id); + } } done: spin_unlock_irqrestore(&xhci->lock, flags); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index db10ee4..22ba752 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1821,6 +1821,7 @@ struct xhci_hcd { #define XHCI_MISSING_CAS (1 << 24) #define XHCI_REVERSE_IN_OUT BIT(32) #define XHCI_STOP_TRANSFER_IN_BLOCK BIT(33) +#define XHCI_STOP_EP_IN_U1 BIT(34) /* For controller with a broken Port Disable implementation */ #define XHCI_BROKEN_PORT_PED (1 << 25) #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) -- 1.7.1 -- 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