]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xhci: Prevent queuing new commands if xhci is inaccessible
authorMathias Nyman <mathias.nyman@linux.intel.com>
Wed, 3 Jun 2026 09:11:29 +0000 (12:11 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Jun 2026 17:23:29 +0000 (19:23 +0200)
Refuse to queue a new command on the command ring if xHC is marked
inaccessible with the HCD_FLAG_HW_ACCESSIBLE.

HCD_FLAG_HW_ACCESSIBLE is set and cleared in suspend and resume.

Also print a warning if xhci is being suspended with commands
still pending on the command ring.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://patch.msgid.link/20260603091132.1110849-13-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c

index 608b6f3ec9f6305eb50667275460f7e01cf6bbd8..83209db2996259012ae28810f4cf1e93c3bc7f25 100644 (file)
@@ -4332,6 +4332,7 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
                         u32 field3, u32 field4, bool command_must_succeed)
 {
        int reserved_trbs = xhci->cmd_ring_reserved_trbs;
+       struct usb_hcd *hcd = xhci_to_hcd(xhci);
        int ret;
 
        if ((xhci->xhc_state & XHCI_STATE_DYING) ||
@@ -4341,6 +4342,11 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
                return -ESHUTDOWN;
        }
 
+       if (!HCD_HW_ACCESSIBLE(hcd)) {
+               xhci_warn(xhci, "Can't queue command, xHC not accessible\n");
+               return -ESHUTDOWN;
+       }
+
        if (!command_must_succeed)
                reserved_trbs++;
 
index 0bf0446b4c8768a99ffb6d3bbb2ed69f057b64ac..0646fedf20422aeeac516fb5964bd5b7c6f5a75d 100644 (file)
@@ -992,6 +992,10 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
        /* step 1: stop endpoint */
        /* skipped assuming that port suspend has done */
 
+       /* Check if command ring is empty */
+       if (!list_empty(&xhci->cmd_list))
+               xhci_warn(xhci, "Suspending and stopping xHC with pending command!\n");
+
        /* step 2: clear Run/Stop bit */
        command = readl(&xhci->op_regs->command);
        command &= ~CMD_RUN;