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