3e413c7d0067e7733162df8e96ff1daba334a5ab
[oweals/openwrt.git] /
1 From 705bc230789927f96d6c9c70dc5475ebaf08aa54 Mon Sep 17 00:00:00 2001
2 From: Jonathan Bell <jonathan@raspberrypi.org>
3 Date: Thu, 11 Jul 2019 17:55:43 +0100
4 Subject: [PATCH] xhci: add quirk for host controllers that don't
5  update endpoint DCS
6
7 Seen on a VLI VL805 PCIe to USB controller. For non-stream endpoints
8 at least, if the xHC halts on a particular TRB due to an error then
9 the DCS field in the Out Endpoint Context maintained by the hardware
10 is not updated with the current cycle state.
11
12 Using the quirk XHCI_EP_CTX_BROKEN_DCS and instead fetch the DCS bit
13 from the TRB that the xHC stopped on.
14
15 See: https://github.com/raspberrypi/linux/issues/3060
16
17 Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
18 ---
19  drivers/usb/host/xhci-pci.c  |  4 +++-
20  drivers/usb/host/xhci-ring.c | 26 +++++++++++++++++++++++++-
21  drivers/usb/host/xhci.h      |  1 +
22  3 files changed, 29 insertions(+), 2 deletions(-)
23
24 --- a/drivers/usb/host/xhci-pci.c
25 +++ b/drivers/usb/host/xhci-pci.c
26 @@ -223,8 +223,10 @@ static void xhci_pci_quirks(struct devic
27                 xhci->quirks |= XHCI_BROKEN_STREAMS;
28  
29         if (pdev->vendor == PCI_VENDOR_ID_VIA &&
30 -                       pdev->device == 0x3483)
31 +                       pdev->device == 0x3483) {
32                 xhci->quirks |= XHCI_LPM_SUPPORT;
33 +               xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
34 +       }
35  
36         if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
37                         pdev->device == 0x1042)
38 --- a/drivers/usb/host/xhci-ring.c
39 +++ b/drivers/usb/host/xhci-ring.c
40 @@ -520,7 +520,10 @@ void xhci_find_new_dequeue_state(struct
41         struct xhci_virt_ep *ep = &dev->eps[ep_index];
42         struct xhci_ring *ep_ring;
43         struct xhci_segment *new_seg;
44 +       struct xhci_segment *halted_seg = NULL;
45         union xhci_trb *new_deq;
46 +       union xhci_trb *halted_trb;
47 +       int index = 0;
48         dma_addr_t addr;
49         u64 hw_dequeue;
50         bool cycle_found = false;
51 @@ -541,7 +544,28 @@ void xhci_find_new_dequeue_state(struct
52         hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
53         new_seg = ep_ring->deq_seg;
54         new_deq = ep_ring->dequeue;
55 -       state->new_cycle_state = hw_dequeue & 0x1;
56 +
57 +       /*
58 +        * Quirk: xHC write-back of the DCS field in the hardware dequeue
59 +        * pointer is wrong - use the cycle state of the TRB pointed to by
60 +        * the dequeue pointer.
61 +        */
62 +       if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS &&
63 +           !(ep->ep_state & EP_HAS_STREAMS))
64 +               halted_seg = trb_in_td(xhci, cur_td->start_seg,
65 +                                      cur_td->first_trb, cur_td->last_trb,
66 +                                      hw_dequeue & ~0xf, false);
67 +       if (halted_seg) {
68 +               index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) /
69 +                        sizeof(*halted_trb);
70 +               halted_trb = &halted_seg->trbs[index];
71 +               state->new_cycle_state = halted_trb->generic.field[3] & 0x1;
72 +               xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n",
73 +                        (u8)(hw_dequeue & 0x1), index,
74 +                        state->new_cycle_state);
75 +       } else {
76 +               state->new_cycle_state = hw_dequeue & 0x1;
77 +       }
78         state->stream_id = stream_id;
79  
80         /*
81 --- a/drivers/usb/host/xhci.h
82 +++ b/drivers/usb/host/xhci.h
83 @@ -1865,6 +1865,7 @@ struct xhci_hcd {
84  #define XHCI_ZERO_64B_REGS     BIT_ULL(32)
85  #define XHCI_RESET_PLL_ON_DISCONNECT   BIT_ULL(34)
86  #define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
87 +#define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(36)
88  
89         unsigned int            num_active_eps;
90         unsigned int            limit_active_eps;