diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/ehci-platform.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-q.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-xilinx-of.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/fhci-hcd.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/fotg210-hcd.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 11 | ||||
-rw-r--r-- | drivers/usb/host/isp1362-hcd.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/max3421-hcd.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ohci-omap.c | 18 | ||||
-rw-r--r-- | drivers/usb/host/ohci-platform.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ohci-ppc-of.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pxa27x.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/oxu210hp-hcd.c | 16 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/sl811-hcd.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 23 | ||||
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/xhci-plat.c | 46 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 144 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 175 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 30 |
24 files changed, 256 insertions, 273 deletions
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 7f4a03e8647a..8c45bc17a580 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -61,11 +61,6 @@ static inline void ehci_write(void __iomem *base, u32 reg, u32 val) __raw_writel(val, base + reg); } -static inline u32 ehci_read(void __iomem *base, u32 reg) -{ - return __raw_readl(base + reg); -} - /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 1115431a255d..f343967443e2 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -518,6 +518,7 @@ static struct platform_driver ehci_platform_driver = { .pm = pm_ptr(&ehci_platform_pm_ops), .of_match_table = vt8500_ehci_ids, .acpi_match_table = ACPI_PTR(ehci_acpi_match), + .probe_type = PROBE_PREFER_ASYNCHRONOUS, } }; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index a2a5c2996350..1163af6fad77 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -645,7 +645,7 @@ qh_urb_transaction ( token |= (1 /* "in" */ << 8); /* else it's already initted to "out" pid (0 << 8) */ - maxpacket = usb_maxpacket(urb->dev, urb->pipe, !is_input); + maxpacket = usb_maxpacket(urb->dev, urb->pipe); /* * buffer gets wrapped in one or more qtds; @@ -1218,7 +1218,7 @@ static int ehci_submit_single_step_set_feature( token |= (1 /* "in" */ << 8); /*This is IN stage*/ - maxpacket = usb_maxpacket(urb->dev, urb->pipe, 0); + maxpacket = usb_maxpacket(urb->dev, urb->pipe); qtd_fill(ehci, qtd, buf, len, token, maxpacket); diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 67a6ee8cb5d8..3d7893747835 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -32,6 +32,8 @@ * There are cases when the host controller fails to enable the port due to, * for example, insufficient power that can be supplied to the device from * the USB bus. In those cases, the messages printed here are not helpful. + * + * Return: Always return 0 */ static int ehci_xilinx_port_handed_over(struct usb_hcd *hcd, int portnum) { @@ -46,11 +48,9 @@ static int ehci_xilinx_port_handed_over(struct usb_hcd *hcd, int portnum) dev_warn(hcd->self.controller, "Maybe your device is not a high speed device?\n"); dev_warn(hcd->self.controller, - "The USB host controller does not support full speed " - "nor low speed devices\n"); + "The USB host controller does not support full speed nor low speed devices\n"); dev_warn(hcd->self.controller, - "You can reconfigure the host controller to have " - "full speed support\n"); + "You can reconfigure the host controller to have full speed support\n"); } return 0; @@ -112,6 +112,8 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { * host controller. Because the Xilinx USB host controller can be configured * as HS only or HS/FS only, it checks the configuration in the device tree * entry, and sets an appropriate value for hcd->has_tt. + * + * Return: zero on success, negative error code otherwise */ static int ehci_hcd_xilinx_of_probe(struct platform_device *op) { @@ -196,6 +198,8 @@ err_irq: * * Remove the hcd structure, and release resources that has been requested * during probe. + * + * Return: Always return 0 */ static int ehci_hcd_xilinx_of_remove(struct platform_device *op) { diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index a8e1048278d0..2ba09c3fbc2f 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -408,8 +408,7 @@ static int fhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, size++; else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 && (urb->transfer_buffer_length - % usb_maxpacket(urb->dev, pipe, - usb_pipeout(pipe))) != 0) + % usb_maxpacket(urb->dev, pipe)) != 0) size++; break; case PIPE_ISOCHRONOUS: diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index c3fd375b4778..f8c111e08a0d 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -2596,7 +2596,7 @@ static struct list_head *qh_urb_transaction(struct fotg210_hcd *fotg210, token |= (1 /* "in" */ << 8); /* else it's already initted to "out" pid (0 << 8) */ - maxpacket = usb_maxpacket(urb->dev, urb->pipe, !is_input); + maxpacket = usb_maxpacket(urb->dev, urb->pipe); /* * buffer gets wrapped in one or more qtds; diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 8835f6bd528e..4f564d71bb0b 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -726,7 +726,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, INIT_LIST_HEAD(&ep->schedule); ep->udev = udev; ep->epnum = epnum; - ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); + ep->maxpacket = usb_maxpacket(udev, urb->pipe); usb_settoggle(udev, epnum, is_out, 0); if (type == PIPE_CONTROL) { @@ -757,8 +757,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, ep->load = usb_calc_bus_time(udev->speed, !is_out, (type == PIPE_ISOCHRONOUS), - usb_maxpacket(udev, pipe, - is_out)) / + usb_maxpacket(udev, pipe)) / 1000; } hep->hcpriv = ep; @@ -1541,10 +1540,12 @@ static int isp116x_remove(struct platform_device *pdev) iounmap(isp116x->data_reg); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - release_mem_region(res->start, 2); + if (res) + release_mem_region(res->start, 2); iounmap(isp116x->addr_reg); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, 2); + if (res) + release_mem_region(res->start, 2); usb_put_hcd(hcd); return 0; diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index d8610ce8f2ec..0e14d1d07709 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -1279,7 +1279,7 @@ static int isp1362_urb_enqueue(struct usb_hcd *hcd, ep->udev = usb_get_dev(udev); ep->hep = hep; ep->epnum = epnum; - ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); + ep->maxpacket = usb_maxpacket(udev, urb->pipe); ep->ptd_offset = -EINVAL; ep->ptd_index = -EINVAL; usb_settoggle(udev, epnum, is_out, 0); @@ -1299,8 +1299,8 @@ static int isp1362_urb_enqueue(struct usb_hcd *hcd, ep->interval = urb->interval; ep->branch = PERIODIC_SIZE; ep->load = usb_calc_bus_time(udev->speed, !is_out, - (type == PIPE_ISOCHRONOUS), - usb_maxpacket(udev, pipe, is_out)) / 1000; + type == PIPE_ISOCHRONOUS, + usb_maxpacket(udev, pipe)) / 1000; break; } hep->hcpriv = ep; diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index 99a5523a79fb..502a3ac5e35b 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -546,7 +546,7 @@ max3421_transfer_out(struct usb_hcd *hcd, struct urb *urb, int fast_retransmit) return MAX3421_HXFR_BULK_OUT(epnum); } - max_packet = usb_maxpacket(urb->dev, urb->pipe, 1); + max_packet = usb_maxpacket(urb->dev, urb->pipe); if (max_packet > MAX3421_FIFO_SIZE) { /* @@ -952,7 +952,7 @@ max3421_transfer_in_done(struct usb_hcd *hcd, struct urb *urb) * USB 2.0 Section 5.3.2 Pipes: packets must be full size * except for last one. */ - max_packet = usb_maxpacket(urb->dev, urb->pipe, 0); + max_packet = usb_maxpacket(urb->dev, urb->pipe); if (max_packet > MAX3421_FIFO_SIZE) { /* * We do not support isochronous transfers at this @@ -998,7 +998,7 @@ max3421_transfer_out_done(struct usb_hcd *hcd, struct urb *urb) * max_packet as an indicator that the end of the * packet has been reached). */ - u32 max_packet = usb_maxpacket(urb->dev, urb->pipe, 1); + u32 max_packet = usb_maxpacket(urb->dev, urb->pipe); if (max3421_hcd->curr_len == max_packet) return 0; diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 666b1c665188..c4c821c2288c 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -181,8 +181,7 @@ static int ohci_urb_enqueue ( size++; else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 && (urb->transfer_buffer_length - % usb_maxpacket (urb->dev, pipe, - usb_pipeout (pipe))) == 0) + % usb_maxpacket(urb->dev, pipe)) == 0) size++; break; case PIPE_ISOCHRONOUS: /* number of packets from URB */ diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 069791d25abb..f5bc9c8bdc9a 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -259,6 +259,10 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev) goto err_put_hcd; } + retval = clk_prepare(priv->usb_host_ck); + if (retval) + goto err_put_host_ck; + if (!cpu_is_omap15xx()) priv->usb_dc_ck = clk_get(&pdev->dev, "usb_dc_ck"); else @@ -266,13 +270,17 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev) if (IS_ERR(priv->usb_dc_ck)) { retval = PTR_ERR(priv->usb_dc_ck); - goto err_put_host_ck; + goto err_unprepare_host_ck; } + retval = clk_prepare(priv->usb_dc_ck); + if (retval) + goto err_put_dc_ck; + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { dev_dbg(&pdev->dev, "request_mem_region failed\n"); retval = -EBUSY; - goto err_put_dc_ck; + goto err_unprepare_dc_ck; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); @@ -297,8 +305,12 @@ err3: iounmap(hcd->regs); err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err_unprepare_dc_ck: + clk_unprepare(priv->usb_dc_ck); err_put_dc_ck: clk_put(priv->usb_dc_ck); +err_unprepare_host_ck: + clk_unprepare(priv->usb_host_ck); err_put_host_ck: clk_put(priv->usb_host_ck); err_put_hcd: @@ -333,7 +345,9 @@ static int ohci_hcd_omap_remove(struct platform_device *pdev) } iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + clk_unprepare(priv->usb_dc_ck); clk_put(priv->usb_dc_ck); + clk_unprepare(priv->usb_host_ck); clk_put(priv->usb_host_ck); usb_put_hcd(hcd); return 0; diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index 4a8456f12a73..47dfbfe9e519 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -334,6 +334,7 @@ static struct platform_driver ohci_platform_driver = { .name = "ohci-platform", .pm = &ohci_platform_pm_ops, .of_match_table = ohci_platform_ids, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, } }; diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 45f7cceb6df3..1960b8dfdba5 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -19,9 +19,6 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> -#include <asm/prom.h> - - static int ohci_ppc_of_start(struct usb_hcd *hcd) { diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 54aa5c77e549..ab4f610a0140 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -36,8 +36,7 @@ #include <linux/usb.h> #include <linux/usb/hcd.h> #include <linux/usb/otg.h> - -#include <mach/hardware.h> +#include <linux/soc/pxa/cpu.h> #include "ohci.h" diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index b741670525e3..3a441310c713 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -1685,7 +1685,7 @@ static struct list_head *qh_urb_transaction(struct oxu_hcd *oxu, token |= (1 /* "in" */ << 8); /* else it's already initted to "out" pid (0 << 8) */ - maxpacket = usb_maxpacket(urb->dev, urb->pipe, !is_input); + maxpacket = usb_maxpacket(urb->dev, urb->pipe); /* * buffer gets wrapped in one or more qtds; @@ -1796,7 +1796,7 @@ static struct ehci_qh *qh_make(struct oxu_hcd *oxu, is_input = usb_pipein(urb->pipe); type = usb_pipetype(urb->pipe); - maxp = usb_maxpacket(urb->dev, urb->pipe, !is_input); + maxp = usb_maxpacket(urb->dev, urb->pipe); /* Compute interrupt scheduling parameters just once, and save. * - allowing for high bandwidth, how many nsec/uframe are used? @@ -3909,8 +3909,10 @@ static int oxu_bus_suspend(struct usb_hcd *hcd) } } + spin_unlock_irq(&oxu->lock); /* turn off now-idle HC */ del_timer_sync(&oxu->watchdog); + spin_lock_irq(&oxu->lock); ehci_halt(oxu); hcd->state = HC_STATE_SUSPENDED; @@ -4223,13 +4225,9 @@ static int oxu_drv_probe(struct platform_device *pdev) /* * Get the platform resources */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(&pdev->dev, - "no IRQ! Check %s setup!\n", dev_name(&pdev->dev)); - return -ENODEV; - } - irq = res->start; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; dev_dbg(&pdev->dev, "IRQ resource %d\n", irq); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 63719cdf6a4e..abb88dd40d4e 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1867,8 +1867,7 @@ static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597, td->pipe = hep->hcpriv; td->urb = urb; td->address = get_urb_to_r8a66597_addr(r8a66597, urb); - td->maxpacket = usb_maxpacket(urb->dev, urb->pipe, - !usb_pipein(urb->pipe)); + td->maxpacket = usb_maxpacket(urb->dev, urb->pipe); if (usb_pipecontrol(urb->pipe)) td->type = USB_PID_SETUP; else if (usb_pipein(urb->pipe)) diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 85623731a516..d206bd95c7bb 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -842,7 +842,7 @@ static int sl811h_urb_enqueue( INIT_LIST_HEAD(&ep->schedule); ep->udev = udev; ep->epnum = epnum; - ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); + ep->maxpacket = usb_maxpacket(udev, urb->pipe); ep->defctrl = SL11H_HCTLMASK_ARM | SL11H_HCTLMASK_ENABLE; usb_settoggle(udev, epnum, is_out, 0); @@ -878,8 +878,8 @@ static int sl811h_urb_enqueue( if (type == PIPE_ISOCHRONOUS) ep->defctrl |= SL11H_HCTLMASK_ISOCH; ep->load = usb_calc_bus_time(udev->speed, !is_out, - (type == PIPE_ISOCHRONOUS), - usb_maxpacket(udev, pipe, is_out)) + type == PIPE_ISOCHRONOUS, + usb_maxpacket(udev, pipe)) / 1000; break; } diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index f65f1ba2b592..c54f2bc23d3f 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -707,6 +707,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, u16 test_mode, u16 wIndex, unsigned long *flags) __must_hold(&xhci->lock) { + struct usb_hcd *usb3_hcd = xhci_get_usb3_hcd(xhci); int i, retval; /* Disable all Device Slots */ @@ -727,7 +728,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, xhci_dbg(xhci, "Disable all port (PP = 0)\n"); /* Power off USB3 ports*/ for (i = 0; i < xhci->usb3_rhub.num_ports; i++) - xhci_set_port_power(xhci, xhci->shared_hcd, i, false, flags); + xhci_set_port_power(xhci, usb3_hcd, i, false, flags); /* Power off USB2 ports*/ for (i = 0; i < xhci->usb2_rhub.num_ports; i++) xhci_set_port_power(xhci, xhci->main_hcd, i, false, flags); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index bbb27ee2c6a3..8c19e151a945 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -782,14 +782,6 @@ void xhci_free_stream_info(struct xhci_hcd *xhci, /***************** Device context manipulation *************************/ -static void xhci_init_endpoint_timer(struct xhci_hcd *xhci, - struct xhci_virt_ep *ep) -{ - timer_setup(&ep->stop_cmd_timer, xhci_stop_endpoint_command_watchdog, - 0); - ep->xhci = xhci; -} - static void xhci_free_tt_info(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, int slot_id) @@ -994,11 +986,11 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id, (unsigned long long)dev->in_ctx->dma); - /* Initialize the cancellation list and watchdog timers for each ep */ + /* Initialize the cancellation and bandwidth list for each ep */ for (i = 0; i < 31; i++) { dev->eps[i].ep_index = i; dev->eps[i].vdev = dev; - xhci_init_endpoint_timer(xhci, &dev->eps[i]); + dev->eps[i].xhci = xhci; INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list); INIT_LIST_HEAD(&dev->eps[i].bw_endpoint_list); } @@ -1072,7 +1064,7 @@ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, struct usb_hcd *hcd; if (udev->speed >= USB_SPEED_SUPER) - hcd = xhci->shared_hcd; + hcd = xhci_get_usb3_hcd(xhci); else hcd = xhci->main_hcd; @@ -2362,10 +2354,11 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) xhci->usb2_rhub.num_ports = USB_MAXCHILDREN; } - /* - * Note we could have all USB 3.0 ports, or all USB 2.0 ports. - * Not sure how the USB core will handle a hub with no ports... - */ + if (!xhci->usb2_rhub.num_ports) + xhci_info(xhci, "USB2 root hub has no ports\n"); + + if (!xhci->usb3_rhub.num_ports) + xhci_info(xhci, "USB3 root hub has no ports\n"); xhci_create_rhub_port_array(xhci, &xhci->usb2_rhub, flags); xhci_create_rhub_port_array(xhci, &xhci->usb3_rhub, flags); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index d7e0e6ebf080..fac9492a8bda 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -59,6 +59,7 @@ #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI 0x464e #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 @@ -129,8 +130,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->revision == 0x0) { xhci->quirks |= XHCI_RESET_EP_QUIRK; xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, - "QUIRK: Fresco Logic xHC needs configure" - " endpoint cmd after reset endpoint"); + "XHCI_RESET_EP_QUIRK for this evaluation HW is deprecated"); } if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && pdev->revision == 0x4) { @@ -268,6 +268,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI)) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 649ffd861b44..044855818cb1 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -180,7 +180,7 @@ static int xhci_plat_probe(struct platform_device *pdev) struct device *sysdev, *tmpdev; struct xhci_hcd *xhci; struct resource *res; - struct usb_hcd *hcd; + struct usb_hcd *hcd, *usb3_hcd; int ret; int irq; struct xhci_plat_priv *priv = NULL; @@ -245,6 +245,8 @@ static int xhci_plat_probe(struct platform_device *pdev) xhci = hcd_to_xhci(hcd); + xhci->allow_single_roothub = 1; + /* * Not all platforms have clks so it is not an error if the * clock do not exist. @@ -283,12 +285,6 @@ static int xhci_plat_probe(struct platform_device *pdev) device_set_wakeup_capable(&pdev->dev, true); xhci->main_hcd = hcd; - xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, - dev_name(&pdev->dev), hcd); - if (!xhci->shared_hcd) { - ret = -ENOMEM; - goto disable_clk; - } /* imod_interval is the interrupt moderation value in nanoseconds. */ xhci->imod_interval = 40000; @@ -313,16 +309,16 @@ static int xhci_plat_probe(struct platform_device *pdev) if (IS_ERR(hcd->usb_phy)) { ret = PTR_ERR(hcd->usb_phy); if (ret == -EPROBE_DEFER) - goto put_usb3_hcd; + goto disable_clk; hcd->usb_phy = NULL; } else { ret = usb_phy_init(hcd->usb_phy); if (ret) - goto put_usb3_hcd; + goto disable_clk; } hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); - xhci->shared_hcd->tpl_support = hcd->tpl_support; + if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) hcd->skip_phy_initialization = 1; @@ -333,12 +329,26 @@ static int xhci_plat_probe(struct platform_device *pdev) if (ret) goto disable_usb_phy; - if (HCC_MAX_PSA(xhci->hcc_params) >= 4) - xhci->shared_hcd->can_do_streams = 1; + if (!xhci_has_one_roothub(xhci)) { + xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, + dev_name(&pdev->dev), hcd); + if (!xhci->shared_hcd) { + ret = -ENOMEM; + goto dealloc_usb2_hcd; + } - ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); - if (ret) - goto dealloc_usb2_hcd; + xhci->shared_hcd->tpl_support = hcd->tpl_support; + } + + usb3_hcd = xhci_get_usb3_hcd(xhci); + if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4) + usb3_hcd->can_do_streams = 1; + + if (xhci->shared_hcd) { + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); + if (ret) + goto put_usb3_hcd; + } device_enable_async_suspend(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); @@ -352,15 +362,15 @@ static int xhci_plat_probe(struct platform_device *pdev) return 0; +put_usb3_hcd: + usb_put_hcd(xhci->shared_hcd); + dealloc_usb2_hcd: usb_remove_hcd(hcd); disable_usb_phy: usb_phy_shutdown(hcd->usb_phy); -put_usb3_hcd: - usb_put_hcd(xhci->shared_hcd); - disable_clk: clk_disable_unprepare(xhci->clk); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f9707997969d..46d0b9ad6f74 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -740,14 +740,6 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, } } -static void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci, - struct xhci_virt_ep *ep) -{ - ep->ep_state &= ~EP_STOP_CMD_PENDING; - /* Can't del_timer_sync in interrupt */ - del_timer(&ep->stop_cmd_timer); -} - /* * Must be called with xhci->lock held in interrupt context, * releases and re-acquires xhci->lock @@ -1122,18 +1114,17 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, reset_type); if (err) break; - xhci_stop_watchdog_timer_in_irq(xhci, ep); + ep->ep_state &= ~EP_STOP_CMD_PENDING; return; case EP_STATE_RUNNING: /* Race, HW handled stop ep cmd before ep was running */ xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n"); command = xhci_alloc_command(xhci, false, GFP_ATOMIC); - if (!command) - xhci_stop_watchdog_timer_in_irq(xhci, ep); - - mod_timer(&ep->stop_cmd_timer, - jiffies + XHCI_STOP_EP_CMD_TIMEOUT * HZ); + if (!command) { + ep->ep_state &= ~EP_STOP_CMD_PENDING; + return; + } xhci_queue_stop_endpoint(xhci, command, slot_id, ep_index, 0); xhci_ring_cmd_db(xhci); @@ -1142,9 +1133,10 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, break; } } + /* will queue a set TR deq if stopped on a cancelled, uncleared TD */ xhci_invalidate_cancelled_tds(ep); - xhci_stop_watchdog_timer_in_irq(xhci, ep); + ep->ep_state &= ~EP_STOP_CMD_PENDING; /* Otherwise ring the doorbell(s) to restart queued transfers */ xhci_giveback_invalidated_tds(ep); @@ -1248,61 +1240,6 @@ void xhci_hc_died(struct xhci_hcd *xhci) usb_hc_died(xhci_to_hcd(xhci)); } -/* Watchdog timer function for when a stop endpoint command fails to complete. - * In this case, we assume the host controller is broken or dying or dead. The - * host may still be completing some other events, so we have to be careful to - * let the event ring handler and the URB dequeueing/enqueueing functions know - * through xhci->state. - * - * The timer may also fire if the host takes a very long time to respond to the - * command, and the stop endpoint command completion handler cannot delete the - * timer before the timer function is called. Another endpoint cancellation may - * sneak in before the timer function can grab the lock, and that may queue - * another stop endpoint command and add the timer back. So we cannot use a - * simple flag to say whether there is a pending stop endpoint command for a - * particular endpoint. - * - * Instead we use a combination of that flag and checking if a new timer is - * pending. - */ -void xhci_stop_endpoint_command_watchdog(struct timer_list *t) -{ - struct xhci_virt_ep *ep = from_timer(ep, t, stop_cmd_timer); - struct xhci_hcd *xhci = ep->xhci; - unsigned long flags; - u32 usbsts; - char str[XHCI_MSG_MAX]; - - spin_lock_irqsave(&xhci->lock, flags); - - /* bail out if cmd completed but raced with stop ep watchdog timer.*/ - if (!(ep->ep_state & EP_STOP_CMD_PENDING) || - timer_pending(&ep->stop_cmd_timer)) { - spin_unlock_irqrestore(&xhci->lock, flags); - xhci_dbg(xhci, "Stop EP timer raced with cmd completion, exit"); - return; - } - usbsts = readl(&xhci->op_regs->status); - - xhci_warn(xhci, "xHCI host not responding to stop endpoint command.\n"); - xhci_warn(xhci, "USBSTS:%s\n", xhci_decode_usbsts(str, usbsts)); - - ep->ep_state &= ~EP_STOP_CMD_PENDING; - - xhci_halt(xhci); - - /* - * handle a stop endpoint cmd timeout as if host died (-ENODEV). - * In the future we could distinguish between -ENODEV and -ETIMEDOUT - * and try to recover a -ETIMEDOUT with a host controller reset - */ - xhci_hc_died(xhci); - - spin_unlock_irqrestore(&xhci->lock, flags); - xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, - "xHCI host controller is dead."); -} - static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci, struct xhci_virt_device *dev, struct xhci_ring *ep_ring, @@ -1489,8 +1426,6 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, /* Cleanup cancelled TDs as ep is stopped. May queue a Set TR Deq cmd */ xhci_invalidate_cancelled_tds(ep); - if (xhci->quirks & XHCI_RESET_EP_QUIRK) - xhci_dbg(xhci, "Note: Removed workaround to queue config ep for this hw"); /* Clear our internal halted state */ ep->ep_state &= ~EP_HALTED; @@ -1534,17 +1469,13 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, struct xhci_input_control_ctx *ctrl_ctx; struct xhci_ep_ctx *ep_ctx; unsigned int ep_index; - unsigned int ep_state; - u32 add_flags, drop_flags; + u32 add_flags; /* - * Configure endpoint commands can come from the USB core - * configuration or alt setting changes, or because the HW - * needed an extra configure endpoint command after a reset - * endpoint command or streams were being configured. - * If the command was for a halted endpoint, the xHCI driver - * is not waiting on the configure endpoint command. + * Configure endpoint commands can come from the USB core configuration + * or alt setting changes, or when streams were being configured. */ + virt_dev = xhci->devs[slot_id]; if (!virt_dev) return; @@ -1555,34 +1486,13 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, } add_flags = le32_to_cpu(ctrl_ctx->add_flags); - drop_flags = le32_to_cpu(ctrl_ctx->drop_flags); + /* Input ctx add_flags are the endpoint index plus one */ ep_index = xhci_last_valid_endpoint(add_flags) - 1; ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->out_ctx, ep_index); trace_xhci_handle_cmd_config_ep(ep_ctx); - /* A usb_set_interface() call directly after clearing a halted - * condition may race on this quirky hardware. Not worth - * worrying about, since this is prototype hardware. Not sure - * if this will work for streams, but streams support was - * untested on this prototype. - */ - if (xhci->quirks & XHCI_RESET_EP_QUIRK && - ep_index != (unsigned int) -1 && - add_flags - SLOT_FLAG == drop_flags) { - ep_state = virt_dev->eps[ep_index].ep_state; - if (!(ep_state & EP_HALTED)) - return; - xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, - "Completed config ep cmd - " - "last ep index = %d, state = %d", - ep_index, ep_state); - /* Clear internal halted state and restart ring(s) */ - virt_dev->eps[ep_index].ep_state &= ~EP_HALTED; - ring_doorbell_for_active_rings(xhci, slot_id, ep_index); - return; - } return; } @@ -1650,9 +1560,12 @@ void xhci_cleanup_command_queue(struct xhci_hcd *xhci) void xhci_handle_command_timeout(struct work_struct *work) { - struct xhci_hcd *xhci; - unsigned long flags; - u64 hw_ring_state; + struct xhci_hcd *xhci; + unsigned long flags; + char str[XHCI_MSG_MAX]; + u64 hw_ring_state; + u32 cmd_field3; + u32 usbsts; xhci = container_of(to_delayed_work(work), struct xhci_hcd, cmd_timer); @@ -1666,6 +1579,27 @@ void xhci_handle_command_timeout(struct work_struct *work) spin_unlock_irqrestore(&xhci->lock, flags); return; } + + cmd_field3 = le32_to_cpu(xhci->current_cmd->command_trb->generic.field[3]); + usbsts = readl(&xhci->op_regs->status); + xhci_dbg(xhci, "Command timeout, USBSTS:%s\n", xhci_decode_usbsts(str, usbsts)); + + /* Bail out and tear down xhci if a stop endpoint command failed */ + if (TRB_FIELD_TO_TYPE(cmd_field3) == TRB_STOP_RING) { + struct xhci_virt_ep *ep; + + xhci_warn(xhci, "xHCI host not responding to stop endpoint command\n"); + + ep = xhci_get_virt_ep(xhci, TRB_TO_SLOT_ID(cmd_field3), + TRB_TO_EP_INDEX(cmd_field3)); + if (ep) + ep->ep_state &= ~EP_STOP_CMD_PENDING; + + xhci_halt(xhci); + xhci_hc_died(xhci); + goto time_out_completed; + } + /* mark this command to be cancelled */ xhci->current_cmd->status = COMP_COMMAND_ABORTED; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 25b87e99b4dd..f0ab63138016 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -486,6 +486,10 @@ static void compliance_mode_recovery(struct timer_list *t) xhci = from_timer(xhci, t, comp_mode_recovery_timer); rhub = &xhci->usb3_rhub; + hcd = rhub->hcd; + + if (!hcd) + return; for (i = 0; i < rhub->num_ports; i++) { temp = readl(rhub->ports[i]->addr); @@ -499,7 +503,6 @@ static void compliance_mode_recovery(struct timer_list *t) i + 1); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "Attempting compliance mode recovery"); - hcd = xhci->shared_hcd; if (hcd->state == HC_STATE_SUSPENDED) usb_hcd_resume_root_hub(hcd); @@ -612,14 +615,11 @@ static int xhci_run_finished(struct xhci_hcd *xhci) xhci_halt(xhci); return -ENODEV; } - xhci->shared_hcd->state = HC_STATE_RUNNING; xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; if (xhci->quirks & XHCI_NEC_HOST) xhci_ring_cmd_db(xhci); - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Finished xhci_run for USB3 roothub"); return 0; } @@ -694,12 +694,17 @@ int xhci_run(struct usb_hcd *hcd) xhci_free_command(xhci, command); } xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Finished xhci_run for USB2 roothub"); + "Finished %s for main hcd", __func__); xhci_create_dbc_dev(xhci); xhci_debugfs_init(xhci); + if (xhci_has_one_roothub(xhci)) + return xhci_run_finished(xhci); + + set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags); + return 0; } EXPORT_SYMBOL_GPL(xhci_run); @@ -992,7 +997,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) return 0; if (hcd->state != HC_STATE_SUSPENDED || - xhci->shared_hcd->state != HC_STATE_SUSPENDED) + (xhci->shared_hcd && xhci->shared_hcd->state != HC_STATE_SUSPENDED)) return -EINVAL; /* Clear root port wake on bits if wakeup not allowed. */ @@ -1009,15 +1014,18 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) __func__, hcd->self.busnum); clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); del_timer_sync(&hcd->rh_timer); - clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); - del_timer_sync(&xhci->shared_hcd->rh_timer); + if (xhci->shared_hcd) { + clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + del_timer_sync(&xhci->shared_hcd->rh_timer); + } if (xhci->quirks & XHCI_SUSPEND_DELAY) usleep_range(1000, 1500); spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); + if (xhci->shared_hcd) + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); /* step 1: stop endpoint */ /* skipped assuming that port suspend has done */ @@ -1117,7 +1125,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) msleep(100); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); + if (xhci->shared_hcd) + set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); spin_lock_irq(&xhci->lock); @@ -1177,7 +1186,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* Let the USB core know _both_ roothubs lost power. */ usb_root_hub_lost_power(xhci->main_hcd->self.root_hub); - usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub); + if (xhci->shared_hcd) + usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub); xhci_dbg(xhci, "Stop HCD\n"); xhci_halt(xhci); @@ -1217,12 +1227,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "Start the primary HCD\n"); retval = xhci_run(hcd->primary_hcd); - if (!retval) { + if (!retval && secondary_hcd) { xhci_dbg(xhci, "Start the secondary HCD\n"); retval = xhci_run(secondary_hcd); } hcd->state = HC_STATE_SUSPENDED; - xhci->shared_hcd->state = HC_STATE_SUSPENDED; + if (xhci->shared_hcd) + xhci->shared_hcd->state = HC_STATE_SUSPENDED; goto done; } @@ -1260,7 +1271,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) } if (pending_portevent) { - usb_hcd_resume_root_hub(xhci->shared_hcd); + if (xhci->shared_hcd) + usb_hcd_resume_root_hub(xhci->shared_hcd); usb_hcd_resume_root_hub(hcd); } } @@ -1279,8 +1291,10 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* Re-enable port polling. */ xhci_dbg(xhci, "%s: starting usb%d port polling.\n", __func__, hcd->self.busnum); - set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); - usb_hcd_poll_rh_status(xhci->shared_hcd); + if (xhci->shared_hcd) { + set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + usb_hcd_poll_rh_status(xhci->shared_hcd); + } set_bit(HCD_FLAG_POLL_RH, &hcd->flags); usb_hcd_poll_rh_status(hcd); @@ -1860,9 +1874,6 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) goto done; } ep->ep_state |= EP_STOP_CMD_PENDING; - ep->stop_cmd_timer.expires = jiffies + - XHCI_STOP_EP_CMD_TIMEOUT * HZ; - add_timer(&ep->stop_cmd_timer); xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id, ep_index, 0); xhci_ring_cmd_db(xhci); @@ -3972,10 +3983,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) trace_xhci_free_dev(slot_ctx); /* Stop any wayward timer functions (which may grab the lock) */ - for (i = 0; i < 31; i++) { + for (i = 0; i < 31; i++) virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING; - del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); - } virt_dev->udev = NULL; xhci_disable_slot(xhci, udev->slot_id); xhci_free_virt_device(xhci, udev->slot_id); @@ -4879,9 +4888,6 @@ static int xhci_check_intel_tier_policy(struct usb_device *udev, struct usb_device *parent; unsigned int num_hubs; - if (state == USB3_LPM_U2) - return 0; - /* Don't enable U1 if the device is on a 2nd tier hub or lower. */ for (parent = udev->parent, num_hubs = 0; parent->parent; parent = parent->parent) @@ -4890,7 +4896,7 @@ static int xhci_check_intel_tier_policy(struct usb_device *udev, if (num_hubs < 2) return 0; - dev_dbg(&udev->dev, "Disabling U1 link state for device" + dev_dbg(&udev->dev, "Disabling U1/U2 link state for device" " below second-tier hub.\n"); dev_dbg(&udev->dev, "Plug device into first-tier hub " "to decrease power consumption.\n"); @@ -4931,9 +4937,6 @@ static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd, return timeout; } - if (xhci_check_tier_policy(xhci, udev, state) < 0) - return timeout; - /* Gather some information about the currently installed configuration * and alternate interface settings. */ @@ -5040,6 +5043,9 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, !xhci->devs[udev->slot_id]) return USB3_LPM_DISABLED; + if (xhci_check_tier_policy(xhci, udev, state) < 0) + return USB3_LPM_DISABLED; + hub_encoded_timeout = xhci_calculate_lpm_timeout(hcd, udev, state); mel = calculate_max_exit_latency(udev, state, hub_encoded_timeout); if (mel < 0) { @@ -5207,6 +5213,57 @@ static int xhci_get_frame(struct usb_hcd *hcd) return readl(&xhci->run_regs->microframe_index) >> 3; } +static void xhci_hcd_init_usb2_data(struct xhci_hcd *xhci, struct usb_hcd *hcd) +{ + xhci->usb2_rhub.hcd = hcd; + hcd->speed = HCD_USB2; + hcd->self.root_hub->speed = USB_SPEED_HIGH; + /* + * USB 2.0 roothub under xHCI has an integrated TT, + * (rate matching hub) as opposed to having an OHCI/UHCI + * companion controller. + */ + hcd->has_tt = 1; +} + +static void xhci_hcd_init_usb3_data(struct xhci_hcd *xhci, struct usb_hcd *hcd) +{ + unsigned int minor_rev; + + /* + * Early xHCI 1.1 spec did not mention USB 3.1 capable hosts + * should return 0x31 for sbrn, or that the minor revision + * is a two digit BCD containig minor and sub-minor numbers. + * This was later clarified in xHCI 1.2. + * + * Some USB 3.1 capable hosts therefore have sbrn 0x30, and + * minor revision set to 0x1 instead of 0x10. + */ + if (xhci->usb3_rhub.min_rev == 0x1) + minor_rev = 1; + else + minor_rev = xhci->usb3_rhub.min_rev / 0x10; + + switch (minor_rev) { + case 2: + hcd->speed = HCD_USB32; + hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; + hcd->self.root_hub->rx_lanes = 2; + hcd->self.root_hub->tx_lanes = 2; + hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x2; + break; + case 1: + hcd->speed = HCD_USB31; + hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; + hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x1; + break; + } + xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n", + minor_rev, minor_rev ? "Enhanced " : ""); + + xhci->usb3_rhub.hcd = hcd; +} + int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) { struct xhci_hcd *xhci; @@ -5215,7 +5272,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) * quirks */ struct device *dev = hcd->self.sysdev; - unsigned int minor_rev; int retval; /* Accept arbitrarily long scatter-gather lists */ @@ -5229,61 +5285,13 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) xhci = hcd_to_xhci(hcd); - if (usb_hcd_is_primary_hcd(hcd)) { - xhci->main_hcd = hcd; - xhci->usb2_rhub.hcd = hcd; - /* Mark the first roothub as being USB 2.0. - * The xHCI driver will register the USB 3.0 roothub. - */ - hcd->speed = HCD_USB2; - hcd->self.root_hub->speed = USB_SPEED_HIGH; - /* - * USB 2.0 roothub under xHCI has an integrated TT, - * (rate matching hub) as opposed to having an OHCI/UHCI - * companion controller. - */ - hcd->has_tt = 1; - } else { - /* - * Early xHCI 1.1 spec did not mention USB 3.1 capable hosts - * should return 0x31 for sbrn, or that the minor revision - * is a two digit BCD containig minor and sub-minor numbers. - * This was later clarified in xHCI 1.2. - * - * Some USB 3.1 capable hosts therefore have sbrn 0x30, and - * minor revision set to 0x1 instead of 0x10. - */ - if (xhci->usb3_rhub.min_rev == 0x1) - minor_rev = 1; - else - minor_rev = xhci->usb3_rhub.min_rev / 0x10; - - switch (minor_rev) { - case 2: - hcd->speed = HCD_USB32; - hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; - hcd->self.root_hub->rx_lanes = 2; - hcd->self.root_hub->tx_lanes = 2; - hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x2; - break; - case 1: - hcd->speed = HCD_USB31; - hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; - hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x1; - break; - } - xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n", - minor_rev, - minor_rev ? "Enhanced " : ""); - - xhci->usb3_rhub.hcd = hcd; - /* xHCI private pointer was set in xhci_pci_probe for the second - * registered roothub. - */ + if (!usb_hcd_is_primary_hcd(hcd)) { + xhci_hcd_init_usb3_data(xhci, hcd); return 0; } mutex_init(&xhci->mutex); + xhci->main_hcd = hcd; xhci->cap_regs = hcd->regs; xhci->op_regs = hcd->regs + HC_LENGTH(readl(&xhci->cap_regs->hc_capbase)); @@ -5358,6 +5366,11 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) return retval; xhci_dbg(xhci, "Called HCD init\n"); + if (xhci_hcd_is_usb3(hcd)) + xhci_hcd_init_usb3_data(xhci, hcd); + else + xhci_hcd_init_usb2_data(xhci, hcd); + xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%016llx\n", xhci->hcc_params, xhci->hci_version, xhci->quirks); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 473a33ce299e..0bd76c94a4b1 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -948,8 +948,6 @@ struct xhci_virt_ep { #define EP_CLEARING_TT (1 << 8) /* ---- Related to URB cancellation ---- */ struct list_head cancelled_td_list; - /* Watchdog timer for stop endpoint command to cancel URBs */ - struct timer_list stop_cmd_timer; struct xhci_hcd *xhci; /* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue * command. We'll need to update the ring's dequeue segment and dequeue @@ -1848,7 +1846,7 @@ struct xhci_hcd { #define XHCI_STATE_REMOVING (1 << 2) unsigned long long quirks; #define XHCI_LINK_TRB_QUIRK BIT_ULL(0) -#define XHCI_RESET_EP_QUIRK BIT_ULL(1) +#define XHCI_RESET_EP_QUIRK BIT_ULL(1) /* Deprecated */ #define XHCI_NEC_HOST BIT_ULL(2) #define XHCI_AMD_PLL_FIX BIT_ULL(3) #define XHCI_SPURIOUS_SUCCESS BIT_ULL(4) @@ -1911,6 +1909,8 @@ struct xhci_hcd { unsigned hw_lpm_support:1; /* Broken Suspend flag for SNPS Suspend resume issue */ unsigned broken_suspend:1; + /* Indicates that omitting hcd is supported if root hub has no ports */ + unsigned allow_single_roothub:1; /* cached usb2 extened protocol capabilites */ u32 *ext_caps; unsigned int num_ext_caps; @@ -1966,6 +1966,30 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) return xhci->main_hcd; } +static inline struct usb_hcd *xhci_get_usb3_hcd(struct xhci_hcd *xhci) +{ + if (xhci->shared_hcd) + return xhci->shared_hcd; + + if (!xhci->usb2_rhub.num_ports) + return xhci->main_hcd; + + return NULL; +} + +static inline bool xhci_hcd_is_usb3(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + return hcd == xhci_get_usb3_hcd(xhci); +} + +static inline bool xhci_has_one_roothub(struct xhci_hcd *xhci) +{ + return xhci->allow_single_roothub && + (!xhci->usb2_rhub.num_ports || !xhci->usb3_rhub.num_ports); +} + #define xhci_dbg(xhci, fmt, args...) \ dev_dbg(xhci_to_hcd(xhci)->self.controller , fmt , ## args) #define xhci_err(xhci, fmt, args...) \ |