From: Longfang Liu liulongfang@huawei.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7ZPUX 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 liulongfang@huawei.com --- drivers/usb/host/xhci-pci.c | 4 ++++ drivers/usb/host/xhci-ring.c | 10 ++++++---- drivers/usb/host/xhci.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 0b32df19071c..67291945de62 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -357,6 +357,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 b69b8c7e7966..935368c6b31d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1583,14 +1583,16 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, cmd_trb = xhci->cmd_ring->dequeue;
trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic); - + cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status)); cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, cmd_trb); /* * 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; @@ -1600,8 +1602,6 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
cancel_delayed_work(&xhci->cmd_timer);
- cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status)); - /* If CMD ring stopped we own the trbs between enqueue and dequeue */ if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) { complete_all(&xhci->cmd_ring_stop_completion); @@ -1623,6 +1623,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 2bddc2f3d517..7e92740221e1 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1840,6 +1840,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)