mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00

Removed upstreamed: target/linux/mediatek/patches-6.1/220-v6.3-clk-mediatek-clk-gate-Propagate-struct-device-with-m.patch target/linux/mediatek/patches-6.1/222-v6.3-clk-mediatek-clk-mtk-Propagate-struct-device-for-com.patch target/linux/mediatek/patches-6.1/223-v6.3-clk-mediatek-clk-mux-Propagate-struct-device-for-mtk.patch target/linux/mediatek/patches-6.1/226-v6.3-clk-mediatek-clk-mtk-Extend-mtk_clk_simple_probe.patch
120 lines
4.1 KiB
Diff
120 lines
4.1 KiB
Diff
From 4f3e85c6f129199a432ef4ed3edbb667a5dedcc1 Mon Sep 17 00:00:00 2001
|
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
|
Date: Thu, 1 Dec 2022 16:59:44 +0000
|
|
Subject: [PATCH] usb: xhci: add XHCI_VLI_HUB_TT_QUIRK
|
|
|
|
The integrated USB2.0 hub in the VL805 chipset has a bug where it
|
|
incorrectly determines the remaining available frame time before the
|
|
host next sends a SOF packet with an incremented frame_number.
|
|
|
|
See the USB2.0 specification sections 11.3 and 11.14.2.3.
|
|
|
|
The hub's non-periodic TT handler can transmit the IN/OUT handshake
|
|
token too late, so a following 64-byte DATA0/1 packet causes the ACK
|
|
handshake to collide with the propagated SOF. This causes port babble.
|
|
|
|
Avoid ringing doorbells for vulnerable endpoints during uFrame 7 if the
|
|
TR is Idle to stop one source of babble. An IN transfer for a Running TR
|
|
may happen at any time, so there's not much we can do about that.
|
|
|
|
Ideally a hub firmware update to properly implement frame timeouts is
|
|
needed, and to avoid spinning for up to 125us when submitting TDs to
|
|
Idle rings.
|
|
|
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
|
---
|
|
drivers/usb/host/xhci-pci.c | 1 +
|
|
drivers/usb/host/xhci-ring.c | 46 ++++++++++++++++++++++++++++++++++++
|
|
drivers/usb/host/xhci.h | 1 +
|
|
3 files changed, 48 insertions(+)
|
|
|
|
--- a/drivers/usb/host/xhci-pci.c
|
|
+++ b/drivers/usb/host/xhci-pci.c
|
|
@@ -298,6 +298,7 @@ static void xhci_pci_quirks(struct devic
|
|
xhci->quirks |= XHCI_AVOID_DQ_ON_LINK;
|
|
xhci->quirks |= XHCI_VLI_TRB_CACHE_BUG;
|
|
xhci->quirks |= XHCI_VLI_SS_BULK_OUT_BUG;
|
|
+ xhci->quirks |= XHCI_VLI_HUB_TT_QUIRK;
|
|
}
|
|
|
|
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
|
|
--- a/drivers/usb/host/xhci-ring.c
|
|
+++ b/drivers/usb/host/xhci-ring.c
|
|
@@ -3583,6 +3583,48 @@ static int xhci_align_td(struct xhci_hcd
|
|
return 1;
|
|
}
|
|
|
|
+static void xhci_vl805_hub_tt_quirk(struct xhci_hcd *xhci, struct urb *urb,
|
|
+ struct xhci_ring *ring)
|
|
+{
|
|
+ struct list_head *tmp;
|
|
+ struct usb_device *udev = urb->dev;
|
|
+ unsigned int timeout = 0;
|
|
+ unsigned int single_td = 0;
|
|
+
|
|
+ /*
|
|
+ * Adding a TD to an Idle ring for a FS nonperiodic endpoint
|
|
+ * that is behind the internal hub's TT will run the risk of causing a
|
|
+ * downstream port babble if submitted late in uFrame 7.
|
|
+ * Wait until we've moved on into at least uFrame 0
|
|
+ * (MFINDEX references the next SOF to be transmitted).
|
|
+ *
|
|
+ * Rings for IN endpoints in the Running state also risk causing
|
|
+ * babble if the returned data is large, but there's not much we can do
|
|
+ * about it here.
|
|
+ */
|
|
+ if (udev->route & 0xffff0 || udev->speed != USB_SPEED_FULL)
|
|
+ return;
|
|
+
|
|
+ list_for_each(tmp, &ring->td_list) {
|
|
+ single_td++;
|
|
+ if (single_td == 2) {
|
|
+ single_td = 0;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (single_td) {
|
|
+ while (timeout < 20 &&
|
|
+ (readl(&xhci->run_regs->microframe_index) & 0x7) == 0) {
|
|
+ udelay(10);
|
|
+ timeout++;
|
|
+ }
|
|
+ if (timeout >= 20)
|
|
+ xhci_warn(xhci, "MFINDEX didn't advance - %u.%u dodged\n",
|
|
+ readl(&xhci->run_regs->microframe_index) >> 3,
|
|
+ readl(&xhci->run_regs->microframe_index) & 7);
|
|
+ }
|
|
+}
|
|
+
|
|
/* This is very similar to what ehci-q.c qtd_fill() does */
|
|
int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|
struct urb *urb, int slot_id, unsigned int ep_index)
|
|
@@ -3751,6 +3793,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
|
|
}
|
|
|
|
check_trb_math(urb, enqd_len);
|
|
+ if (xhci->quirks & XHCI_VLI_HUB_TT_QUIRK)
|
|
+ xhci_vl805_hub_tt_quirk(xhci, urb, ring);
|
|
giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
|
|
start_cycle, start_trb);
|
|
return 0;
|
|
@@ -3886,6 +3930,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
|
|
/* Event on completion */
|
|
field | TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state);
|
|
|
|
+ if (xhci->quirks & XHCI_VLI_HUB_TT_QUIRK)
|
|
+ xhci_vl805_hub_tt_quirk(xhci, urb, ep_ring);
|
|
giveback_first_trb(xhci, slot_id, ep_index, 0,
|
|
start_cycle, start_trb);
|
|
return 0;
|
|
--- a/drivers/usb/host/xhci.h
|
|
+++ b/drivers/usb/host/xhci.h
|
|
@@ -1911,6 +1911,7 @@ struct xhci_hcd {
|
|
#define XHCI_AVOID_DQ_ON_LINK BIT_ULL(47)
|
|
#define XHCI_VLI_TRB_CACHE_BUG BIT_ULL(48)
|
|
#define XHCI_VLI_SS_BULK_OUT_BUG BIT_ULL(49)
|
|
+#define XHCI_VLI_HUB_TT_QUIRK BIT_ULL(50)
|
|
|
|
unsigned int num_active_eps;
|
|
unsigned int limit_active_eps;
|