From c25c1e28b778e185da9253c4638db67952a84476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 26 Oct 2023 15:53:14 +0200 Subject: [PATCH] bcm53xx: backport XHCI patch modifying xhci_run_finished() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will help switching to newer 5.15 kernels. This backport required rebasing Northstar's USB host patch. Signed-off-by: Rafał Miłecki --- ...upt-disabled-in-initialization-until.patch | 87 +++++++++++++++++++ ...support-for-performing-fake-doorbell.patch | 36 ++------ 2 files changed, 96 insertions(+), 27 deletions(-) create mode 100644 target/linux/bcm53xx/patches-5.15/081-xhci-Keep-interrupt-disabled-in-initialization-until.patch diff --git a/target/linux/bcm53xx/patches-5.15/081-xhci-Keep-interrupt-disabled-in-initialization-until.patch b/target/linux/bcm53xx/patches-5.15/081-xhci-Keep-interrupt-disabled-in-initialization-until.patch new file mode 100644 index 0000000000..78b3aa85e3 --- /dev/null +++ b/target/linux/bcm53xx/patches-5.15/081-xhci-Keep-interrupt-disabled-in-initialization-until.patch @@ -0,0 +1,87 @@ +From a808925075fb750804a60ff0710614466c396db4 Mon Sep 17 00:00:00 2001 +From: Hongyu Xie +Date: Thu, 23 Jun 2022 14:19:42 +0300 +Subject: [PATCH] xhci: Keep interrupt disabled in initialization until host is + running. + +irq is disabled in xhci_quiesce(called by xhci_halt, with bit:2 cleared +in USBCMD register), but xhci_run(called by usb_add_hcd) re-enable it. +It's possible that you will receive thousands of interrupt requests +after initialization for 2.0 roothub. And you will get a lot of +warning like, "xHCI dying, ignoring interrupt. Shouldn't IRQs be +disabled?". This amount of interrupt requests will cause the entire +system to freeze. +This problem was first found on a device with ASM2142 host controller +on it. + +[tidy up old code while moving it, reword header -Mathias] + +Cc: stable@kernel.org +Signed-off-by: Hongyu Xie +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220623111945.1557702-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci.c | 35 ++++++++++++++++++++++------------- + 1 file changed, 22 insertions(+), 13 deletions(-) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -611,8 +611,27 @@ static int xhci_init(struct usb_hcd *hcd + + static int xhci_run_finished(struct xhci_hcd *xhci) + { ++ unsigned long flags; ++ u32 temp; ++ ++ /* ++ * Enable interrupts before starting the host (xhci 4.2 and 5.5.2). ++ * Protect the short window before host is running with a lock ++ */ ++ spin_lock_irqsave(&xhci->lock, flags); ++ ++ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Enable interrupts"); ++ temp = readl(&xhci->op_regs->command); ++ temp |= (CMD_EIE); ++ writel(temp, &xhci->op_regs->command); ++ ++ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Enable primary interrupter"); ++ temp = readl(&xhci->ir_set->irq_pending); ++ writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending); ++ + if (xhci_start(xhci)) { + xhci_halt(xhci); ++ spin_unlock_irqrestore(&xhci->lock, flags); + return -ENODEV; + } + xhci->shared_hcd->state = HC_STATE_RUNNING; +@@ -623,6 +642,9 @@ static int xhci_run_finished(struct xhci + + xhci_dbg_trace(xhci, trace_xhci_dbg_init, + "Finished xhci_run for USB3 roothub"); ++ ++ spin_unlock_irqrestore(&xhci->lock, flags); ++ + return 0; + } + +@@ -671,19 +693,6 @@ int xhci_run(struct usb_hcd *hcd) + temp |= (xhci->imod_interval / 250) & ER_IRQ_INTERVAL_MASK; + writel(temp, &xhci->ir_set->irq_control); + +- /* Set the HCD state before we enable the irqs */ +- temp = readl(&xhci->op_regs->command); +- temp |= (CMD_EIE); +- xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "// Enable interrupts, cmd = 0x%x.", temp); +- writel(temp, &xhci->op_regs->command); +- +- temp = readl(&xhci->ir_set->irq_pending); +- xhci_dbg_trace(xhci, trace_xhci_dbg_init, +- "// Enabling event ring interrupter %p by writing 0x%x to irq_pending", +- xhci->ir_set, (unsigned int) ER_IRQ_ENABLE(temp)); +- writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending); +- + if (xhci->quirks & XHCI_NEC_HOST) { + struct xhci_command *command; + diff --git a/target/linux/bcm53xx/patches-5.15/180-usb-xhci-add-support-for-performing-fake-doorbell.patch b/target/linux/bcm53xx/patches-5.15/180-usb-xhci-add-support-for-performing-fake-doorbell.patch index 17013c75ba..49277ab251 100644 --- a/target/linux/bcm53xx/patches-5.15/180-usb-xhci-add-support-for-performing-fake-doorbell.patch +++ b/target/linux/bcm53xx/patches-5.15/180-usb-xhci-add-support-for-performing-fake-doorbell.patch @@ -90,41 +90,23 @@ it on BCM4708 family. /* * Reset a halted HC. * -@@ -611,10 +654,20 @@ static int xhci_init(struct usb_hcd *hcd - - static int xhci_run_finished(struct xhci_hcd *xhci) - { -- if (xhci_start(xhci)) { -- xhci_halt(xhci); -- return -ENODEV; -+ int err; -+ -+ err = xhci_start(xhci); -+ if (err) { -+ err = -ENODEV; -+ goto err_halt; +@@ -634,6 +677,16 @@ static int xhci_run_finished(struct xhci + spin_unlock_irqrestore(&xhci->lock, flags); + return -ENODEV; } + + if (xhci->quirks & XHCI_FAKE_DOORBELL) { -+ err = xhci_fake_doorbell(xhci, 1); -+ if (err) -+ goto err_halt; ++ int err = xhci_fake_doorbell(xhci, 1); ++ if (err) { ++ xhci_halt(xhci); ++ spin_unlock_irqrestore(&xhci->lock, flags); ++ return err; ++ } + } + xhci->shared_hcd->state = HC_STATE_RUNNING; xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; -@@ -624,6 +677,10 @@ static int xhci_run_finished(struct xhci - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Finished xhci_run for USB3 roothub"); - return 0; -+ -+err_halt: -+ xhci_halt(xhci); -+ return err; - } - - /* --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1908,6 +1908,7 @@ struct xhci_hcd {