]> git.hungrycats.org Git - linux/commitdiff
xhci: Blacklist using streams on the Etron EJ168 controller
authorHans de Goede <hdegoede@redhat.com>
Fri, 25 Jul 2014 20:01:18 +0000 (22:01 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 5 Sep 2014 23:36:27 +0000 (16:36 -0700)
commit 8f873c1ff4ca034626093d03b254e7cb8bb782dd upstream.

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

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h

index e20520f427535ade657d22fa52850aaa2dd8a475..464049f638c0205753bc10f45a6d1e0f64257f72 100644 (file)
@@ -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 */
index 7436d5f5e67aab1f17e251b7503c0360f17ae861..83693b58aad938d5afda38996f914646124499c1 100644 (file)
@@ -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;
        }
index 9ffecd56600d4d69fe99decf48801e7ba6a1ee57..dace5152e179921cb6ece8533a2272c8ed140ad7 100644 (file)
@@ -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 */