FAILED: patch "[PATCH] xhci: Keep interrupt disabled in initialization until host is" failed to apply to 4.14-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From a808925075fb750804a60ff0710614466c396db4 Mon Sep 17 00:00:00 2001
From: Hongyu Xie <[email protected]>
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]
drivers/usb/host/xhci.c +22 -13
@@ -611,15 +611,37 @@ 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->cmd_ring_state =CMD_RING_STATE_RUNNING ;if (xhci->quirks &XHCI_NEC_HOST )xhci_ring_cmd_db (xhci); +spin_unlock_irqrestore (&xhci->lock, flags); +return 0 ; }
@@ -668,19 +690,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;