From cf4ae44b10e7cd6d5490fb9bc18fccb7306140d8 Mon Sep 17 00:00:00 2001 From: Longfang Liu Date: Fri, 16 Jun 2023 11:41:31 +0800 Subject: [PATCH] xhci:fix USB xhci controller issue driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7DZ8S CVE: NA ---------------------------------------------------------------------- When the current HiSilicon USB xhci controller formats the faulty U disk, it will trigger a controller exception error. This will cause errors in the control logic of the xhci controller and driver software. In the end, all USB devices on the xhci controller cannot be used. By introducing a noop command operation, restore the logic of the xhci controller and driver software, and restore all USB devices on the xhci controller to normal. Signed-off-by: Longfang Liu (cherry picked from commit 1a86940388049d27b6cb387c041c7d18e25af830) --- drivers/usb/host/xhci-pci.c | 4 ++++ drivers/usb/host/xhci-ring.c | 6 +++++- drivers/usb/host/xhci.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 9f6600e6f22f..5115e994c663 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -376,6 +376,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (xhci->quirks & XHCI_RESET_ON_RESUME) xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "QUIRK: Resetting on resume"); + + if (pdev->vendor == PCI_VENDOR_ID_HUAWEI && + (pdev->device == 0xa23c || pdev->device == 0xa23d)) + xhci->quirks |= XHCI_USB3_NOOP; } #ifdef CONFIG_ACPI diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fa3a7ac15f82..1aa4a73d650f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1492,7 +1492,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, * Check whether the completion event is for our internal kept * command. */ - if (!cmd_dequeue_dma || cmd_dma != (u64)cmd_dequeue_dma) { + if (!cmd_dequeue_dma || ((cmd_dma != (u64)cmd_dequeue_dma) && + !((xhci->quirks & XHCI_USB3_NOOP) && (cmd_comp_code == + COMP_COMMAND_RING_STOPPED)))) { xhci_warn(xhci, "ERROR mismatched command completion event\n"); return; @@ -1525,6 +1527,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, if (cmd_comp_code == COMP_COMMAND_ABORTED) { xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; if (cmd->status == COMP_COMMAND_ABORTED) { + if (xhci->quirks & XHCI_USB3_NOOP) + trb_to_noop(cmd->command_trb, TRB_CMD_NOOP); if (xhci->current_cmd == cmd) xhci->current_cmd = NULL; goto event_handled; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 5f68e880e0ca..18671a416c02 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1835,6 +1835,7 @@ struct xhci_hcd { #define XHCI_STATE_HALTED (1 << 1) #define XHCI_STATE_REMOVING (1 << 2) unsigned long long quirks; +#define XHCI_USB3_NOOP BIT_ULL(63) #define XHCI_LINK_TRB_QUIRK BIT_ULL(0) #define XHCI_RESET_EP_QUIRK BIT_ULL(1) #define XHCI_NEC_HOST BIT_ULL(2) -- Gitee