c6806e8
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1121288
c6806e8
Upstream-status: Send upstream for 3.16/3.17 with Cc: stable
c6806e8
c6806e8
From 508b353921aa266c48f70e1cd9332d3e2ef67171 Mon Sep 17 00:00:00 2001
c6806e8
From: Hans de Goede <hdegoede@redhat.com>
c6806e8
Date: Fri, 25 Jul 2014 12:28:02 +0200
c6806e8
Subject: [PATCH v2] xhci: Blacklist using streams on the Etron EJ168
c6806e8
 controller
c6806e8
c6806e8
Streams on the EJ168 do not work as they should. I've spend 2 days trying
c6806e8
to get them to work, but without success.
c6806e8
c6806e8
The first problem is that when ever you ring the stream-ring doorbell, the
c6806e8
controller starts executing trbs at the beginning of the first ring segment,
c6806e8
event if it ended somewhere else previously. This can be worked around by
c6806e8
allowing enqueing only one td (not a problem with how streams are typically
c6806e8
used) and then resetting our copies of the enqueueing en dequeueing pointers
c6806e8
on a td completion to match what the controller seems to be doing.
c6806e8
c6806e8
This way things seem to start working with uas and instead of being able
c6806e8
to complete only the very first scsi command, the scsi core can probe the disk.
c6806e8
c6806e8
But then things break later on when td-s get enqueued with more then one
c6806e8
trb. The controller does seem to increase its dequeue pointer while executing
c6806e8
a stream-ring (data transfer events I inserted for debugging do trigger).
c6806e8
However execution seems to stop at the final normal trb of a multi trb td,
c6806e8
even if there is a data transfer event inserted after the final trb.
c6806e8
c6806e8
The first problem alone is a serious deviation from the spec, and esp.
c6806e8
dealing with cancellation would have been very tricky if not outright
c6806e8
impossible, but the second problem simply is a deal breaker altogether,
c6806e8
so this patch simply disables streams.
c6806e8
c6806e8
Note this will cause the usb-storage + uas driver pair to automatically switch
c6806e8
to using usb-storage instead of uas on these devices, essentially reverting
c6806e8
to the 3.14 and earlier behavior when uas was marked CONFIG_BROKEN.
c6806e8
c6806e8
https://bugzilla.redhat.com/show_bug.cgi?id=1121288
c6806e8
https://bugzilla.kernel.org/show_bug.cgi?id=80101
c6806e8
c6806e8
Cc: stable@vger.kernel.org # 3.15
c6806e8
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
c6806e8
---
c6806e8
 drivers/usb/host/xhci-pci.c | 4 +++-
c6806e8
 drivers/usb/host/xhci.c     | 3 ++-
c6806e8
 drivers/usb/host/xhci.h     | 2 ++
c6806e8
 3 files changed, 7 insertions(+), 2 deletions(-)
c6806e8
c6806e8
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
c6806e8
index e20520f..464049f 100644
c6806e8
--- a/drivers/usb/host/xhci-pci.c
c6806e8
+++ b/drivers/usb/host/xhci-pci.c
c6806e8
@@ -143,6 +143,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
c6806e8
 			pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
c6806e8
 		xhci->quirks |= XHCI_RESET_ON_RESUME;
c6806e8
 		xhci->quirks |= XHCI_TRUST_TX_LENGTH;
c6806e8
+		xhci->quirks |= XHCI_BROKEN_STREAMS;
c6806e8
 	}
c6806e8
 	if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
c6806e8
 			pdev->device == 0x0015)
c6806e8
@@ -230,7 +231,8 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
c6806e8
 		goto put_usb3_hcd;
c6806e8
 	/* Roothub already marked as USB 3.0 speed */
c6806e8
 
c6806e8
-	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
c6806e8
+	if (!(xhci->quirks & XHCI_BROKEN_STREAMS) &&
c6806e8
+			HCC_MAX_PSA(xhci->hcc_params) >= 4)
c6806e8
 		xhci->shared_hcd->can_do_streams = 1;
c6806e8
 
c6806e8
 	/* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
c6806e8
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
c6806e8
index 7d02e1b..758bc31 100644
c6806e8
--- a/drivers/usb/host/xhci.c
c6806e8
+++ b/drivers/usb/host/xhci.c
c6806e8
@@ -3163,7 +3163,8 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
c6806e8
 			num_streams);
c6806e8
 
c6806e8
 	/* MaxPSASize value 0 (2 streams) means streams are not supported */
c6806e8
-	if (HCC_MAX_PSA(xhci->hcc_params) < 4) {
c6806e8
+	if ((xhci->quirks & XHCI_BROKEN_STREAMS) ||
c6806e8
+			HCC_MAX_PSA(xhci->hcc_params) < 4) {
c6806e8
 		xhci_dbg(xhci, "xHCI controller does not support streams.\n");
c6806e8
 		return -ENOSYS;
c6806e8
 	}
c6806e8
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
c6806e8
index 1411069..88b2958 100644
c6806e8
--- a/drivers/usb/host/xhci.h
c6806e8
+++ b/drivers/usb/host/xhci.h
c6806e8
@@ -1558,6 +1558,8 @@ struct xhci_hcd {
c6806e8
 #define XHCI_PLAT		(1 << 16)
c6806e8
 #define XHCI_SLOW_SUSPEND	(1 << 17)
c6806e8
 #define XHCI_SPURIOUS_WAKEUP	(1 << 18)
c6806e8
+/* For controllers with a broken beyond repair streams implementation */
c6806e8
+#define XHCI_BROKEN_STREAMS	(1 << 19)
c6806e8
 	unsigned int		num_active_eps;
c6806e8
 	unsigned int		limit_active_eps;
c6806e8
 	/* There are two roothubs to keep track of bus suspend info for */
c6806e8
-- 
c6806e8
2.0.4
c6806e8