diff options
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r-- | drivers/usb/host/xhci.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9957bd96d4bc..dfa44d3e8eee 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -175,6 +175,16 @@ int xhci_reset(struct xhci_hcd *xhci) command |= CMD_RESET; writel(command, &xhci->op_regs->command); + /* Existing Intel xHCI controllers require a delay of 1 mS, + * after setting the CMD_RESET bit, and before accessing any + * HC registers. This allows the HC to complete the + * reset operation and be ready for HC register access. + * Without this delay, the subsequent HC register access, + * may result in a system hang very rarely. + */ + if (xhci->quirks & XHCI_INTEL_HOST) + udelay(1000); + ret = xhci_handshake(&xhci->op_regs->command, CMD_RESET, 0, 10 * 1000 * 1000); if (ret) @@ -3973,7 +3983,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) __le32 __iomem *addr; int raw_port; - if (hcd->speed != HCD_USB3) + if (hcd->speed < HCD_USB3) addr = xhci->usb2_ports[port1 - 1]; else addr = xhci->usb3_ports[port1 - 1]; @@ -4124,7 +4134,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, int hird, exit_latency; int ret; - if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support || + if (hcd->speed >= HCD_USB3 || !xhci->hw_lpm_support || !udev->lpm_capable) return -EPERM; @@ -4241,7 +4251,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); int portnum = udev->portnum - 1; - if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support || + if (hcd->speed >= HCD_USB3 || !xhci->sw_lpm_support || !udev->lpm_capable) return 0; @@ -4841,8 +4851,9 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) /* XHCI controllers don't stop the ep queue on short packets :| */ hcd->self.no_stop_on_short = 1; + xhci = hcd_to_xhci(hcd); + if (usb_hcd_is_primary_hcd(hcd)) { - xhci = hcd_to_xhci(hcd); xhci->main_hcd = hcd; /* Mark the first roothub as being USB 2.0. * The xHCI driver will register the USB 3.0 roothub. @@ -4856,6 +4867,10 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) */ hcd->has_tt = 1; } else { + if (xhci->sbrn == 0x31) { + xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n"); + hcd->speed = HCD_USB31; + } /* xHCI private pointer was set in xhci_pci_probe for the second * registered roothub. */ @@ -4875,6 +4890,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) xhci->hcc_params = readl(&xhci->cap_regs->hc_capbase); xhci->hci_version = HC_VERSION(xhci->hcc_params); xhci->hcc_params = readl(&xhci->cap_regs->hcc_params); + if (xhci->hci_version > 0x100) + xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2); xhci_print_registers(xhci); xhci->quirks = quirks; @@ -4906,6 +4923,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) !dma_set_mask(dev, DMA_BIT_MASK(64))) { xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n"); dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); + } else { + /* + * This is to avoid error in cases where a 32-bit USB + * controller is used on a 64-bit capable system. + */ + retval = dma_set_mask(dev, DMA_BIT_MASK(32)); + if (retval) + return retval; + xhci_dbg(xhci, "Enabling 32-bit DMA addresses.\n"); + dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); } xhci_dbg(xhci, "Calling HCD init\n"); @@ -5020,7 +5047,7 @@ static int __init xhci_hcd_init(void) BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8); BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8); BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8); - BUILD_BUG_ON(sizeof(struct xhci_cap_regs) != 7*32/8); + BUILD_BUG_ON(sizeof(struct xhci_cap_regs) != 8*32/8); BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8); /* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */ BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8); |