lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Tue, 19 Dec 2017 17:52:50 +0800
From:   <yinbo.zhu@....com>
To:     Felipe Balbi <balbi@...com>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        Mathias Nyman <mathias.nyman@...el.com>,
        "open list:DESIGNWARE USB3 DRD IP DRIVER" <linux-usb@...r.kernel.org>,
        open list <linux-kernel@...r.kernel.org>
CC:     <xiaobo.xie@....com>, <jerry.huang@....com>, <ran.wang_1@....com>,
        "yinbo . zhu" <yinbo.zhu@....com>
Subject: [PATCH v3 3/3] usb: host: Implement workaround for Erratum A-009668

From: yinbo.zhu <yinbo.zhu@....com>

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@....com>
---
Change in v3:
                Adjust the commit information.
                Replace "(1<<34)" with BIT(34).
                Update the DT properity description.
                Update erratum description in code comment.
 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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ