]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
usb: xhci: fix host not responding after suspend and resume
authorNiklas Neronin <niklas.neronin@linux.intel.com>
Tue, 19 Aug 2025 12:58:44 +0000 (15:58 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 19 Aug 2025 14:12:13 +0000 (16:12 +0200)
Partially revert commit e1db856bd288 ("usb: xhci: remove '0' write to
write-1-to-clear register") because the patch cleared the Interrupt Pending
bit during interrupt enabling and disabling. The Interrupt Pending bit
should only be cleared when the driver has handled the interrupt.

Ideally, all interrupts should be handled before disabling the interrupt;
consequently, no interrupt should be pending when enabling the interrupt.
For this reason, keep the debug message informing if an interrupt is still
pending when an interrupt is disabled.

Because the Interrupt Pending bit is write-1-to-clear, writing '0' to it
ensures that the state does not change.

Link: https://lore.kernel.org/linux-usb/20250818231103.672ec7ed@foxbook
Fixes: e1db856bd288 ("usb: xhci: remove '0' write to write-1-to-clear register")
Closes: https://bbs.archlinux.org/viewtopic.php?id=307641
cc: stable@vger.kernel.org # 6.16+
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20250819125844.2042452-3-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci.c

index 0e03691f03bfe56c92242a3a3c2ee3895f2c1391..742c23826e173a7beaee5abd87ac84f200d6522e 100644 (file)
@@ -309,6 +309,7 @@ int xhci_enable_interrupter(struct xhci_interrupter *ir)
                return -EINVAL;
 
        iman = readl(&ir->ir_set->iman);
+       iman &= ~IMAN_IP;
        iman |= IMAN_IE;
        writel(iman, &ir->ir_set->iman);
 
@@ -325,6 +326,7 @@ int xhci_disable_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
                return -EINVAL;
 
        iman = readl(&ir->ir_set->iman);
+       iman &= ~IMAN_IP;
        iman &= ~IMAN_IE;
        writel(iman, &ir->ir_set->iman);