openwrt-cghmn-mt300n/target/linux/bcm27xx/patches-6.6/950-0485-usb-xhci-add-XHCI_VLI_HUB_TT_QUIRK.patch
John Audia 9af0e94fa6 kernel: bump 6.6 to 6.6.64
Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.6.64

Manually rebased:
	generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch
	bcm27xx/patches-6.6/950-0585-drm-vc4-Introduce-generation-number-enum.patch
	bcm27xx/patches-6.6/950-0610-drm-vc4-hvs-Support-BCM2712-HVS.patch
	bcm27xx/patches-6.6/950-0829-vc4-hvs-Add-support-for-D0-register-changes.patch

Removed upstreamed:
	bcm27xx/patches-6.6/950-0597-drm-vc4-hdmi-Avoid-hang-with-debug-registers-when-su.patch[1]
	bcm27xx/patches-6.6/950-0599-drm-vc4-Fix-dlist-debug-not-resetting-the-next-entry.patch[2]
	bcm27xx/patches-6.6/950-0600-drm-vc4-Remove-incorrect-limit-from-hvs_dlist-debugf.patch[3]
	bcm27xx/patches-6.6/950-0708-drm-vc4-Correct-logic-on-stopping-an-HVS-channel.patch[4]
	ramips/patches-6.6/002-01-v6.13-clk-ralink-mtmips-fix-clock-plan-for-Ralink-SoC-RT38.patch[5]
	ramips/patches-6.6/002-02-v6.13-clk-ralink-mtmips-fix-clocks-probe-order-in-oldest-r.patch[6]

All other patches automatically rebased.

1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.6.64&id=223ee2567a55e4f80315c768d2969e6a3b9fb23d
2. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.6.64&id=8182b5ca19c6f173b6498d1c6d3e4b034b76bbde
3. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.6.64&id=52c1716f65a558174e381360bd88f18dae4be85c
4. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.6.64&id=9728b508b01a5eeeac79ceb676364c674dd951ac
5. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.6.64&id=f85a1d06afbcc57ac44176db8f9d7a934979952c
6. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.6.64&id=fbb13732c6ffa9d58cedafabcd5ce8fd7ef8ae5a

Build system: x86/64
Build-tested: x86/64/AMD Cezanne, flogic/xiaomi_redmi-router-ax6000-ubootmod, ramips/tplink_archer-a6-v3
Run-tested: x86/64/AMD Cezanne, flogic/xiaomi_redmi-router-ax6000-ubootmod, ramips/tplink_archer-a6-v3

Co-authored-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
Signed-off-by: John Audia <therealgraysky@proton.me>
Link: https://github.com/openwrt/openwrt/pull/17217
Signed-off-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
(cherry picked from commit 5158e28769cb5e5c6a59bd9a176f55cf2d568742)
2024-12-15 01:43:39 +01:00

155 lines
5.1 KiB
Diff

From 9d4246df36c1766b2761fd68a103b7ef329d8d83 Mon Sep 17 00:00:00 2001
From: Jonathan Bell <jonathan@raspberrypi.com>
Date: Thu, 1 Dec 2022 16:59:44 +0000
Subject: [PATCH 0485/1085] 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>
xhci: constrain XHCI_VLI_HUB_TT_QUIRK to old firmware versions
VLI have a firmware update for the VL805 which resolves the incorrect
frame time calculation in the hub's TT. Limit applying the quirk to
known-bad firmwares.
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
---
drivers/usb/host/xhci-pci.c | 14 +++++++++++
drivers/usb/host/xhci-ring.c | 46 ++++++++++++++++++++++++++++++++++++
drivers/usb/host/xhci.h | 1 +
3 files changed, 61 insertions(+)
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -27,6 +27,8 @@
#define SPARSE_DISABLE_BIT 17
#define SPARSE_CNTL_ENABLE 0xC12C
+#define VL805_FW_VER_0138C0 0x0138C0
+
/* Device for a quirk */
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
@@ -295,6 +297,16 @@ static int xhci_pci_reinit(struct xhci_h
return 0;
}
+static u32 xhci_vl805_get_fw_version(struct pci_dev *dev)
+{
+ int ret;
+ u32 ver;
+
+ ret = pci_read_config_dword(dev, 0x50, &ver);
+ /* Default to a fw version of 0 instead of ~0 */
+ return ret ? 0 : ver;
+}
+
static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -496,6 +508,8 @@ static void xhci_pci_quirks(struct devic
xhci->quirks |= XHCI_AVOID_DQ_ON_LINK;
xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
xhci->quirks |= XHCI_VLI_SS_BULK_OUT_BUG;
+ if (xhci_vl805_get_fw_version(pdev) < VL805_FW_VER_0138C0)
+ 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
@@ -3679,6 +3679,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)
@@ -3835,6 +3877,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;
@@ -3970,6 +4014,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
@@ -1665,6 +1665,7 @@ struct xhci_hcd {
/* Downstream VLI fixes */
#define XHCI_AVOID_DQ_ON_LINK BIT_ULL(56)
#define XHCI_VLI_SS_BULK_OUT_BUG BIT_ULL(57)
+#define XHCI_VLI_HUB_TT_QUIRK BIT_ULL(58)
unsigned int num_active_eps;
unsigned int limit_active_eps;