Loading drivers/usb/host/xhci-ring.c +4 −4 Original line number Diff line number Diff line Loading @@ -351,13 +351,13 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) &xhci->op_regs->cmd_ring); /* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the * completion of the Command Abort operation. If CRR is not negated in 5 * seconds then driver handles it as if host died (-ENODEV). * completion of the Command Abort operation. If CRR is not negated in a * timely manner then driver handles it as if host died (-ENODEV). * In the future we should distinguish between -ENODEV and -ETIMEDOUT * and try to recover a -ETIMEDOUT with a host controller reset. */ ret = xhci_handshake(&xhci->op_regs->cmd_ring, CMD_RING_RUNNING, 0, 5 * 1000 * 1000); ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring, CMD_RING_RUNNING, 0, 1000 * 1000); if (ret < 0) { xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret); xhci_halt(xhci); Loading drivers/usb/host/xhci.c +22 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,27 @@ int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec) return -ETIMEDOUT; } int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; do { result = readl_relaxed(ptr); if (result == ~(u32)0) /* card removed */ return -ENODEV; /* host removed. Bail out */ if (xhci->xhc_state & XHCI_STATE_REMOVING) return -ENODEV; result &= mask; if (result == done) return 0; udelay(1); usec--; } while (usec > 0); return -ETIMEDOUT; } /* * Disable interrupts and begin the xHCI halting process. */ Loading Loading @@ -206,7 +227,7 @@ int xhci_reset(struct xhci_hcd *xhci) if (xhci->quirks & XHCI_INTEL_HOST) udelay(1000); ret = xhci_handshake(&xhci->op_regs->command, ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command, CMD_RESET, 0, 10 * 1000 * 1000); if (ret) return ret; Loading drivers/usb/host/xhci.h +2 −0 Original line number Diff line number Diff line Loading @@ -2040,6 +2040,8 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num); /* xHCI host controller glue */ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec); int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec); void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); int xhci_start(struct xhci_hcd *xhci); Loading Loading
drivers/usb/host/xhci-ring.c +4 −4 Original line number Diff line number Diff line Loading @@ -351,13 +351,13 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) &xhci->op_regs->cmd_ring); /* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the * completion of the Command Abort operation. If CRR is not negated in 5 * seconds then driver handles it as if host died (-ENODEV). * completion of the Command Abort operation. If CRR is not negated in a * timely manner then driver handles it as if host died (-ENODEV). * In the future we should distinguish between -ENODEV and -ETIMEDOUT * and try to recover a -ETIMEDOUT with a host controller reset. */ ret = xhci_handshake(&xhci->op_regs->cmd_ring, CMD_RING_RUNNING, 0, 5 * 1000 * 1000); ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring, CMD_RING_RUNNING, 0, 1000 * 1000); if (ret < 0) { xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret); xhci_halt(xhci); Loading
drivers/usb/host/xhci.c +22 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,27 @@ int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec) return -ETIMEDOUT; } int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; do { result = readl_relaxed(ptr); if (result == ~(u32)0) /* card removed */ return -ENODEV; /* host removed. Bail out */ if (xhci->xhc_state & XHCI_STATE_REMOVING) return -ENODEV; result &= mask; if (result == done) return 0; udelay(1); usec--; } while (usec > 0); return -ETIMEDOUT; } /* * Disable interrupts and begin the xHCI halting process. */ Loading Loading @@ -206,7 +227,7 @@ int xhci_reset(struct xhci_hcd *xhci) if (xhci->quirks & XHCI_INTEL_HOST) udelay(1000); ret = xhci_handshake(&xhci->op_regs->command, ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command, CMD_RESET, 0, 10 * 1000 * 1000); if (ret) return ret; Loading
drivers/usb/host/xhci.h +2 −0 Original line number Diff line number Diff line Loading @@ -2040,6 +2040,8 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned int intr_num); /* xHCI host controller glue */ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec); int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec); void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); int xhci_start(struct xhci_hcd *xhci); Loading