1135b31d4f6222803db8e079352a830ae2615bc5
[openwrt/staging/stintel.git] /
1 From a956051a926b0a9e0bc587303ce1a2e153707e80 Mon Sep 17 00:00:00 2001
2 From: Dom Cobley <popcornmix@gmail.com>
3 Date: Mon, 31 Jul 2023 13:47:10 +0100
4 Subject: [PATCH 0061/1085] Revert "Revert "xhci: add quirk for host
5 controllers that don't update endpoint DCS""
6
7 This reverts commit 5bef4b3cb95a5b883dfec8b3ffc0d671323d55bb.
8
9 We don't agree with upstream revert so undo it.
10 ---
11 drivers/usb/host/xhci-pci.c | 4 +++-
12 drivers/usb/host/xhci-ring.c | 25 ++++++++++++++++++++++++-
13 2 files changed, 27 insertions(+), 2 deletions(-)
14
15 --- a/drivers/usb/host/xhci-pci.c
16 +++ b/drivers/usb/host/xhci-pci.c
17 @@ -490,8 +490,10 @@ static void xhci_pci_quirks(struct devic
18 pdev->device == 0x3432)
19 xhci->quirks |= XHCI_BROKEN_STREAMS;
20
21 - if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483)
22 + if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) {
23 xhci->quirks |= XHCI_LPM_SUPPORT;
24 + xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
25 + }
26
27 if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
28 pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) {
29 --- a/drivers/usb/host/xhci-ring.c
30 +++ b/drivers/usb/host/xhci-ring.c
31 @@ -633,8 +633,11 @@ static int xhci_move_dequeue_past_td(str
32 struct xhci_ring *ep_ring;
33 struct xhci_command *cmd;
34 struct xhci_segment *new_seg;
35 + struct xhci_segment *halted_seg = NULL;
36 union xhci_trb *new_deq;
37 int new_cycle;
38 + union xhci_trb *halted_trb;
39 + int index = 0;
40 dma_addr_t addr;
41 u64 hw_dequeue;
42 bool cycle_found = false;
43 @@ -672,7 +675,27 @@ static int xhci_move_dequeue_past_td(str
44 hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
45 new_seg = ep_ring->deq_seg;
46 new_deq = ep_ring->dequeue;
47 - new_cycle = hw_dequeue & 0x1;
48 +
49 + /*
50 + * Quirk: xHC write-back of the DCS field in the hardware dequeue
51 + * pointer is wrong - use the cycle state of the TRB pointed to by
52 + * the dequeue pointer.
53 + */
54 + if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS &&
55 + !(ep->ep_state & EP_HAS_STREAMS))
56 + halted_seg = trb_in_td(xhci, td->start_seg,
57 + td->first_trb, td->last_trb,
58 + hw_dequeue & ~0xf, false);
59 + if (halted_seg) {
60 + index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) /
61 + sizeof(*halted_trb);
62 + halted_trb = &halted_seg->trbs[index];
63 + new_cycle = halted_trb->generic.field[3] & 0x1;
64 + xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n",
65 + (u8)(hw_dequeue & 0x1), index, new_cycle);
66 + } else {
67 + new_cycle = hw_dequeue & 0x1;
68 + }
69
70 /*
71 * We want to find the pointer, segment and cycle state of the new trb