Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/torvalds/linux.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-06-03 21:17:49 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-06-03 21:17:49 +0300
commit54c2cc79194c961a213c1d375fe3aa4165664cc4 (patch)
treea6f03d84b18dcab2a03c0d162327bba2f577cfb5 /drivers/usb/host
parent932c2989b59008e530ffcc7c7e6ef507a28b28ca (diff)
parent97fa5887cf283bb75ffff5f6b2c0e71794c02400 (diff)
Merge tag 'usb-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB / Thunderbolt updates from Greg KH: "Here is the "big" set of USB and Thunderbolt driver changes for 5.18-rc1. For the most part it's been a quiet development cycle for the USB core, but there are the usual "hot spots" of development activity. Included in here are: - Thunderbolt driver updates: - fixes for devices without displayport adapters - lane bonding support and improvements - other minor changes based on device testing - dwc3 gadget driver changes. It seems this driver will never be finished given that the IP core is showing up in zillions of new devices and each implementation decides to do something different with it... - uvc gadget driver updates as more devices start to use and rely on this hardware as well - usb_maxpacket() api changes to remove an unneeded and unused parameter. - usb-serial driver device id updates and small cleanups - typec cleanups and fixes based on device testing - device tree updates for usb properties - lots of other small fixes and driver updates. All of these have been in linux-next for weeks with no reported problems" * tag 'usb-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (154 commits) USB: new quirk for Dell Gen 2 devices usb: dwc3: core: Add error log when core soft reset failed usb: dwc3: gadget: Move null pinter check to proper place usb: hub: Simplify error and success path in port_over_current_notify usb: cdns3: allocate TX FIFO size according to composite EP number usb: dwc3: Fix ep0 handling when getting reset while doing control transfer usb: Probe EHCI, OHCI controllers asynchronously usb: isp1760: Fix out-of-bounds array access xhci: Don't defer primary roothub registration if there is only one roothub USB: serial: option: add Quectel BG95 modem USB: serial: pl2303: fix type detection for odd device xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI xhci: Remove quirk for over 10 year old evaluation hardware xhci: prevent U2 link power state if Intel tier policy prevented U1 xhci: use generic command timer for stop endpoint commands. usb: host: xhci-plat: omit shared hcd if either root hub has no ports usb: host: xhci-plat: prepare operation w/o shared hcd usb: host: xhci-plat: create shared hcd after having added main hcd xhci: prepare for operation w/o shared hcd xhci: factor out parts of xhci_gen_setup() ...
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-omap.c5
-rw-r--r--drivers/usb/host/ehci-platform.c1
-rw-r--r--drivers/usb/host/ehci-q.c4
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c12
-rw-r--r--drivers/usb/host/fhci-hcd.c3
-rw-r--r--drivers/usb/host/fotg210-hcd.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c11
-rw-r--r--drivers/usb/host/isp1362-hcd.c6
-rw-r--r--drivers/usb/host/max3421-hcd.c6
-rw-r--r--drivers/usb/host/ohci-hcd.c3
-rw-r--r--drivers/usb/host/ohci-omap.c18
-rw-r--r--drivers/usb/host/ohci-platform.c1
-rw-r--r--drivers/usb/host/ohci-ppc-of.c3
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c16
-rw-r--r--drivers/usb/host/r8a66597-hcd.c3
-rw-r--r--drivers/usb/host/sl811-hcd.c6
-rw-r--r--drivers/usb/host/xhci-hub.c3
-rw-r--r--drivers/usb/host/xhci-mem.c23
-rw-r--r--drivers/usb/host/xhci-pci.c5
-rw-r--r--drivers/usb/host/xhci-plat.c46
-rw-r--r--drivers/usb/host/xhci-ring.c144
-rw-r--r--drivers/usb/host/xhci.c175
-rw-r--r--drivers/usb/host/xhci.h30
23 files changed, 255 insertions, 271 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/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...) \