summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/Kconfig12
-rw-r--r--drivers/usb/host/Makefile4
-rw-r--r--drivers/usb/host/ehci-dbg.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c4
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-mem.c12
-rw-r--r--drivers/usb/host/ehci-orion.c36
-rw-r--r--drivers/usb/host/ehci-platform.c10
-rw-r--r--drivers/usb/host/fotg210-hcd.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c5
-rw-r--r--drivers/usb/host/ohci-pci.c16
-rw-r--r--drivers/usb/host/ohci-platform.c3
-rw-r--r--drivers/usb/host/ohci.h3
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c2
-rw-r--r--drivers/usb/host/pci-quirks.h4
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/host/uhci-hcd.h2
-rw-r--r--drivers/usb/host/xhci-dbg.c308
-rw-r--r--drivers/usb/host/xhci-hub.c167
-rw-r--r--drivers/usb/host/xhci-mem.c53
-rw-r--r--drivers/usb/host/xhci-pci.c3
-rw-r--r--drivers/usb/host/xhci-plat.c121
-rw-r--r--drivers/usb/host/xhci-plat.h1
-rw-r--r--drivers/usb/host/xhci-rcar.c11
-rw-r--r--drivers/usb/host/xhci-rcar.h6
-rw-r--r--drivers/usb/host/xhci-ring.c266
-rw-r--r--drivers/usb/host/xhci-trace.h174
-rw-r--r--drivers/usb/host/xhci.c334
-rw-r--r--drivers/usb/host/xhci.h333
29 files changed, 1093 insertions, 805 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 407d947b34ea..ababb91d654a 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -30,7 +30,7 @@ if USB_XHCI_HCD
config USB_XHCI_PCI
tristate
- depends on PCI
+ depends on USB_PCI
default y
config USB_XHCI_PLATFORM
@@ -139,7 +139,7 @@ if USB_EHCI_HCD
config USB_EHCI_PCI
tristate
- depends on PCI
+ depends on USB_PCI
default y
config USB_EHCI_HCD_PMC_MSP
@@ -188,7 +188,7 @@ config USB_EHCI_HCD_OMAP
config USB_EHCI_HCD_ORION
tristate "Support for Marvell EBU on-chip EHCI USB controller"
- depends on USB_EHCI_HCD && PLAT_ORION
+ depends on USB_EHCI_HCD && (PLAT_ORION || ARCH_MVEBU)
default y
---help---
Enables support for the on-chip EHCI controller on Marvell's
@@ -525,7 +525,7 @@ config USB_OHCI_HCD_PPC_OF
config USB_OHCI_HCD_PCI
tristate "OHCI support for PCI-bus USB controllers"
- depends on PCI
+ depends on USB_PCI
default y
select USB_OHCI_LITTLE_ENDIAN
---help---
@@ -606,7 +606,7 @@ endif # USB_OHCI_HCD
config USB_UHCI_HCD
tristate "UHCI HCD (most Intel and VIA) support"
- depends on PCI || USB_UHCI_SUPPORT_NON_PCI_HC
+ depends on USB_PCI || USB_UHCI_SUPPORT_NON_PCI_HC
---help---
The Universal Host Controller Interface is a standard by Intel for
accessing the USB hardware in the PC (which is also called the USB
@@ -739,7 +739,7 @@ config USB_RENESAS_USBHS_HCD
config USB_WHCI_HCD
tristate "Wireless USB Host Controller Interface (WHCI) driver"
- depends on PCI && USB && UWB
+ depends on USB_PCI && USB && UWB
select USB_WUSB
select UWB_WHCI
help
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 2644537b7bcf..c77b0a38557b 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -27,9 +27,7 @@ endif
obj-$(CONFIG_USB_WHCI_HCD) += whci/
-ifneq ($(CONFIG_USB), )
- obj-$(CONFIG_PCI) += pci-quirks.o
-endif
+obj-$(CONFIG_USB_PCI) += pci-quirks.o
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 1a2614aae42c..cbb9b8e12c3c 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -803,7 +803,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
size -= temp;
next += temp;
-#ifdef CONFIG_PCI
+#ifdef CONFIG_USB_PCI
/* EHCI 0.96 and later may have "extended capabilities" */
if (dev_is_pci(hcd->self.controller)) {
struct pci_dev *pdev;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 3733aab46efe..4a08b70c81aa 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -96,8 +96,8 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
}
irq = res->start;
- hcd = usb_create_hcd(&fsl_ehci_hc_driver, &pdev->dev,
- dev_name(&pdev->dev));
+ hcd = __usb_create_hcd(&fsl_ehci_hc_driver, pdev->dev.parent,
+ &pdev->dev, dev_name(&pdev->dev), NULL);
if (!hcd) {
retval = -ENOMEM;
goto err1;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ac2c4eab478d..6e834b83a104 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -597,7 +597,7 @@ static int ehci_run (struct usb_hcd *hcd)
/*
* hcc_params controls whether ehci->regs->segment must (!!!)
* be used; it constrains QH/ITD/SITD and QTD locations.
- * pci_pool consistent memory always uses segment zero.
+ * dma_pool consistent memory always uses segment zero.
* streaming mappings for I/O buffers, like pci_map_single(),
* can return segments above 4GB, if the device allows.
*
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 4de43011df23..9b7e63977215 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -138,7 +138,7 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
ehci->sitd_pool = NULL;
if (ehci->periodic)
- dma_free_coherent (ehci_to_hcd(ehci)->self.controller,
+ dma_free_coherent(ehci_to_hcd(ehci)->self.sysdev,
ehci->periodic_size * sizeof (u32),
ehci->periodic, ehci->periodic_dma);
ehci->periodic = NULL;
@@ -155,7 +155,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
/* QTDs for control/bulk/intr transfers */
ehci->qtd_pool = dma_pool_create ("ehci_qtd",
- ehci_to_hcd(ehci)->self.controller,
+ ehci_to_hcd(ehci)->self.sysdev,
sizeof (struct ehci_qtd),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
@@ -165,7 +165,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
/* QHs for control/bulk/intr transfers */
ehci->qh_pool = dma_pool_create ("ehci_qh",
- ehci_to_hcd(ehci)->self.controller,
+ ehci_to_hcd(ehci)->self.sysdev,
sizeof(struct ehci_qh_hw),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
@@ -179,7 +179,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
/* ITD for high speed ISO transfers */
ehci->itd_pool = dma_pool_create ("ehci_itd",
- ehci_to_hcd(ehci)->self.controller,
+ ehci_to_hcd(ehci)->self.sysdev,
sizeof (struct ehci_itd),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
@@ -189,7 +189,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
/* SITD for full/low speed split ISO transfers */
ehci->sitd_pool = dma_pool_create ("ehci_sitd",
- ehci_to_hcd(ehci)->self.controller,
+ ehci_to_hcd(ehci)->self.sysdev,
sizeof (struct ehci_sitd),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
@@ -199,7 +199,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
/* Hardware periodic table */
ehci->periodic = (__le32 *)
- dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller,
+ dma_alloc_coherent(ehci_to_hcd(ehci)->self.sysdev,
ehci->periodic_size * sizeof(__le32),
&ehci->periodic_dma, flags);
if (ehci->periodic == NULL) {
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index ee8d5faa0194..1aec87ec68df 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -47,6 +47,18 @@
#define USB_PHY_IVREF_CTRL 0x440
#define USB_PHY_TST_GRP_CTRL 0x450
+#define USB_SBUSCFG 0x90
+
+/* BAWR = BARD = 3 : Align read/write bursts packets larger than 128 bytes */
+#define USB_SBUSCFG_BAWR_ALIGN_128B (0x3 << 6)
+#define USB_SBUSCFG_BARD_ALIGN_128B (0x3 << 3)
+/* AHBBRST = 3 : Align AHB Burst to INCR16 (64 bytes) */
+#define USB_SBUSCFG_AHBBRST_INCR16 (0x3 << 0)
+
+#define USB_SBUSCFG_DEF_VAL (USB_SBUSCFG_BAWR_ALIGN_128B \
+ | USB_SBUSCFG_BARD_ALIGN_128B \
+ | USB_SBUSCFG_AHBBRST_INCR16)
+
#define DRIVER_DESC "EHCI orion driver"
#define hcd_to_orion_priv(h) ((struct orion_ehci_hcd *)hcd_to_ehci(h)->priv)
@@ -151,8 +163,31 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
}
}
+static int ehci_orion_drv_reset(struct usb_hcd *hcd)
+{
+ struct device *dev = hcd->self.controller;
+ int ret;
+
+ ret = ehci_setup(hcd);
+ if (ret)
+ return ret;
+
+ /*
+ * For SoC without hlock, need to program sbuscfg value to guarantee
+ * AHB master's burst would not overrun or underrun FIFO.
+ *
+ * sbuscfg reg has to be set after usb controller reset, otherwise
+ * the value would be override to 0.
+ */
+ if (of_device_is_compatible(dev->of_node, "marvell,armada-3700-ehci"))
+ wrl(USB_SBUSCFG, USB_SBUSCFG_DEF_VAL);
+
+ return ret;
+}
+
static const struct ehci_driver_overrides orion_overrides __initconst = {
.extra_priv_size = sizeof(struct orion_ehci_hcd),
+ .reset = ehci_orion_drv_reset,
};
static int ehci_orion_drv_probe(struct platform_device *pdev)
@@ -310,6 +345,7 @@ static int ehci_orion_drv_remove(struct platform_device *pdev)
static const struct of_device_id ehci_orion_dt_ids[] = {
{ .compatible = "marvell,orion-ehci", },
+ { .compatible = "marvell,armada-3700-ehci", },
{},
};
MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index a268d9e8d6cf..bc7b9be12f54 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -34,6 +34,7 @@
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/of.h>
#include "ehci.h"
@@ -220,6 +221,9 @@ static int ehci_platform_probe(struct platform_device *dev)
if (IS_ERR(priv->phys[phy_num])) {
err = PTR_ERR(priv->phys[phy_num]);
goto err_put_hcd;
+ } else if (!hcd->phy) {
+ /* Avoiding phy_get() in usb_add_hcd() */
+ hcd->phy = priv->phys[phy_num];
}
}
@@ -297,6 +301,7 @@ static int ehci_platform_probe(struct platform_device *dev)
goto err_power;
device_wakeup_enable(hcd->self.controller);
+ device_enable_async_suspend(hcd->self.controller);
platform_set_drvdata(dev, hcd);
return err;
@@ -370,6 +375,7 @@ static int ehci_platform_resume(struct device *dev)
struct usb_ehci_pdata *pdata = dev_get_platdata(dev);
struct platform_device *pdev = to_platform_device(dev);
struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+ struct device *companion_dev;
if (pdata->power_on) {
int err = pdata->power_on(pdev);
@@ -377,6 +383,10 @@ static int ehci_platform_resume(struct device *dev)
return err;
}
+ companion_dev = usb_of_get_companion_dev(hcd->self.controller);
+ if (companion_dev)
+ device_pm_wait_for_dev(hcd->self.controller, companion_dev);
+
ehci_resume(hcd, priv->reset_on_resume);
return 0;
}
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index 1c5b34b74860..ced08dc229ad 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -5047,7 +5047,7 @@ static int fotg210_run(struct usb_hcd *hcd)
/*
* hcc_params controls whether fotg210->regs->segment must (!!!)
* be used; it constrains QH/ITD/SITD and QTD locations.
- * pci_pool consistent memory always uses segment zero.
+ * dma_pool consistent memory always uses segment zero.
* streaming mappings for I/O buffers, like pci_map_single(),
* can return segments above 4GB, if the device allows.
*
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index b6daf2e69989..44924824fa41 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -231,7 +231,8 @@ static int ohci_urb_enqueue (
/* Start up the I/O watchdog timer, if it's not running */
if (!timer_pending(&ohci->io_watchdog) &&
- list_empty(&ohci->eds_in_use)) {
+ list_empty(&ohci->eds_in_use) &&
+ !(ohci->flags & OHCI_QUIRK_QEMU)) {
ohci->prev_frame_no = ohci_frame_no(ohci);
mod_timer(&ohci->io_watchdog,
jiffies + IO_WATCHDOG_DELAY);
@@ -994,7 +995,7 @@ static void ohci_stop (struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_PM) || defined(CONFIG_PCI)
+#if defined(CONFIG_PM) || defined(CONFIG_USB_PCI)
/* must not be called from interrupt context */
int ohci_restart(struct ohci_hcd *ohci)
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index bb1509675727..a84aebe9b0a9 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -164,6 +164,15 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
return 0;
}
+static int ohci_quirk_qemu(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+ ohci->flags |= OHCI_QUIRK_QEMU;
+ ohci_dbg(ohci, "enabled qemu quirk\n");
+ return 0;
+}
+
/* List of quirks for OHCI */
static const struct pci_device_id ohci_pci_quirks[] = {
{
@@ -214,6 +223,13 @@ static const struct pci_device_id ohci_pci_quirks[] = {
PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
.driver_data = (unsigned long)ohci_quirk_amd700,
},
+ {
+ .vendor = PCI_VENDOR_ID_APPLE,
+ .device = 0x003f,
+ .subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
+ .subdevice = PCI_SUBDEVICE_ID_QEMU,
+ .driver_data = (unsigned long)ohci_quirk_qemu,
+ },
/* FIXME for some of the early AMD 760 southbridges, OHCI
* won't work at all. blacklist them.
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 898b74086c12..6368fce43197 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -183,6 +183,9 @@ static int ohci_platform_probe(struct platform_device *dev)
if (IS_ERR(priv->phys[phy_num])) {
err = PTR_ERR(priv->phys[phy_num]);
goto err_put_hcd;
+ } else if (!hcd->phy) {
+ /* Avoiding phy_get() in usb_add_hcd() */
+ hcd->phy = priv->phys[phy_num];
}
}
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 37f1725e7a46..12742d002d2d 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -418,6 +418,7 @@ struct ohci_hcd {
#define OHCI_QUIRK_AMD_PLL 0x200 /* AMD PLL quirk*/
#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
#define OHCI_QUIRK_GLOBAL_SUSPEND 0x800 /* must suspend ports */
+#define OHCI_QUIRK_QEMU 0x1000 /* relax timing expectations */
// there are also chip quirks/bugs in init logic
@@ -438,7 +439,7 @@ struct ohci_hcd {
};
-#ifdef CONFIG_PCI
+#ifdef CONFIG_USB_PCI
static inline int quirk_nec(struct ohci_hcd *ohci)
{
return ohci->flags & OHCI_QUIRK_NEC;
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index bcf531c44c70..ed20fb34c897 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -2708,7 +2708,7 @@ static int oxu_run(struct usb_hcd *hcd)
/* hcc_params controls whether oxu->regs->segment must (!!!)
* be used; it constrains QH/ITD/SITD and QTD locations.
- * pci_pool consistent memory always uses segment zero.
+ * dma_pool consistent memory always uses segment zero.
* streaming mappings for I/O buffers, like pci_map_single(),
* can return segments above 4GB, if the device allows.
*
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index c622ddf21c94..0222195bd5b0 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -1,7 +1,7 @@
#ifndef __LINUX_USB_PCI_QUIRKS_H
#define __LINUX_USB_PCI_QUIRKS_H
-#ifdef CONFIG_PCI
+#ifdef CONFIG_USB_PCI
void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
int usb_amd_find_chipset_info(void);
@@ -21,6 +21,6 @@ static inline void usb_amd_quirk_pll_enable(void) {}
static inline void usb_amd_dev_put(void) {}
static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
static inline void sb800_prefetch(struct device *dev, int on) {}
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_USB_PCI */
#endif /* __LINUX_USB_PCI_QUIRKS_H */
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 683098afa93e..94b150196d4f 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -837,7 +837,7 @@ static int uhci_count_ports(struct usb_hcd *hcd)
static const char hcd_name[] = "uhci_hcd";
-#ifdef CONFIG_PCI
+#ifdef CONFIG_USB_PCI
#include "uhci-pci.c"
#define PCI_DRIVER uhci_pci_driver
#endif
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 6f986d82472d..7fa318a3091d 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -530,7 +530,7 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg)
#else
/* Support non-PCI host controllers */
-#ifdef CONFIG_PCI
+#ifdef CONFIG_USB_PCI
/* Support PCI and non-PCI host controllers */
#define uhci_has_pci_registers(u) ((u)->io_addr != 0)
#else
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 2b4a00fa735d..2c83b37ae8f2 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -254,157 +254,6 @@ void xhci_print_registers(struct xhci_hcd *xhci)
xhci_print_ports(xhci);
}
-void xhci_print_trb_offsets(struct xhci_hcd *xhci, union xhci_trb *trb)
-{
- int i;
- for (i = 0; i < 4; i++)
- xhci_dbg(xhci, "Offset 0x%x = 0x%x\n",
- i*4, trb->generic.field[i]);
-}
-
-/**
- * Debug a transfer request block (TRB).
- */
-void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
-{
- u64 address;
- u32 type = le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK;
-
- switch (type) {
- case TRB_TYPE(TRB_LINK):
- xhci_dbg(xhci, "Link TRB:\n");
- xhci_print_trb_offsets(xhci, trb);
-
- address = le64_to_cpu(trb->link.segment_ptr);
- xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address);
-
- xhci_dbg(xhci, "Interrupter target = 0x%x\n",
- GET_INTR_TARGET(le32_to_cpu(trb->link.intr_target)));
- xhci_dbg(xhci, "Cycle bit = %u\n",
- le32_to_cpu(trb->link.control) & TRB_CYCLE);
- xhci_dbg(xhci, "Toggle cycle bit = %u\n",
- le32_to_cpu(trb->link.control) & LINK_TOGGLE);
- xhci_dbg(xhci, "No Snoop bit = %u\n",
- le32_to_cpu(trb->link.control) & TRB_NO_SNOOP);
- break;
- case TRB_TYPE(TRB_TRANSFER):
- address = le64_to_cpu(trb->trans_event.buffer);
- /*
- * FIXME: look at flags to figure out if it's an address or if
- * the data is directly in the buffer field.
- */
- xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
- break;
- case TRB_TYPE(TRB_COMPLETION):
- address = le64_to_cpu(trb->event_cmd.cmd_trb);
- xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
- xhci_dbg(xhci, "Completion status = %u\n",
- GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status)));
- xhci_dbg(xhci, "Flags = 0x%x\n",
- le32_to_cpu(trb->event_cmd.flags));
- break;
- default:
- xhci_dbg(xhci, "Unknown TRB with TRB type ID %u\n",
- (unsigned int) type>>10);
- xhci_print_trb_offsets(xhci, trb);
- break;
- }
-}
-
-/**
- * Debug a segment with an xHCI ring.
- *
- * @return The Link TRB of the segment, or NULL if there is no Link TRB
- * (which is a bug, since all segments must have a Link TRB).
- *
- * Prints out all TRBs in the segment, even those after the Link TRB.
- *
- * XXX: should we print out TRBs that the HC owns? As long as we don't
- * write, that should be fine... We shouldn't expect that the memory pointed to
- * by the TRB is valid at all. Do we care about ones the HC owns? Probably,
- * for HC debugging.
- */
-void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
-{
- int i;
- u64 addr = seg->dma;
- union xhci_trb *trb = seg->trbs;
-
- for (i = 0; i < TRBS_PER_SEGMENT; i++) {
- trb = &seg->trbs[i];
- xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", addr,
- lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
- upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
- le32_to_cpu(trb->link.intr_target),
- le32_to_cpu(trb->link.control));
- addr += sizeof(*trb);
- }
-}
-
-void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring)
-{
- xhci_dbg(xhci, "Ring deq = %p (virt), 0x%llx (dma)\n",
- ring->dequeue,
- (unsigned long long)xhci_trb_virt_to_dma(ring->deq_seg,
- ring->dequeue));
- xhci_dbg(xhci, "Ring deq updated %u times\n",
- ring->deq_updates);
- xhci_dbg(xhci, "Ring enq = %p (virt), 0x%llx (dma)\n",
- ring->enqueue,
- (unsigned long long)xhci_trb_virt_to_dma(ring->enq_seg,
- ring->enqueue));
- xhci_dbg(xhci, "Ring enq updated %u times\n",
- ring->enq_updates);
-}
-
-/**
- * Debugging for an xHCI ring, which is a queue broken into multiple segments.
- *
- * Print out each segment in the ring. Check that the DMA address in
- * each link segment actually matches the segment's stored DMA address.
- * Check that the link end bit is only set at the end of the ring.
- * Check that the dequeue and enqueue pointers point to real data in this ring
- * (not some other ring).
- */
-void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring)
-{
- /* FIXME: Throw an error if any segment doesn't have a Link TRB */
- struct xhci_segment *seg;
- struct xhci_segment *first_seg = ring->first_seg;
- xhci_debug_segment(xhci, first_seg);
-
- if (!ring->enq_updates && !ring->deq_updates) {
- xhci_dbg(xhci, " Ring has not been updated\n");
- return;
- }
- for (seg = first_seg->next; seg != first_seg; seg = seg->next)
- xhci_debug_segment(xhci, seg);
-}
-
-void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
- unsigned int slot_id, unsigned int ep_index,
- struct xhci_virt_ep *ep)
-{
- int i;
- struct xhci_ring *ring;
-
- if (ep->ep_state & EP_HAS_STREAMS) {
- for (i = 1; i < ep->stream_info->num_streams; i++) {
- ring = ep->stream_info->stream_rings[i];
- xhci_dbg(xhci, "Dev %d endpoint %d stream ID %d:\n",
- slot_id, ep_index, i);
- xhci_debug_segment(xhci, ring->deq_seg);
- }
- } else {
- ring = ep->ring;
- if (!ring)
- return;
- xhci_dbg(xhci, "Dev %d endpoint ring %d:\n",
- slot_id, ep_index);
- xhci_debug_segment(xhci, ring->deq_seg);
- }
-}
-
void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
{
u64 addr = erst->erst_dma_addr;
@@ -434,166 +283,13 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
upper_32_bits(val));
}
-/* Print the last 32 bytes for 64-byte contexts */
-static void dbg_rsvd64(struct xhci_hcd *xhci, u64 *ctx, dma_addr_t dma)
-{
- int i;
- for (i = 0; i < 4; i++) {
- xhci_dbg(xhci, "@%p (virt) @%08llx "
- "(dma) %#08llx - rsvd64[%d]\n",
- &ctx[4 + i], (unsigned long long)dma,
- ctx[4 + i], i);
- dma += 8;
- }
-}
-
char *xhci_get_slot_state(struct xhci_hcd *xhci,
struct xhci_container_ctx *ctx)
{
struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
+ int state = GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state));
- switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) {
- case SLOT_STATE_ENABLED:
- return "enabled/disabled";
- case SLOT_STATE_DEFAULT:
- return "default";
- case SLOT_STATE_ADDRESSED:
- return "addressed";
- case SLOT_STATE_CONFIGURED:
- return "configured";
- default:
- return "reserved";
- }
-}
-
-static void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx)
-{
- /* Fields are 32 bits wide, DMA addresses are in bytes */
- int field_size = 32 / 8;
- int i;
-
- struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
- dma_addr_t dma = ctx->dma +
- ((unsigned long)slot_ctx - (unsigned long)ctx->bytes);
- int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
-
- xhci_dbg(xhci, "Slot Context:\n");
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n",
- &slot_ctx->dev_info,
- (unsigned long long)dma, slot_ctx->dev_info);
- dma += field_size;
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n",
- &slot_ctx->dev_info2,
- (unsigned long long)dma, slot_ctx->dev_info2);
- dma += field_size;
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n",
- &slot_ctx->tt_info,
- (unsigned long long)dma, slot_ctx->tt_info);
- dma += field_size;
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n",
- &slot_ctx->dev_state,
- (unsigned long long)dma, slot_ctx->dev_state);
- dma += field_size;
- for (i = 0; i < 4; i++) {
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
- &slot_ctx->reserved[i], (unsigned long long)dma,
- slot_ctx->reserved[i], i);
- dma += field_size;
- }
-
- if (csz)
- dbg_rsvd64(xhci, (u64 *)slot_ctx, dma);
-}
-
-static void xhci_dbg_ep_ctx(struct xhci_hcd *xhci,
- struct xhci_container_ctx *ctx,
- unsigned int last_ep)
-{
- int i, j;
- int last_ep_ctx = 31;
- /* Fields are 32 bits wide, DMA addresses are in bytes */
- int field_size = 32 / 8;
- int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
-
- if (last_ep < 31)
- last_ep_ctx = last_ep + 1;
- for (i = 0; i < last_ep_ctx; i++) {
- unsigned int epaddr = xhci_get_endpoint_address(i);
- struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i);
- dma_addr_t dma = ctx->dma +
- ((unsigned long)ep_ctx - (unsigned long)ctx->bytes);
-
- xhci_dbg(xhci, "%s Endpoint %02d Context (ep_index %02d):\n",
- usb_endpoint_out(epaddr) ? "OUT" : "IN",
- epaddr & USB_ENDPOINT_NUMBER_MASK, i);
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
- &ep_ctx->ep_info,
- (unsigned long long)dma, ep_ctx->ep_info);
- dma += field_size;
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n",
- &ep_ctx->ep_info2,
- (unsigned long long)dma, ep_ctx->ep_info2);
- dma += field_size;
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n",
- &ep_ctx->deq,
- (unsigned long long)dma, ep_ctx->deq);
- dma += 2*field_size;
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n",
- &ep_ctx->tx_info,
- (unsigned long long)dma, ep_ctx->tx_info);
- dma += field_size;
- for (j = 0; j < 3; j++) {
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
- &ep_ctx->reserved[j],
- (unsigned long long)dma,
- ep_ctx->reserved[j], j);
- dma += field_size;
- }
-
- if (csz)
- dbg_rsvd64(xhci, (u64 *)ep_ctx, dma);
- }
-}
-
-void xhci_dbg_ctx(struct xhci_hcd *xhci,
- struct xhci_container_ctx *ctx,
- unsigned int last_ep)
-{
- int i;
- /* Fields are 32 bits wide, DMA addresses are in bytes */
- int field_size = 32 / 8;
- dma_addr_t dma = ctx->dma;
- int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
-
- if (ctx->type == XHCI_CTX_TYPE_INPUT) {
- struct xhci_input_control_ctx *ctrl_ctx =
- xhci_get_input_control_ctx(ctx);
- if (!ctrl_ctx) {
- xhci_warn(xhci, "Could not get input context, bad type.\n");
- return;
- }
-
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
- &ctrl_ctx->drop_flags, (unsigned long long)dma,
- ctrl_ctx->drop_flags);
- dma += field_size;
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
- &ctrl_ctx->add_flags, (unsigned long long)dma,
- ctrl_ctx->add_flags);
- dma += field_size;
- for (i = 0; i < 6; i++) {
- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n",
- &ctrl_ctx->rsvd2[i], (unsigned long long)dma,
- ctrl_ctx->rsvd2[i], i);
- dma += field_size;
- }
-
- if (csz)
- dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);
- }
-
- xhci_dbg_slot_ctx(xhci, ctx);
- xhci_dbg_ep_ctx(xhci, ctx, last_ep);
+ return xhci_slot_state_string(state);
}
void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *),
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 3bddeaa1e2d7..5e3e9d4c6956 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -392,10 +392,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
trace_xhci_stop_device(virt_dev);
cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
- if (!cmd) {
- xhci_dbg(xhci, "Couldn't allocate command structure.\n");
+ if (!cmd)
return -ENOMEM;
- }
spin_lock_irqsave(&xhci->lock, flags);
for (i = LAST_EP_INDEX; i > 0; i--) {
@@ -540,6 +538,119 @@ static int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array)
return max_ports;
}
+static __le32 __iomem *xhci_get_port_io_addr(struct usb_hcd *hcd, int index)
+{
+ __le32 __iomem **port_array;
+
+ xhci_get_ports(hcd, &port_array);
+ return port_array[index];
+}
+
+/*
+ * xhci_set_port_power() must be called with xhci->lock held.
+ * It will release and re-aquire the lock while calling ACPI
+ * method.
+ */
+static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
+ u16 index, bool on, unsigned long *flags)
+{
+ __le32 __iomem *addr;
+ u32 temp;
+
+ addr = xhci_get_port_io_addr(hcd, index);
+ temp = readl(addr);
+ temp = xhci_port_state_to_neutral(temp);
+ if (on) {
+ /* Power on */
+ writel(temp | PORT_POWER, addr);
+ temp = readl(addr);
+ xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n",
+ index, temp);
+ } else {
+ /* Power off */
+ writel(temp & ~PORT_POWER, addr);
+ }
+
+ spin_unlock_irqrestore(&xhci->lock, *flags);
+ temp = usb_acpi_power_manageable(hcd->self.root_hub,
+ index);
+ if (temp)
+ usb_acpi_set_power_state(hcd->self.root_hub,
+ index, on);
+ spin_lock_irqsave(&xhci->lock, *flags);
+}
+
+static void xhci_port_set_test_mode(struct xhci_hcd *xhci,
+ u16 test_mode, u16 wIndex)
+{
+ u32 temp;
+ __le32 __iomem *addr;
+
+ /* xhci only supports test mode for usb2 ports, i.e. xhci->main_hcd */
+ addr = xhci_get_port_io_addr(xhci->main_hcd, wIndex);
+ temp = readl(addr + PORTPMSC);
+ temp |= test_mode << PORT_TEST_MODE_SHIFT;
+ writel(temp, addr + PORTPMSC);
+ xhci->test_mode = test_mode;
+ if (test_mode == TEST_FORCE_EN)
+ xhci_start(xhci);
+}
+
+static int xhci_enter_test_mode(struct xhci_hcd *xhci,
+ u16 test_mode, u16 wIndex, unsigned long *flags)
+{
+ int i, retval;
+
+ /* Disable all Device Slots */
+ xhci_dbg(xhci, "Disable all slots\n");
+ for (i = 1; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
+ retval = xhci_disable_slot(xhci, NULL, i);
+ if (retval)
+ xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",
+ i, retval);
+ }
+ /* Put all ports to the Disable state by clear PP */
+ xhci_dbg(xhci, "Disable all port (PP = 0)\n");
+ /* Power off USB3 ports*/
+ for (i = 0; i < xhci->num_usb3_ports; i++)
+ xhci_set_port_power(xhci, xhci->shared_hcd, i, false, flags);
+ /* Power off USB2 ports*/
+ for (i = 0; i < xhci->num_usb2_ports; i++)
+ xhci_set_port_power(xhci, xhci->main_hcd, i, false, flags);
+ /* Stop the controller */
+ xhci_dbg(xhci, "Stop controller\n");
+ retval = xhci_halt(xhci);
+ if (retval)
+ return retval;
+ /* Disable runtime PM for test mode */
+ pm_runtime_forbid(xhci_to_hcd(xhci)->self.controller);
+ /* Set PORTPMSC.PTC field to enter selected test mode */
+ /* Port is selected by wIndex. port_id = wIndex + 1 */
+ xhci_dbg(xhci, "Enter Test Mode: %d, Port_id=%d\n",
+ test_mode, wIndex + 1);
+ xhci_port_set_test_mode(xhci, test_mode, wIndex);
+ return retval;
+}
+
+static int xhci_exit_test_mode(struct xhci_hcd *xhci)
+{
+ int retval;
+
+ if (!xhci->test_mode) {
+ xhci_err(xhci, "Not in test mode, do nothing.\n");
+ return 0;
+ }
+ if (xhci->test_mode == TEST_FORCE_EN &&
+ !(xhci->xhc_state & XHCI_STATE_HALTED)) {
+ retval = xhci_halt(xhci);
+ if (retval)
+ return retval;
+ }
+ pm_runtime_allow(xhci_to_hcd(xhci)->self.controller);
+ xhci->test_mode = 0;
+ return xhci_reset(xhci);
+}
+
void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
int port_id, u32 link_state)
{
@@ -895,6 +1006,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 link_state = 0;
u16 wake_mask = 0;
u16 timeout = 0;
+ u16 test_mode = 0;
max_ports = xhci_get_ports(hcd, &port_array);
bus_state = &xhci->bus_state[hcd_index(hcd)];
@@ -935,7 +1047,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
goto error;
wIndex--;
temp = readl(port_array[wIndex]);
- if (temp == 0xffffffff) {
+ if (temp == ~(u32)0) {
+ xhci_hc_died(xhci);
retval = -ENODEV;
break;
}
@@ -968,6 +1081,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
link_state = (wIndex & 0xff00) >> 3;
if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
wake_mask = wIndex & 0xff00;
+ if (wValue == USB_PORT_FEAT_TEST)
+ test_mode = (wIndex & 0xff00) >> 8;
/* The MSB of wIndex is the U1/U2 timeout */
timeout = (wIndex & 0xff00) >> 8;
wIndex &= 0xff;
@@ -975,7 +1090,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
goto error;
wIndex--;
temp = readl(port_array[wIndex]);
- if (temp == 0xffffffff) {
+ if (temp == ~(u32)0) {
+ xhci_hc_died(xhci);
retval = -ENODEV;
break;
}
@@ -1092,18 +1208,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
* However, hub_wq will ignore the roothub events until
* the roothub is registered.
*/
- writel(temp | PORT_POWER, port_array[wIndex]);
-
- temp = readl(port_array[wIndex]);
- xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp);
-
- spin_unlock_irqrestore(&xhci->lock, flags);
- temp = usb_acpi_power_manageable(hcd->self.root_hub,
- wIndex);
- if (temp)
- usb_acpi_set_power_state(hcd->self.root_hub,
- wIndex, true);
- spin_lock_irqsave(&xhci->lock, flags);
+ xhci_set_port_power(xhci, hcd, wIndex, true, &flags);
break;
case USB_PORT_FEAT_RESET:
temp = (temp | PORT_RESET);
@@ -1142,6 +1247,15 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp |= PORT_U2_TIMEOUT(timeout);
writel(temp, port_array[wIndex] + PORTPMSC);
break;
+ case USB_PORT_FEAT_TEST:
+ /* 4.19.6 Port Test Modes (USB2 Test Mode) */
+ if (hcd->speed != HCD_USB2)
+ goto error;
+ if (test_mode > TEST_FORCE_EN || test_mode < TEST_J)
+ goto error;
+ retval = xhci_enter_test_mode(xhci, test_mode, wIndex,
+ &flags);
+ break;
default:
goto error;
}
@@ -1153,7 +1267,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
goto error;
wIndex--;
temp = readl(port_array[wIndex]);
- if (temp == 0xffffffff) {
+ if (temp == ~(u32)0) {
+ xhci_hc_died(xhci);
retval = -ENODEV;
break;
}
@@ -1207,15 +1322,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
port_array[wIndex], temp);
break;
case USB_PORT_FEAT_POWER:
- writel(temp & ~PORT_POWER, port_array[wIndex]);
-
- spin_unlock_irqrestore(&xhci->lock, flags);
- temp = usb_acpi_power_manageable(hcd->self.root_hub,
- wIndex);
- if (temp)
- usb_acpi_set_power_state(hcd->self.root_hub,
- wIndex, false);
- spin_lock_irqsave(&xhci->lock, flags);
+ xhci_set_port_power(xhci, hcd, wIndex, false, &flags);
+ break;
+ case USB_PORT_FEAT_TEST:
+ retval = xhci_exit_test_mode(xhci);
break;
default:
goto error;
@@ -1269,7 +1379,8 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
/* For each port, did anything change? If so, set that bit in buf. */
for (i = 0; i < max_ports; i++) {
temp = readl(port_array[i]);
- if (temp == 0xffffffff) {
+ if (temp == ~(u32)0) {
+ xhci_hc_died(xhci);
retval = -ENODEV;
break;
}
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index ba1853f4e407..bbe22bcc550a 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -288,6 +288,8 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
if (!ring)
return;
+ trace_xhci_ring_free(ring);
+
if (ring->first_seg) {
if (ring->type == TYPE_STREAM)
xhci_remove_stream_mapping(ring);
@@ -313,9 +315,6 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring,
* handling ring expansion, set the cycle state equal to the old ring.
*/
ring->cycle_state = cycle_state;
- /* Not necessary for new rings, but needed for re-initialized rings */
- ring->enq_updates = 0;
- ring->deq_updates = 0;
/*
* Each segment has a link TRB, and leave an extra TRB for SW
@@ -400,6 +399,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
cpu_to_le32(LINK_TOGGLE);
}
xhci_initialize_ring_info(ring, cycle_state);
+ trace_xhci_ring_alloc(ring);
return ring;
fail:
@@ -504,6 +504,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
}
xhci_link_rings(xhci, ring, first, last, num_segs);
+ trace_xhci_ring_expansion(ring);
xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion,
"ring expansion succeed, now has %d segments",
ring->num_segs);
@@ -586,7 +587,7 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci,
unsigned int num_stream_ctxs,
struct xhci_stream_ctx *stream_ctx, dma_addr_t dma)
{
- struct device *dev = xhci_to_hcd(xhci)->self.controller;
+ struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs;
if (size > MEDIUM_STREAM_ARRAY_SIZE)
@@ -614,7 +615,7 @@ static struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci,
unsigned int num_stream_ctxs, dma_addr_t *dma,
gfp_t mem_flags)
{
- struct device *dev = xhci_to_hcd(xhci)->self.controller;
+ struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs;
if (size > MEDIUM_STREAM_ARRAY_SIZE)
@@ -1502,6 +1503,17 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
*/
max_esit_payload = xhci_get_max_esit_payload(udev, ep);
interval = xhci_get_endpoint_interval(udev, ep);
+
+ /* Periodic endpoint bInterval limit quirk */
+ if (usb_endpoint_xfer_int(&ep->desc) ||
+ usb_endpoint_xfer_isoc(&ep->desc)) {
+ if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_7) &&
+ udev->speed >= USB_SPEED_HIGH &&
+ interval >= 7) {
+ interval = 6;
+ }
+ }
+
mult = xhci_get_endpoint_mult(udev, ep);
max_packet = usb_endpoint_maxp(&ep->desc);
max_burst = xhci_get_endpoint_max_burst(udev, ep);
@@ -1686,7 +1698,7 @@ void xhci_slot_copy(struct xhci_hcd *xhci,
static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
{
int i;
- struct device *dev = xhci_to_hcd(xhci)->self.controller;
+ struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2);
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
@@ -1709,36 +1721,27 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
if (!xhci->scratchpad->sp_buffers)
goto fail_sp3;
- xhci->scratchpad->sp_dma_buffers =
- kzalloc(sizeof(dma_addr_t) * num_sp, flags);
-
- if (!xhci->scratchpad->sp_dma_buffers)
- goto fail_sp4;
-
xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma);
for (i = 0; i < num_sp; i++) {
dma_addr_t dma;
void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma,
flags);
if (!buf)
- goto fail_sp5;
+ goto fail_sp4;
xhci->scratchpad->sp_array[i] = dma;
xhci->scratchpad->sp_buffers[i] = buf;
- xhci->scratchpad->sp_dma_buffers[i] = dma;
}
return 0;
- fail_sp5:
+ fail_sp4:
for (i = i - 1; i >= 0; i--) {
dma_free_coherent(dev, xhci->page_size,
xhci->scratchpad->sp_buffers[i],
- xhci->scratchpad->sp_dma_buffers[i]);
+ xhci->scratchpad->sp_array[i]);
}
- kfree(xhci->scratchpad->sp_dma_buffers);
- fail_sp4:
kfree(xhci->scratchpad->sp_buffers);
fail_sp3:
@@ -1758,7 +1761,7 @@ static void scratchpad_free(struct xhci_hcd *xhci)
{
int num_sp;
int i;
- struct device *dev = xhci_to_hcd(xhci)->self.controller;
+ struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
if (!xhci->scratchpad)
return;
@@ -1768,9 +1771,8 @@ static void scratchpad_free(struct xhci_hcd *xhci)
for (i = 0; i < num_sp; i++) {
dma_free_coherent(dev, xhci->page_size,
xhci->scratchpad->sp_buffers[i],
- xhci->scratchpad->sp_dma_buffers[i]);
+ xhci->scratchpad->sp_array[i]);
}
- kfree(xhci->scratchpad->sp_dma_buffers);
kfree(xhci->scratchpad->sp_buffers);
dma_free_coherent(dev, num_sp * sizeof(u64),
xhci->scratchpad->sp_array,
@@ -1831,7 +1833,7 @@ void xhci_free_command(struct xhci_hcd *xhci,
void xhci_mem_cleanup(struct xhci_hcd *xhci)
{
- struct device *dev = xhci_to_hcd(xhci)->self.controller;
+ struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
int size;
int i, j, num_ports;
@@ -2373,7 +2375,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
{
dma_addr_t dma;
- struct device *dev = xhci_to_hcd(xhci)->self.controller;
+ struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
unsigned int val, val2;
u64 val_64;
struct xhci_segment *seg;
@@ -2419,7 +2421,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
writel(val, &xhci->op_regs->config_reg);
/*
- * Section 5.4.8 - doorbell array must be
+ * xHCI section 5.4.6 - doorbell array must be
* "physically contiguous and 64-byte (cache line) aligned".
*/
xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma,
@@ -2480,7 +2482,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
(xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
xhci->cmd_ring->cycle_state;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "// Setting command ring address to 0x%x", val);
+ "// Setting command ring address to 0x%016llx", val_64);
xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
xhci_dbg_cmd_ptrs(xhci);
@@ -2601,7 +2603,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
return 0;
fail:
- xhci_warn(xhci, "Couldn't initialize memory\n");
xhci_halt(xhci);
xhci_reset(xhci);
xhci_mem_cleanup(xhci);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index fc99f51d12e1..7b86508ac8cf 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -199,6 +199,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == 0x1042)
xhci->quirks |= XHCI_BROKEN_STREAMS;
+ if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
+ xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
+
if (xhci->quirks & XHCI_RESET_ON_RESUME)
xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
"QUIRK: Resetting on resume");
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 6ed468fa7d5e..7c2a9e7c8e0f 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -14,6 +14,7 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
+#include <linux/pci.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/usb/phy.h>
@@ -54,6 +55,16 @@ static int xhci_priv_init_quirk(struct usb_hcd *hcd)
return priv->init_quirk(hcd);
}
+static int xhci_priv_resume_quirk(struct usb_hcd *hcd)
+{
+ struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
+
+ if (!priv->resume_quirk)
+ return 0;
+
+ return priv->resume_quirk(hcd);
+}
+
static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
{
/*
@@ -92,18 +103,21 @@ static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = {
.firmware_name = XHCI_RCAR_FIRMWARE_NAME_V1,
.init_quirk = xhci_rcar_init_quirk,
.plat_start = xhci_rcar_start,
+ .resume_quirk = xhci_rcar_resume_quirk,
};
static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = {
.firmware_name = XHCI_RCAR_FIRMWARE_NAME_V2,
.init_quirk = xhci_rcar_init_quirk,
.plat_start = xhci_rcar_start,
+ .resume_quirk = xhci_rcar_resume_quirk,
};
static const struct xhci_plat_priv xhci_plat_renesas_rcar_r8a7796 = {
.firmware_name = XHCI_RCAR_FIRMWARE_NAME_V3,
.init_quirk = xhci_rcar_init_quirk,
.plat_start = xhci_rcar_start,
+ .resume_quirk = xhci_rcar_resume_quirk,
};
static const struct of_device_id usb_xhci_of_match[] = {
@@ -148,6 +162,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
const struct hc_driver *driver;
+ struct device *sysdev;
struct xhci_hcd *xhci;
struct resource *res;
struct usb_hcd *hcd;
@@ -164,24 +179,47 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (irq < 0)
return -ENODEV;
+ /*
+ * sysdev must point to a device that is known to the system firmware
+ * or PCI hardware. We handle these three cases here:
+ * 1. xhci_plat comes from firmware
+ * 2. xhci_plat is child of a device from firmware (dwc3-plat)
+ * 3. xhci_plat is grandchild of a pci device (dwc3-pci)
+ */
+ sysdev = &pdev->dev;
+ if (sysdev->parent && !sysdev->of_node && sysdev->parent->of_node)
+ sysdev = sysdev->parent;
+#ifdef CONFIG_PCI
+ else if (sysdev->parent && sysdev->parent->parent &&
+ sysdev->parent->parent->bus == &pci_bus_type)
+ sysdev = sysdev->parent->parent;
+#endif
+
/* Try to set 64-bit DMA first */
- if (!pdev->dev.dma_mask)
+ if (WARN_ON(!sysdev->dma_mask))
/* Platform did not initialize dma_mask */
- ret = dma_coerce_mask_and_coherent(&pdev->dev,
+ ret = dma_coerce_mask_and_coherent(sysdev,
DMA_BIT_MASK(64));
else
- ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(64));
/* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
if (ret) {
- ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(32));
if (ret)
return ret;
}
- hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
- if (!hcd)
- return -ENOMEM;
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_noresume(&pdev->dev);
+
+ hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
+ dev_name(&pdev->dev), NULL);
+ if (!hcd) {
+ ret = -ENOMEM;
+ goto disable_runtime;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hcd->regs = devm_ioremap_resource(&pdev->dev, res);
@@ -222,20 +260,20 @@ static int xhci_plat_probe(struct platform_device *pdev)
xhci->clk = clk;
xhci->main_hcd = hcd;
- xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev,
+ xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
dev_name(&pdev->dev), hcd);
if (!xhci->shared_hcd) {
ret = -ENOMEM;
goto disable_clk;
}
- if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
+ if (device_property_read_bool(sysdev, "usb3-lpm-capable"))
xhci->quirks |= XHCI_LPM_SUPPORT;
if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped"))
xhci->quirks |= XHCI_BROKEN_PORT_PED;
- hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
+ hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
if (IS_ERR(hcd->usb_phy)) {
ret = PTR_ERR(hcd->usb_phy);
if (ret == -EPROBE_DEFER)
@@ -258,6 +296,15 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (ret)
goto dealloc_usb2_hcd;
+ device_enable_async_suspend(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ /*
+ * Prevent runtime pm from being on as default, users should enable
+ * runtime pm using power/control in sysfs.
+ */
+ pm_runtime_forbid(&pdev->dev);
+
return 0;
@@ -277,6 +324,10 @@ disable_clk:
put_hcd:
usb_put_hcd(hcd);
+disable_runtime:
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
return ret;
}
@@ -298,14 +349,17 @@ static int xhci_plat_remove(struct platform_device *dev)
clk_disable_unprepare(clk);
usb_put_hcd(hcd);
+ pm_runtime_set_suspended(&dev->dev);
+ pm_runtime_disable(&dev->dev);
+
return 0;
}
-#ifdef CONFIG_PM_SLEEP
-static int xhci_plat_suspend(struct device *dev)
+static int __maybe_unused xhci_plat_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ int ret;
/*
* xhci_suspend() needs `do_wakeup` to know whether host is allowed
@@ -315,24 +369,53 @@ static int xhci_plat_suspend(struct device *dev)
* reconsider this when xhci_plat_suspend enlarges its scope, e.g.,
* also applies to runtime suspend.
*/
- return xhci_suspend(xhci, device_may_wakeup(dev));
+ ret = xhci_suspend(xhci, device_may_wakeup(dev));
+
+ if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk))
+ clk_disable_unprepare(xhci->clk);
+
+ return ret;
}
-static int xhci_plat_resume(struct device *dev)
+static int __maybe_unused xhci_plat_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ int ret;
+
+ if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk))
+ clk_prepare_enable(xhci->clk);
+
+ ret = xhci_priv_resume_quirk(hcd);
+ if (ret)
+ return ret;
+
+ return xhci_resume(xhci, 0);
+}
+
+static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+ return xhci_suspend(xhci, true);
+}
+
+static int __maybe_unused xhci_plat_runtime_resume(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
return xhci_resume(xhci, 0);
}
static const struct dev_pm_ops xhci_plat_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume)
+
+ SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend,
+ xhci_plat_runtime_resume,
+ NULL)
};
-#define DEV_PM_OPS (&xhci_plat_pm_ops)
-#else
-#define DEV_PM_OPS NULL
-#endif /* CONFIG_PM */
static const struct acpi_device_id usb_xhci_acpi_match[] = {
/* XHCI-compliant USB Controller */
@@ -347,7 +430,7 @@ static struct platform_driver usb_xhci_driver = {
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "xhci-hcd",
- .pm = DEV_PM_OPS,
+ .pm = &xhci_plat_pm_ops,
.of_match_table = of_match_ptr(usb_xhci_of_match),
.acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
},
diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h
index 9af0cb48053f..29b227895b07 100644
--- a/drivers/usb/host/xhci-plat.h
+++ b/drivers/usb/host/xhci-plat.h
@@ -17,6 +17,7 @@ struct xhci_plat_priv {
const char *firmware_name;
void (*plat_start)(struct usb_hcd *);
int (*init_quirk)(struct usb_hcd *);
+ int (*resume_quirk)(struct usb_hcd *);
};
#define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv)
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index d28df386e780..07278228214b 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -198,3 +198,14 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd)
return xhci_rcar_download_firmware(hcd);
}
+
+int xhci_rcar_resume_quirk(struct usb_hcd *hcd)
+{
+ int ret;
+
+ ret = xhci_rcar_download_firmware(hcd);
+ if (!ret)
+ xhci_rcar_start(hcd);
+
+ return ret;
+}
diff --git a/drivers/usb/host/xhci-rcar.h b/drivers/usb/host/xhci-rcar.h
index d2ffe20401cf..d247951147a1 100644
--- a/drivers/usb/host/xhci-rcar.h
+++ b/drivers/usb/host/xhci-rcar.h
@@ -18,6 +18,7 @@
#if IS_ENABLED(CONFIG_USB_XHCI_RCAR)
void xhci_rcar_start(struct usb_hcd *hcd);
int xhci_rcar_init_quirk(struct usb_hcd *hcd);
+int xhci_rcar_resume_quirk(struct usb_hcd *hcd);
#else
static inline void xhci_rcar_start(struct usb_hcd *hcd)
{
@@ -27,5 +28,10 @@ static inline int xhci_rcar_init_quirk(struct usb_hcd *hcd)
{
return 0;
}
+
+static inline int xhci_rcar_resume_quirk(struct usb_hcd *hcd)
+{
+ return 0;
+}
#endif
#endif /* _XHCI_RCAR_H */
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index a3309aa02993..74bf5c60a260 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -167,8 +167,6 @@ static void next_trb(struct xhci_hcd *xhci,
*/
static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
{
- ring->deq_updates++;
-
/* event ring doesn't have link trbs, check for last trb */
if (ring->type == TYPE_EVENT) {
if (!last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
@@ -191,6 +189,9 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
ring->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs;
}
+
+ trace_xhci_inc_deq(ring);
+
return;
}
@@ -223,7 +224,6 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
ring->num_trbs_free--;
next = ++(ring->enqueue);
- ring->enq_updates++;
/* Update the dequeue pointer further if that was a link TRB */
while (trb_is_link(next)) {
@@ -259,6 +259,8 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
ring->enqueue = ring->enq_seg->trbs;
next = ring->enqueue;
}
+
+ trace_xhci_inc_enq(ring);
}
/*
@@ -359,21 +361,19 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
&xhci->op_regs->cmd_ring);
- /* Section 4.6.1.2 of xHCI 1.0 spec says software should
- * time the completion od all xHCI commands, including
- * the Command Abort operation. If software doesn't see
- * CRR negated in a timely manner (e.g. longer than 5
- * seconds), then it should assume that the there are
- * larger problems with the xHC and assert HCRST.
+ /* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the
+ * completion of the Command Abort operation. If CRR is not negated in 5
+ * seconds then driver handles it as if host died (-ENODEV).
+ * In the future we should distinguish between -ENODEV and -ETIMEDOUT
+ * and try to recover a -ETIMEDOUT with a host controller reset.
*/
ret = xhci_handshake(&xhci->op_regs->cmd_ring,
CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
if (ret < 0) {
- xhci_err(xhci,
- "Stop command ring failed, maybe the host is dead\n");
- xhci->xhc_state |= XHCI_STATE_DYING;
+ xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret);
xhci_halt(xhci);
- return -ESHUTDOWN;
+ xhci_hc_died(xhci);
+ return ret;
}
/*
* Writing the CMD_RING_ABORT bit should cause a cmd completion event,
@@ -689,6 +689,8 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
struct xhci_virt_ep *ep;
struct xhci_td *cur_td = NULL;
struct xhci_td *last_unlinked_td;
+ struct xhci_ep_ctx *ep_ctx;
+ struct xhci_virt_device *vdev;
struct xhci_dequeue_state deq_state;
@@ -702,6 +704,11 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
memset(&deq_state, 0, sizeof(deq_state));
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
+
+ vdev = xhci->devs[slot_id];
+ ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
+ trace_xhci_handle_cmd_stop_ep(ep_ctx);
+
ep = &xhci->devs[slot_id]->eps[ep_index];
last_unlinked_td = list_last_entry(&ep->cancelled_td_list,
struct xhci_td, cancelled_td_list);
@@ -866,6 +873,40 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
}
}
+/*
+ * host controller died, register read returns 0xffffffff
+ * Complete pending commands, mark them ABORTED.
+ * URBs need to be given back as usb core might be waiting with device locks
+ * held for the URBs to finish during device disconnect, blocking host remove.
+ *
+ * Call with xhci->lock held.
+ * lock is relased and re-acquired while giving back urb.
+ */
+void xhci_hc_died(struct xhci_hcd *xhci)
+{
+ int i, j;
+
+ if (xhci->xhc_state & XHCI_STATE_DYING)
+ return;
+
+ xhci_err(xhci, "xHCI host controller not responding, assume dead\n");
+ xhci->xhc_state |= XHCI_STATE_DYING;
+
+ xhci_cleanup_command_queue(xhci);
+
+ /* return any pending urbs, remove may be waiting for them */
+ for (i = 0; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
+ if (!xhci->devs[i])
+ continue;
+ for (j = 0; j < 31; j++)
+ xhci_kill_endpoint_urbs(xhci, i, j);
+ }
+
+ /* inform usb core hc died if PCI remove isn't already handling it */
+ if (!(xhci->xhc_state & XHCI_STATE_REMOVING))
+ 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
@@ -887,7 +928,6 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
{
struct xhci_hcd *xhci;
struct xhci_virt_ep *ep;
- int ret, i, j;
unsigned long flags;
ep = (struct xhci_virt_ep *) arg;
@@ -904,52 +944,22 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
}
xhci_warn(xhci, "xHCI host not responding to stop endpoint command.\n");
- xhci_warn(xhci, "Assuming host is dying, halting host.\n");
- /* Oops, HC is dead or dying or at least not responding to the stop
- * endpoint command.
- */
-
- xhci->xhc_state |= XHCI_STATE_DYING;
ep->ep_state &= ~EP_STOP_CMD_PENDING;
- /* Disable interrupts from the host controller and start halting it */
- xhci_quiesce(xhci);
- spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_halt(xhci);
- ret = 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_lock_irqsave(&xhci->lock, flags);
- if (ret < 0) {
- /* This is bad; the host is not responding to commands and it's
- * not allowing itself to be halted. At least interrupts are
- * disabled. If we call usb_hc_died(), it will attempt to
- * disconnect all device drivers under this host. Those
- * disconnect() methods will wait for all URBs to be unlinked,
- * so we must complete them.
- */
- xhci_warn(xhci, "Non-responsive xHCI host is not halting.\n");
- xhci_warn(xhci, "Completing active URBs anyway.\n");
- /* We could turn all TDs on the rings to no-ops. This won't
- * help if the host has cached part of the ring, and is slow if
- * we want to preserve the cycle bit. Skip it and hope the host
- * doesn't touch the memory.
- */
- }
- for (i = 0; i < MAX_HC_SLOTS; i++) {
- if (!xhci->devs[i])
- continue;
- for (j = 0; j < 31; j++)
- xhci_kill_endpoint_urbs(xhci, i, j);
- }
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
- "Calling usb_hc_died()");
- usb_hc_died(xhci_to_hcd(xhci));
- 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,
@@ -1029,6 +1039,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
+ trace_xhci_handle_cmd_set_deq(slot_ctx);
+ trace_xhci_handle_cmd_set_deq_ep(ep_ctx);
if (cmd_comp_code != COMP_SUCCESS) {
unsigned int ep_state;
@@ -1099,9 +1111,15 @@ cleanup:
static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
union xhci_trb *trb, u32 cmd_comp_code)
{
+ struct xhci_virt_device *vdev;
+ struct xhci_ep_ctx *ep_ctx;
unsigned int ep_index;
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
+ vdev = xhci->devs[slot_id];
+ ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
+ trace_xhci_handle_cmd_reset_ep(ep_ctx);
+
/* This command will only fail if the endpoint wasn't halted,
* but we don't care.
*/
@@ -1114,11 +1132,11 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
*/
if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
struct xhci_command *command;
+
command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
- if (!command) {
- xhci_warn(xhci, "WARN Cannot submit cfg ep: ENOMEM\n");
+ if (!command)
return;
- }
+
xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
"Queueing configure endpoint command");
xhci_queue_configure_endpoint(xhci, command,
@@ -1143,10 +1161,15 @@ static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id,
static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id)
{
struct xhci_virt_device *virt_dev;
+ struct xhci_slot_ctx *slot_ctx;
virt_dev = xhci->devs[slot_id];
if (!virt_dev)
return;
+
+ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
+ trace_xhci_handle_cmd_disable_slot(slot_ctx);
+
if (xhci->quirks & XHCI_EP_LIMIT_QUIRK)
/* Delete default control endpoint resources */
xhci_free_device_endpoint_resources(xhci, virt_dev, true);
@@ -1158,6 +1181,7 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
{
struct xhci_virt_device *virt_dev;
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;
@@ -1182,6 +1206,9 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
/* 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
@@ -1206,9 +1233,26 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
return;
}
+static void xhci_handle_cmd_addr_dev(struct xhci_hcd *xhci, int slot_id)
+{
+ struct xhci_virt_device *vdev;
+ struct xhci_slot_ctx *slot_ctx;
+
+ vdev = xhci->devs[slot_id];
+ slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx);
+ trace_xhci_handle_cmd_addr_dev(slot_ctx);
+}
+
static void xhci_handle_cmd_reset_dev(struct xhci_hcd *xhci, int slot_id,
struct xhci_event_cmd *event)
{
+ struct xhci_virt_device *vdev;
+ struct xhci_slot_ctx *slot_ctx;
+
+ vdev = xhci->devs[slot_id];
+ slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx);
+ trace_xhci_handle_cmd_reset_dev(slot_ctx);
+
xhci_dbg(xhci, "Completed reset device command.\n");
if (!xhci->devs[slot_id])
xhci_warn(xhci, "Reset device command completion "
@@ -1250,7 +1294,6 @@ void xhci_cleanup_command_queue(struct xhci_hcd *xhci)
void xhci_handle_command_timeout(struct work_struct *work)
{
struct xhci_hcd *xhci;
- int ret;
unsigned long flags;
u64 hw_ring_state;
@@ -1271,22 +1314,17 @@ void xhci_handle_command_timeout(struct work_struct *work)
/* Make sure command ring is running before aborting it */
hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+ if (hw_ring_state == ~(u64)0) {
+ xhci_hc_died(xhci);
+ goto time_out_completed;
+ }
+
if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
(hw_ring_state & CMD_RING_RUNNING)) {
/* Prevent new doorbell, and start command abort */
xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
xhci_dbg(xhci, "Command timeout\n");
- ret = xhci_abort_cmd_ring(xhci, flags);
- if (unlikely(ret == -ESHUTDOWN)) {
- xhci_err(xhci, "Abort command ring failed\n");
- xhci_cleanup_command_queue(xhci);
- spin_unlock_irqrestore(&xhci->lock, flags);
- usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
- xhci_dbg(xhci, "xHCI host controller is dead.\n");
-
- return;
- }
-
+ xhci_abort_cmd_ring(xhci, flags);
goto time_out_completed;
}
@@ -1384,6 +1422,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
case TRB_EVAL_CONTEXT:
break;
case TRB_ADDR_DEV:
+ xhci_handle_cmd_addr_dev(xhci, slot_id);
break;
case TRB_STOP_RING:
WARN_ON(slot_id != TRB_TO_SLOT_ID(
@@ -2243,7 +2282,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
xdev = xhci->devs[slot_id];
if (!xdev) {
- xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
+ xhci_err(xhci, "ERROR Transfer event pointed to bad slot %u\n",
+ slot_id);
xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
(unsigned long long) xhci_trb_virt_to_dma(
xhci->event_ring->deq_seg,
@@ -2252,8 +2292,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
upper_32_bits(le64_to_cpu(event->buffer)),
le32_to_cpu(event->transfer_len),
le32_to_cpu(event->flags));
- xhci_dbg(xhci, "Event ring:\n");
- xhci_debug_segment(xhci, xhci->event_ring->deq_seg);
return -ENODEV;
}
@@ -2263,8 +2301,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
if (!ep_ring || GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) {
- xhci_err(xhci, "ERROR Transfer event for disabled endpoint "
- "or incorrect stream ring\n");
+ xhci_err(xhci,
+ "ERROR Transfer event for disabled endpoint slot %u ep %u or incorrect stream ring\n",
+ slot_id, ep_index);
xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
(unsigned long long) xhci_trb_virt_to_dma(
xhci->event_ring->deq_seg,
@@ -2273,8 +2312,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
upper_32_bits(le64_to_cpu(event->buffer)),
le32_to_cpu(event->transfer_len),
le32_to_cpu(event->flags));
- xhci_dbg(xhci, "Event ring:\n");
- xhci_debug_segment(xhci, xhci->event_ring->deq_seg);
return -ENODEV;
}
@@ -2298,45 +2335,62 @@ static int handle_tx_event(struct xhci_hcd *xhci,
trb_comp_code = COMP_SHORT_PACKET;
else
xhci_warn_ratelimited(xhci,
- "WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n");
+ "WARN Successful completion on short TX for slot %u ep %u: needs XHCI_TRUST_TX_LENGTH quirk?\n",
+ slot_id, ep_index);
case COMP_SHORT_PACKET:
break;
case COMP_STOPPED:
- xhci_dbg(xhci, "Stopped on Transfer TRB\n");
+ xhci_dbg(xhci, "Stopped on Transfer TRB for slot %u ep %u\n",
+ slot_id, ep_index);
break;
case COMP_STOPPED_LENGTH_INVALID:
- xhci_dbg(xhci, "Stopped on No-op or Link TRB\n");
+ xhci_dbg(xhci,
+ "Stopped on No-op or Link TRB for slot %u ep %u\n",
+ slot_id, ep_index);
break;
case COMP_STOPPED_SHORT_PACKET:
- xhci_dbg(xhci, "Stopped with short packet transfer detected\n");
+ xhci_dbg(xhci,
+ "Stopped with short packet transfer detected for slot %u ep %u\n",
+ slot_id, ep_index);
break;
case COMP_STALL_ERROR:
- xhci_dbg(xhci, "Stalled endpoint\n");
+ xhci_dbg(xhci, "Stalled endpoint for slot %u ep %u\n", slot_id,
+ ep_index);
ep->ep_state |= EP_HALTED;
status = -EPIPE;
break;
case COMP_TRB_ERROR:
- xhci_warn(xhci, "WARN: TRB error on endpoint\n");
+ xhci_warn(xhci,
+ "WARN: TRB error for slot %u ep %u on endpoint\n",
+ slot_id, ep_index);
status = -EILSEQ;
break;
case COMP_SPLIT_TRANSACTION_ERROR:
case COMP_USB_TRANSACTION_ERROR:
- xhci_dbg(xhci, "Transfer error on endpoint\n");
+ xhci_dbg(xhci, "Transfer error for slot %u ep %u on endpoint\n",
+ slot_id, ep_index);
status = -EPROTO;
break;
case COMP_BABBLE_DETECTED_ERROR:
- xhci_dbg(xhci, "Babble error on endpoint\n");
+ xhci_dbg(xhci, "Babble error for slot %u ep %u on endpoint\n",
+ slot_id, ep_index);
status = -EOVERFLOW;
break;
case COMP_DATA_BUFFER_ERROR:
- xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n");
+ xhci_warn(xhci,
+ "WARN: HC couldn't access mem fast enough for slot %u ep %u\n",
+ slot_id, ep_index);
status = -ENOSR;
break;
case COMP_BANDWIDTH_OVERRUN_ERROR:
- xhci_warn(xhci, "WARN: bandwidth overrun event on endpoint\n");
+ xhci_warn(xhci,
+ "WARN: bandwidth overrun event for slot %u ep %u on endpoint\n",
+ slot_id, ep_index);
break;
case COMP_ISOCH_BUFFER_OVERRUN:
- xhci_warn(xhci, "WARN: buffer overrun event on endpoint\n");
+ xhci_warn(xhci,
+ "WARN: buffer overrun event for slot %u ep %u on endpoint",
+ slot_id, ep_index);
break;
case COMP_RING_UNDERRUN:
/*
@@ -2360,7 +2414,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep_index);
goto cleanup;
case COMP_INCOMPATIBLE_DEVICE_ERROR:
- xhci_warn(xhci, "WARN: detect an incompatible device");
+ xhci_warn(xhci,
+ "WARN: detect an incompatible device for slot %u ep %u",
+ slot_id, ep_index);
status = -EPROTO;
break;
case COMP_MISSED_SERVICE_ERROR:
@@ -2371,19 +2427,24 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* short transfer when process the ep_ring next time.
*/
ep->skip = true;
- xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
+ xhci_dbg(xhci,
+ "Miss service interval error for slot %u ep %u, set skip flag\n",
+ slot_id, ep_index);
goto cleanup;
case COMP_NO_PING_RESPONSE_ERROR:
ep->skip = true;
- xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
+ xhci_dbg(xhci,
+ "No Ping response error for slot %u ep %u, Skip one Isoc TD\n",
+ slot_id, ep_index);
goto cleanup;
default:
if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
status = 0;
break;
}
- xhci_warn(xhci, "ERROR Unknown event condition %u, HC probably busted\n",
- trb_comp_code);
+ xhci_warn(xhci,
+ "ERROR Unknown event condition %u for slot %u ep %u , HC probably busted\n",
+ trb_comp_code, slot_id, ep_index);
goto cleanup;
}
@@ -2402,15 +2463,11 @@ static int handle_tx_event(struct xhci_hcd *xhci,
xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
ep_index);
- xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
- (le32_to_cpu(event->flags) &
- TRB_TYPE_BITMASK)>>10);
- xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
}
if (ep->skip) {
ep->skip = false;
- xhci_dbg(xhci, "td_list is empty while skip "
- "flag set. Clear skip flag.\n");
+ xhci_dbg(xhci, "td_list is empty while skip flag set. Clear skip flag for slot %u ep %u.\n",
+ slot_id, ep_index);
}
goto cleanup;
}
@@ -2418,8 +2475,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
/* We've skipped all the TDs on the ep ring when ep->skip set */
if (ep->skip && td_num == 0) {
ep->skip = false;
- xhci_dbg(xhci, "All tds on the ep_ring skipped. "
- "Clear skip flag.\n");
+ xhci_dbg(xhci, "All tds on the ep_ring skipped. Clear skip flag for slot %u ep %u.\n",
+ slot_id, ep_index);
goto cleanup;
}
@@ -2478,7 +2535,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep_ring->last_td_was_short = false;
if (ep->skip) {
- xhci_dbg(xhci, "Found td. Clear skip flag.\n");
+ xhci_dbg(xhci,
+ "Found td. Clear skip flag for slot %u ep %u.\n",
+ slot_id, ep_index);
ep->skip = false;
}
@@ -2495,7 +2554,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* the TD.
*/
if (trb_is_noop(ep_trb)) {
- xhci_dbg(xhci, "ep_trb is a no-op TRB. Skip it\n");
+ xhci_dbg(xhci,
+ "ep_trb is a no-op TRB. Skip it for slot %u ep %u\n",
+ slot_id, ep_index);
goto cleanup;
}
@@ -2623,7 +2684,8 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
spin_lock(&xhci->lock);
/* Check if the xHC generated the interrupt, or the irq is shared */
status = readl(&xhci->op_regs->status);
- if (status == 0xffffffff) {
+ if (status == ~(u32)0) {
+ xhci_hc_died(xhci);
ret = IRQ_HANDLED;
goto out;
}
@@ -3942,10 +4004,8 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
/* This function gets called from contexts where it cannot sleep */
cmd = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
- if (!cmd) {
- xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr: ENOMEM\n");
+ if (!cmd)
return;
- }
ep->queued_deq_seg = deq_state->new_deq_seg;
ep->queued_deq_ptr = deq_state->new_deq_ptr;
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 1ac2cdf8eece..8ce96de10e8a 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -231,6 +231,7 @@ DECLARE_EVENT_CLASS(xhci_log_urb,
__field(int, epnum)
__field(int, dir_in)
__field(int, type)
+ __field(int, slot_id)
),
TP_fast_assign(
__entry->urb = urb;
@@ -245,8 +246,9 @@ DECLARE_EVENT_CLASS(xhci_log_urb,
__entry->epnum = usb_endpoint_num(&urb->ep->desc);
__entry->dir_in = usb_endpoint_dir_in(&urb->ep->desc);
__entry->type = usb_endpoint_type(&urb->ep->desc);
+ __entry->slot_id = urb->dev->slot_id;
),
- TP_printk("ep%d%s-%s: urb %p pipe %u length %d/%d sgs %d/%d stream %d flags %08x",
+ TP_printk("ep%d%s-%s: urb %p pipe %u slot %d length %d/%d sgs %d/%d stream %d flags %08x",
__entry->epnum, __entry->dir_in ? "in" : "out",
({ char *s;
switch (__entry->type) {
@@ -264,8 +266,8 @@ DECLARE_EVENT_CLASS(xhci_log_urb,
break;
default:
s = "UNKNOWN";
- } s; }), __entry->urb, __entry->pipe, __entry->actual,
- __entry->length, __entry->num_mapped_sgs,
+ } s; }), __entry->urb, __entry->pipe, __entry->slot_id,
+ __entry->actual, __entry->length, __entry->num_mapped_sgs,
__entry->num_sgs, __entry->stream, __entry->flags
)
);
@@ -285,6 +287,172 @@ DEFINE_EVENT(xhci_log_urb, xhci_urb_dequeue,
TP_ARGS(urb)
);
+DECLARE_EVENT_CLASS(xhci_log_ep_ctx,
+ TP_PROTO(struct xhci_ep_ctx *ctx),
+ TP_ARGS(ctx),
+ TP_STRUCT__entry(
+ __field(u32, info)
+ __field(u32, info2)
+ __field(u64, deq)
+ __field(u32, tx_info)
+ ),
+ TP_fast_assign(
+ __entry->info = le32_to_cpu(ctx->ep_info);
+ __entry->info2 = le32_to_cpu(ctx->ep_info2);
+ __entry->deq = le64_to_cpu(ctx->deq);
+ __entry->tx_info = le32_to_cpu(ctx->tx_info);
+ ),
+ TP_printk("%s", xhci_decode_ep_context(__entry->info,
+ __entry->info2, __entry->deq, __entry->tx_info)
+ )
+);
+
+DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_stop_ep,
+ TP_PROTO(struct xhci_ep_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_set_deq_ep,
+ TP_PROTO(struct xhci_ep_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_reset_ep,
+ TP_PROTO(struct xhci_ep_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_config_ep,
+ TP_PROTO(struct xhci_ep_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DECLARE_EVENT_CLASS(xhci_log_slot_ctx,
+ TP_PROTO(struct xhci_slot_ctx *ctx),
+ TP_ARGS(ctx),
+ TP_STRUCT__entry(
+ __field(u32, info)
+ __field(u32, info2)
+ __field(u32, tt_info)
+ __field(u32, state)
+ ),
+ TP_fast_assign(
+ __entry->info = le32_to_cpu(ctx->dev_info);
+ __entry->info2 = le32_to_cpu(ctx->dev_info2);
+ __entry->tt_info = le64_to_cpu(ctx->tt_info);
+ __entry->state = le32_to_cpu(ctx->dev_state);
+ ),
+ TP_printk("%s", xhci_decode_slot_context(__entry->info,
+ __entry->info2, __entry->tt_info,
+ __entry->state)
+ )
+);
+
+DEFINE_EVENT(xhci_log_slot_ctx, xhci_alloc_dev,
+ TP_PROTO(struct xhci_slot_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_slot_ctx, xhci_free_dev,
+ TP_PROTO(struct xhci_slot_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_slot_ctx, xhci_handle_cmd_disable_slot,
+ TP_PROTO(struct xhci_slot_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_slot_ctx, xhci_discover_or_reset_device,
+ TP_PROTO(struct xhci_slot_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_slot_ctx, xhci_setup_device_slot,
+ TP_PROTO(struct xhci_slot_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_slot_ctx, xhci_handle_cmd_addr_dev,
+ TP_PROTO(struct xhci_slot_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_slot_ctx, xhci_handle_cmd_reset_dev,
+ TP_PROTO(struct xhci_slot_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DEFINE_EVENT(xhci_log_slot_ctx, xhci_handle_cmd_set_deq,
+ TP_PROTO(struct xhci_slot_ctx *ctx),
+ TP_ARGS(ctx)
+);
+
+DECLARE_EVENT_CLASS(xhci_log_ring,
+ TP_PROTO(struct xhci_ring *ring),
+ TP_ARGS(ring),
+ TP_STRUCT__entry(
+ __field(u32, type)
+ __field(void *, ring)
+ __field(dma_addr_t, enq)
+ __field(dma_addr_t, deq)
+ __field(dma_addr_t, enq_seg)
+ __field(dma_addr_t, deq_seg)
+ __field(unsigned int, num_segs)
+ __field(unsigned int, stream_id)
+ __field(unsigned int, cycle_state)
+ __field(unsigned int, num_trbs_free)
+ __field(unsigned int, bounce_buf_len)
+ ),
+ TP_fast_assign(
+ __entry->ring = ring;
+ __entry->type = ring->type;
+ __entry->num_segs = ring->num_segs;
+ __entry->stream_id = ring->stream_id;
+ __entry->enq_seg = ring->enq_seg->dma;
+ __entry->deq_seg = ring->deq_seg->dma;
+ __entry->cycle_state = ring->cycle_state;
+ __entry->num_trbs_free = ring->num_trbs_free;
+ __entry->bounce_buf_len = ring->bounce_buf_len;
+ __entry->enq = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
+ __entry->deq = xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
+ ),
+ TP_printk("%s %p: enq %pad(%pad) deq %pad(%pad) segs %d stream %d free_trbs %d bounce %d cycle %d",
+ xhci_ring_type_string(__entry->type), __entry->ring,
+ &__entry->enq, &__entry->enq_seg,
+ &__entry->deq, &__entry->deq_seg,
+ __entry->num_segs,
+ __entry->stream_id,
+ __entry->num_trbs_free,
+ __entry->bounce_buf_len,
+ __entry->cycle_state
+ )
+);
+
+DEFINE_EVENT(xhci_log_ring, xhci_ring_alloc,
+ TP_PROTO(struct xhci_ring *ring),
+ TP_ARGS(ring)
+);
+
+DEFINE_EVENT(xhci_log_ring, xhci_ring_free,
+ TP_PROTO(struct xhci_ring *ring),
+ TP_ARGS(ring)
+);
+
+DEFINE_EVENT(xhci_log_ring, xhci_ring_expansion,
+ TP_PROTO(struct xhci_ring *ring),
+ TP_ARGS(ring)
+);
+
+DEFINE_EVENT(xhci_log_ring, xhci_inc_enq,
+ TP_PROTO(struct xhci_ring *ring),
+ TP_ARGS(ring)
+);
+
+DEFINE_EVENT(xhci_log_ring, xhci_inc_deq,
+ TP_PROTO(struct xhci_ring *ring),
+ TP_ARGS(ring)
+);
#endif /* __XHCI_TRACE_H */
/* this part must be outside header guard */
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 953fd8f62df0..2d1310220832 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -125,7 +125,7 @@ int xhci_halt(struct xhci_hcd *xhci)
/*
* Set the run bit and wait for the host to be running.
*/
-static int xhci_start(struct xhci_hcd *xhci)
+int xhci_start(struct xhci_hcd *xhci)
{
u32 temp;
int ret;
@@ -216,31 +216,21 @@ int xhci_reset(struct xhci_hcd *xhci)
return ret;
}
-#ifdef CONFIG_PCI
-static int xhci_free_msi(struct xhci_hcd *xhci)
-{
- int i;
-
- if (!xhci->msix_entries)
- return -EINVAL;
-
- for (i = 0; i < xhci->msix_count; i++)
- if (xhci->msix_entries[i].vector)
- free_irq(xhci->msix_entries[i].vector,
- xhci_to_hcd(xhci));
- return 0;
-}
+#ifdef CONFIG_USB_PCI
/*
* Set up MSI
*/
static int xhci_setup_msi(struct xhci_hcd *xhci)
{
int ret;
+ /*
+ * TODO:Check with MSI Soc for sysdev
+ */
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
- ret = pci_enable_msi(pdev);
- if (ret) {
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
+ if (ret < 0) {
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"failed to allocate MSI entry");
return ret;
@@ -251,35 +241,13 @@ static int xhci_setup_msi(struct xhci_hcd *xhci)
if (ret) {
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"disable MSI interrupt");
- pci_disable_msi(pdev);
+ pci_free_irq_vectors(pdev);
}
return ret;
}
/*
- * Free IRQs
- * free all IRQs request
- */
-static void xhci_free_irq(struct xhci_hcd *xhci)
-{
- struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
- int ret;
-
- /* return if using legacy interrupt */
- if (xhci_to_hcd(xhci)->irq > 0)
- return;
-
- ret = xhci_free_msi(xhci);
- if (!ret)
- return;
- if (pdev->irq > 0)
- free_irq(pdev->irq, xhci_to_hcd(xhci));
-
- return;
-}
-
-/*
* Set up MSI-X
*/
static int xhci_setup_msix(struct xhci_hcd *xhci)
@@ -298,28 +266,17 @@ static int xhci_setup_msix(struct xhci_hcd *xhci)
xhci->msix_count = min(num_online_cpus() + 1,
HCS_MAX_INTRS(xhci->hcs_params1));
- xhci->msix_entries =
- kmalloc((sizeof(struct msix_entry))*xhci->msix_count,
- GFP_KERNEL);
- if (!xhci->msix_entries)
- return -ENOMEM;
-
- for (i = 0; i < xhci->msix_count; i++) {
- xhci->msix_entries[i].entry = i;
- xhci->msix_entries[i].vector = 0;
- }
-
- ret = pci_enable_msix_exact(pdev, xhci->msix_entries, xhci->msix_count);
- if (ret) {
+ ret = pci_alloc_irq_vectors(pdev, xhci->msix_count, xhci->msix_count,
+ PCI_IRQ_MSIX);
+ if (ret < 0) {
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Failed to enable MSI-X");
- goto free_entries;
+ return ret;
}
for (i = 0; i < xhci->msix_count; i++) {
- ret = request_irq(xhci->msix_entries[i].vector,
- xhci_msi_irq,
- 0, "xhci_hcd", xhci_to_hcd(xhci));
+ ret = request_irq(pci_irq_vector(pdev, i), xhci_msi_irq, 0,
+ "xhci_hcd", xhci_to_hcd(xhci));
if (ret)
goto disable_msix;
}
@@ -329,11 +286,9 @@ static int xhci_setup_msix(struct xhci_hcd *xhci)
disable_msix:
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "disable MSI-X interrupt");
- xhci_free_irq(xhci);
- pci_disable_msix(pdev);
-free_entries:
- kfree(xhci->msix_entries);
- xhci->msix_entries = NULL;
+ while (--i >= 0)
+ free_irq(pci_irq_vector(pdev, i), xhci_to_hcd(xhci));
+ pci_free_irq_vectors(pdev);
return ret;
}
@@ -346,27 +301,33 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
if (xhci->quirks & XHCI_PLAT)
return;
- xhci_free_irq(xhci);
+ /* return if using legacy interrupt */
+ if (hcd->irq > 0)
+ return;
+
+ if (hcd->msix_enabled) {
+ int i;
- if (xhci->msix_entries) {
- pci_disable_msix(pdev);
- kfree(xhci->msix_entries);
- xhci->msix_entries = NULL;
+ for (i = 0; i < xhci->msix_count; i++)
+ free_irq(pci_irq_vector(pdev, i), xhci_to_hcd(xhci));
} else {
- pci_disable_msi(pdev);
+ free_irq(pci_irq_vector(pdev, 0), xhci_to_hcd(xhci));
}
+ pci_free_irq_vectors(pdev);
hcd->msix_enabled = 0;
- return;
}
static void __maybe_unused xhci_msix_sync_irqs(struct xhci_hcd *xhci)
{
- int i;
+ struct usb_hcd *hcd = xhci_to_hcd(xhci);
+
+ if (hcd->msix_enabled) {
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ int i;
- if (xhci->msix_entries) {
for (i = 0; i < xhci->msix_count; i++)
- synchronize_irq(xhci->msix_entries[i].vector);
+ synchronize_irq(pci_irq_vector(pdev, i));
}
}
@@ -539,7 +500,7 @@ static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci)
* device contexts (?), set up a command ring segment (or two?), create event
* ring (one for now).
*/
-int xhci_init(struct usb_hcd *hcd)
+static int xhci_init(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int retval = 0;
@@ -619,16 +580,10 @@ int xhci_run(struct usb_hcd *hcd)
if (ret)
return ret;
- xhci_dbg(xhci, "Command ring memory map follows:\n");
- xhci_debug_ring(xhci, xhci->cmd_ring);
- xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
xhci_dbg_cmd_ptrs(xhci);
xhci_dbg(xhci, "ERST memory map follows:\n");
xhci_dbg_erst(xhci, &xhci->erst);
- xhci_dbg(xhci, "Event ring:\n");
- xhci_debug_ring(xhci, xhci->event_ring);
- xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
temp_64 &= ~ERST_PTR_MASK;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
@@ -661,9 +616,11 @@ int xhci_run(struct usb_hcd *hcd)
if (xhci->quirks & XHCI_NEC_HOST) {
struct xhci_command *command;
+
command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
if (!command)
return -ENOMEM;
+
xhci_queue_vendor_command(xhci, command, 0, 0, 0,
TRB_TYPE(TRB_NEC_GET_FW));
}
@@ -682,28 +639,28 @@ EXPORT_SYMBOL_GPL(xhci_run);
* Disable device contexts, disable IRQs, and quiesce the HC.
* Reset the HC, finish any completed transactions, and cleanup memory.
*/
-void xhci_stop(struct usb_hcd *hcd)
+static void xhci_stop(struct usb_hcd *hcd)
{
u32 temp;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
mutex_lock(&xhci->mutex);
- if (!(xhci->xhc_state & XHCI_STATE_HALTED)) {
- spin_lock_irq(&xhci->lock);
-
- xhci->xhc_state |= XHCI_STATE_HALTED;
- xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
- xhci_halt(xhci);
- xhci_reset(xhci);
- spin_unlock_irq(&xhci->lock);
- }
-
+ /* Only halt host and free memory after both hcds are removed */
if (!usb_hcd_is_primary_hcd(hcd)) {
+ /* usb core will free this hcd shortly, unset pointer */
+ xhci->shared_hcd = NULL;
mutex_unlock(&xhci->mutex);
return;
}
+ spin_lock_irq(&xhci->lock);
+ xhci->xhc_state |= XHCI_STATE_HALTED;
+ xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+ xhci_halt(xhci);
+ xhci_reset(xhci);
+ spin_unlock_irq(&xhci->lock);
+
xhci_cleanup_msix(xhci);
/* Deleting Compliance Mode Recovery Timer */
@@ -721,7 +678,7 @@ void xhci_stop(struct usb_hcd *hcd)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Disabling event ring interrupts");
temp = readl(&xhci->op_regs->status);
- writel(temp & ~STS_EINT, &xhci->op_regs->status);
+ writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status);
temp = readl(&xhci->ir_set->irq_pending);
writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
xhci_print_ir_set(xhci, 0);
@@ -743,12 +700,12 @@ void xhci_stop(struct usb_hcd *hcd)
*
* This will only ever be called with the main usb_hcd (the USB3 roothub).
*/
-void xhci_shutdown(struct usb_hcd *hcd)
+static void xhci_shutdown(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
- usb_disable_xhci_ports(to_pci_dev(hcd->self.controller));
+ usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev));
spin_lock_irq(&xhci->lock);
xhci_halt(xhci);
@@ -765,7 +722,7 @@ void xhci_shutdown(struct usb_hcd *hcd)
/* Yet another workaround for spurious wakeups at shutdown with HSW */
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
- pci_set_power_state(to_pci_dev(hcd->self.controller), PCI_D3hot);
+ pci_set_power_state(to_pci_dev(hcd->self.sysdev), PCI_D3hot);
}
#ifdef CONFIG_PM
@@ -1054,7 +1011,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
xhci_dbg(xhci, "// Disabling event ring interrupts\n");
temp = readl(&xhci->op_regs->status);
- writel(temp & ~STS_EINT, &xhci->op_regs->status);
+ writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status);
temp = readl(&xhci->ir_set->irq_pending);
writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
xhci_print_ir_set(xhci, 0);
@@ -1176,7 +1133,7 @@ unsigned int xhci_get_endpoint_address(unsigned int ep_index)
* endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is
* bit 1, etc.
*/
-unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc)
+static unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc)
{
return 1 << (xhci_get_endpoint_index(desc) + 1);
}
@@ -1185,7 +1142,7 @@ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc)
* endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is
* bit 1, etc.
*/
-unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index)
+static unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index)
{
return 1 << (ep_index + 1);
}
@@ -1306,11 +1263,6 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG);
ctrl_ctx->drop_flags = 0;
- xhci_dbg(xhci, "Slot %d input context\n", slot_id);
- xhci_dbg_ctx(xhci, command->in_ctx, ep_index);
- xhci_dbg(xhci, "Slot %d output context\n", slot_id);
- xhci_dbg_ctx(xhci, out_ctx, ep_index);
-
ret = xhci_configure_endpoint(xhci, urb->dev, command,
true, false);
@@ -1329,7 +1281,7 @@ command_cleanup:
* non-error returns are a promise to giveback() the urb later
* we drop ownership so next owner (or urb unlink) can get it
*/
-int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
+static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
unsigned long flags;
@@ -1465,7 +1417,7 @@ free_priv:
* Note that this function can be called in any context, or so says
* usb_hcd_unlink_urb()
*/
-int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{
unsigned long flags;
int ret, i;
@@ -1501,10 +1453,16 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
if (!ep || !ep_ring)
goto err_giveback;
+ /* If xHC is dead take it down and return ALL URBs in xhci_hc_died() */
temp = readl(&xhci->op_regs->status);
- if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
+ if (temp == ~(u32)0 || xhci->xhc_state & XHCI_STATE_DYING) {
+ xhci_hc_died(xhci);
+ goto done;
+ }
+
+ if (xhci->xhc_state & XHCI_STATE_HALTED) {
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
- "HW died, freeing TD.");
+ "HC halted, freeing TD manually.");
for (i = urb_priv->num_tds_done;
i < urb_priv->num_tds;
i++) {
@@ -1576,7 +1534,7 @@ err_giveback:
* disabled, so there's no need for mutual exclusion to protect
* the xhci->devs[slot_id] structure.
*/
-int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+static int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
struct usb_host_endpoint *ep)
{
struct xhci_hcd *xhci;
@@ -1659,7 +1617,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
* configuration or alt setting is installed in the device, so there's no need
* for mutual exclusion to protect the xhci->devs[slot_id] structure.
*/
-int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
struct usb_host_endpoint *ep)
{
struct xhci_hcd *xhci;
@@ -1852,7 +1810,6 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
struct usb_device *udev, u32 *cmd_status)
{
int ret;
- struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
switch (*cmd_status) {
case COMP_COMMAND_ABORTED:
@@ -1873,7 +1830,6 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
case COMP_CONTEXT_STATE_ERROR:
dev_warn(&udev->dev,
"WARN: invalid context state for evaluate context command.\n");
- xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1);
ret = -EINVAL;
break;
case COMP_INCOMPATIBLE_DEVICE_ERROR:
@@ -2330,7 +2286,7 @@ static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw)
}
-void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci,
+static void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci,
struct xhci_bw_info *ep_bw,
struct xhci_interval_bw_table *bw_table,
struct usb_device *udev,
@@ -2595,6 +2551,12 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
return -EINVAL;
spin_lock_irqsave(&xhci->lock, flags);
+
+ if (xhci->xhc_state & XHCI_STATE_DYING) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ return -ESHUTDOWN;
+ }
+
virt_dev = xhci->devs[udev->slot_id];
ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
@@ -2689,7 +2651,7 @@ static void xhci_check_bw_drop_ep_streams(struct xhci_hcd *xhci,
* else should be touching the xhci->devs[slot_id] structure, so we
* don't need to take the xhci->lock for manipulating that.
*/
-int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
+static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
{
int i;
int ret = 0;
@@ -2746,9 +2708,6 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
break;
}
}
- xhci_dbg(xhci, "New Input Control Context:\n");
- xhci_dbg_ctx(xhci, virt_dev->in_ctx,
- LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
ret = xhci_configure_endpoint(xhci, udev, command,
false, false);
@@ -2756,10 +2715,6 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
/* Callee should call reset_bandwidth() */
goto command_cleanup;
- xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
- xhci_dbg_ctx(xhci, virt_dev->out_ctx,
- LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
-
/* Free any rings that were dropped, but not changed. */
for (i = 1; i < 31; i++) {
if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) &&
@@ -2793,7 +2748,7 @@ command_cleanup:
return ret;
}
-void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
+static void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
{
struct xhci_hcd *xhci;
struct xhci_virt_device *virt_dev;
@@ -2826,9 +2781,6 @@ static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci,
ctrl_ctx->drop_flags = cpu_to_le32(drop_flags);
xhci_slot_copy(xhci, in_ctx, out_ctx);
ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
-
- xhci_dbg(xhci, "Input Context:\n");
- xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags));
}
static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
@@ -2919,7 +2871,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
* Context: in_interrupt
*/
-void xhci_endpoint_reset(struct usb_hcd *hcd,
+static void xhci_endpoint_reset(struct usb_hcd *hcd,
struct usb_host_endpoint *ep)
{
struct xhci_hcd *xhci;
@@ -3095,7 +3047,7 @@ static u32 xhci_calculate_no_streams_bitmask(struct xhci_hcd *xhci,
* hardware or endpoints claim they can't support the number of requested
* stream IDs.
*/
-int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
+static int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
struct usb_host_endpoint **eps, unsigned int num_eps,
unsigned int num_streams, gfp_t mem_flags)
{
@@ -3129,10 +3081,9 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
}
config_cmd = xhci_alloc_command(xhci, true, true, mem_flags);
- if (!config_cmd) {
- xhci_dbg(xhci, "Could not allocate xHCI command structure.\n");
+ if (!config_cmd)
return -ENOMEM;
- }
+
ctrl_ctx = xhci_get_input_control_ctx(config_cmd->in_ctx);
if (!ctrl_ctx) {
xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
@@ -3259,7 +3210,7 @@ cleanup:
* Modify the endpoint context state, submit a configure endpoint command,
* and free all endpoint rings for streams if that completes successfully.
*/
-int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
+static int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
struct usb_host_endpoint **eps, unsigned int num_eps,
gfp_t mem_flags)
{
@@ -3391,7 +3342,8 @@ void xhci_free_device_endpoint_resources(struct xhci_hcd *xhci,
* re-initialization during S3/S4. In this case, call xhci_alloc_dev() to
* re-allocate the device.
*/
-int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
+static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
+ struct usb_device *udev)
{
int ret, i;
unsigned long flags;
@@ -3443,6 +3395,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
SLOT_STATE_DISABLED)
return 0;
+ trace_xhci_discover_or_reset_device(slot_ctx);
+
xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
/* Allocate the command structure that holds the struct completion.
* Assume we're in process context, since the normal device reset
@@ -3539,9 +3493,6 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
}
/* If necessary, update the number of active TTs on this root port */
xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps);
-
- xhci_dbg(xhci, "Output context after successful reset device cmd:\n");
- xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint);
ret = 0;
command_cleanup:
@@ -3554,12 +3505,11 @@ command_cleanup:
* disconnected, and all traffic has been stopped and the endpoints have been
* disabled. Free any HC data structures associated with that device.
*/
-void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
+static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_virt_device *virt_dev;
- unsigned long flags;
- u32 state;
+ struct xhci_slot_ctx *slot_ctx;
int i, ret;
struct xhci_command *command;
@@ -3587,6 +3537,8 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
}
virt_dev = xhci->devs[udev->slot_id];
+ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
+ trace_xhci_free_dev(slot_ctx);
/* Stop any wayward timer functions (which may grab the lock) */
for (i = 0; i < 31; i++) {
@@ -3594,30 +3546,50 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
}
+ xhci_disable_slot(xhci, command, udev->slot_id);
+ /*
+ * Event command completion handler will free any data structures
+ * associated with the slot. XXX Can free sleep?
+ */
+}
+
+int xhci_disable_slot(struct xhci_hcd *xhci, struct xhci_command *command,
+ u32 slot_id)
+{
+ unsigned long flags;
+ u32 state;
+ int ret = 0;
+ struct xhci_virt_device *virt_dev;
+
+ virt_dev = xhci->devs[slot_id];
+ if (!virt_dev)
+ return -EINVAL;
+ if (!command)
+ command = xhci_alloc_command(xhci, false, false, GFP_KERNEL);
+ if (!command)
+ return -ENOMEM;
+
spin_lock_irqsave(&xhci->lock, flags);
/* Don't disable the slot if the host controller is dead. */
state = readl(&xhci->op_regs->status);
if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) ||
(xhci->xhc_state & XHCI_STATE_HALTED)) {
- xhci_free_virt_device(xhci, udev->slot_id);
+ xhci_free_virt_device(xhci, slot_id);
spin_unlock_irqrestore(&xhci->lock, flags);
kfree(command);
- return;
+ return ret;
}
- if (xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
- udev->slot_id)) {
+ ret = xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
+ slot_id);
+ if (ret) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
- return;
+ return ret;
}
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
-
- /*
- * Event command completion handler will free any data structures
- * associated with the slot. XXX Can free sleep?
- */
+ return ret;
}
/*
@@ -3650,6 +3622,8 @@ static int xhci_reserve_host_control_ep_resources(struct xhci_hcd *xhci)
int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct xhci_virt_device *vdev;
+ struct xhci_slot_ctx *slot_ctx;
unsigned long flags;
int ret, slot_id;
struct xhci_command *command;
@@ -3705,6 +3679,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
goto disable_slot;
}
+ vdev = xhci->devs[slot_id];
+ slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx);
+ trace_xhci_alloc_dev(slot_ctx);
+
udev->slot_id = slot_id;
#ifndef CONFIG_USB_DEFAULT_PERSIST
@@ -3724,15 +3702,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
disable_slot:
/* Disable slot, if we can do it without mem alloc */
- spin_lock_irqsave(&xhci->lock, flags);
kfree(command->completion);
command->completion = NULL;
command->status = 0;
- if (!xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
- udev->slot_id))
- xhci_ring_cmd_db(xhci);
- spin_unlock_irqrestore(&xhci->lock, flags);
- return 0;
+ return xhci_disable_slot(xhci, command, udev->slot_id);
}
/*
@@ -3779,9 +3752,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
ret = -EINVAL;
goto out;
}
+ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
+ trace_xhci_setup_device_slot(slot_ctx);
if (setup == SETUP_CONTEXT_ONLY) {
- slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) ==
SLOT_STATE_DEFAULT) {
xhci_dbg(xhci, "Slot already in default state\n");
@@ -3818,8 +3792,6 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
ctrl_ctx->drop_flags = 0;
- xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
- xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
trace_xhci_address_ctx(xhci, virt_dev->in_ctx,
le32_to_cpu(slot_ctx->dev_info) >> 27);
@@ -3872,8 +3844,6 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
xhci_err(xhci,
"ERROR: unexpected setup %s command completion code 0x%x.\n",
act, command->status);
- xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
- xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
trace_xhci_address_ctx(xhci, virt_dev->out_ctx, 1);
ret = -EINVAL;
break;
@@ -3892,17 +3862,12 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
xhci_dbg_trace(xhci, trace_xhci_dbg_address,
"Output Context DMA address = %#08llx",
(unsigned long long)virt_dev->out_ctx->dma);
- xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
- xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
trace_xhci_address_ctx(xhci, virt_dev->in_ctx,
le32_to_cpu(slot_ctx->dev_info) >> 27);
- xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
- xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
/*
* USB core uses address 1 for the roothubs, so we add one to the
* address given back to us by the HC.
*/
- slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
trace_xhci_address_ctx(xhci, virt_dev->out_ctx,
le32_to_cpu(slot_ctx->dev_info) >> 27);
/* Zero the input context control for later use */
@@ -3921,12 +3886,12 @@ out:
return ret;
}
-int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
+static int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
{
return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS);
}
-int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev)
+static int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev)
{
return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ONLY);
}
@@ -4003,14 +3968,10 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
xhci_dbg_trace(xhci, trace_xhci_dbg_context_change,
"Set up evaluate context for LPM MEL change.");
- xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id);
- xhci_dbg_ctx(xhci, command->in_ctx, 0);
/* Issue and wait for the evaluate context command. */
ret = xhci_configure_endpoint(xhci, udev, command,
true, true);
- xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id);
- xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0);
if (!ret) {
spin_lock_irqsave(&xhci->lock, flags);
@@ -4083,7 +4044,7 @@ static int xhci_calculate_usb2_hw_lpm_params(struct usb_device *udev)
return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm);
}
-int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
+static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
struct usb_device *udev, int enable)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -4207,7 +4168,7 @@ static int xhci_check_usb2_port_capability(struct xhci_hcd *xhci, int port,
return 0;
}
-int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
+static 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;
@@ -4616,7 +4577,7 @@ static int calculate_max_exit_latency(struct usb_device *udev,
}
/* Returns the USB3 hub-encoded value for the U1/U2 timeout. */
-int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
+static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
struct usb_device *udev, enum usb3_link_state state)
{
struct xhci_hcd *xhci;
@@ -4647,7 +4608,7 @@ int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
return hub_encoded_timeout;
}
-int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
+static int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
struct usb_device *udev, enum usb3_link_state state)
{
struct xhci_hcd *xhci;
@@ -4663,24 +4624,24 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
}
#else /* CONFIG_PM */
-int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
+static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
struct usb_device *udev, int enable)
{
return 0;
}
-int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
+static int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
{
return 0;
}
-int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
+static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
struct usb_device *udev, enum usb3_link_state state)
{
return USB3_LPM_DISABLED;
}
-int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
+static int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
struct usb_device *udev, enum usb3_link_state state)
{
return 0;
@@ -4692,7 +4653,7 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
/* Once a hub descriptor is fetched for a device, we need to update the xHC's
* internal data structures for the device.
*/
-int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
struct usb_tt *tt, gfp_t mem_flags)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -4713,11 +4674,11 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
xhci_warn(xhci, "Cannot update hub desc for unknown device.\n");
return -EINVAL;
}
+
config_cmd = xhci_alloc_command(xhci, true, true, mem_flags);
- if (!config_cmd) {
- xhci_dbg(xhci, "Could not allocate xHCI command structure.\n");
+ if (!config_cmd)
return -ENOMEM;
- }
+
ctrl_ctx = xhci_get_input_control_ctx(config_cmd->in_ctx);
if (!ctrl_ctx) {
xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
@@ -4778,8 +4739,6 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
xhci_dbg(xhci, "Set up %s for hub device.\n",
(xhci->hci_version > 0x95) ?
"configure endpoint" : "evaluate context");
- xhci_dbg(xhci, "Slot %u Input Context:\n", hdev->slot_id);
- xhci_dbg_ctx(xhci, config_cmd->in_ctx, 0);
/* Issue and wait for the configure endpoint or
* evaluate context command.
@@ -4791,14 +4750,11 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
ret = xhci_configure_endpoint(xhci, hdev, config_cmd,
true, false);
- xhci_dbg(xhci, "Slot %u Output Context:\n", hdev->slot_id);
- xhci_dbg_ctx(xhci, vdev->out_ctx, 0);
-
xhci_free_command(xhci, config_cmd);
return ret;
}
-int xhci_get_frame(struct usb_hcd *hcd)
+static int xhci_get_frame(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
/* EHCI mods by the periodic size. Why? */
@@ -4808,7 +4764,11 @@ int xhci_get_frame(struct usb_hcd *hcd)
int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
{
struct xhci_hcd *xhci;
- struct device *dev = hcd->self.controller;
+ /*
+ * TODO: Check with DWC3 clients for sysdev according to
+ * quirks
+ */
+ struct device *dev = hcd->self.sysdev;
int retval;
/* Accept arbitrarily long scatter-gather lists */
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index da3eb695fe54..73a28a986d5e 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -425,6 +425,7 @@ struct xhci_op_regs {
#define PORT_L1DS_MASK (0xff << 8)
#define PORT_L1DS(p) (((p) & 0xff) << 8)
#define PORT_HLE (1 << 16)
+#define PORT_TEST_MODE_SHIFT 28
/* USB3 Protocol PORTLI Port Link Information */
#define PORT_RX_LANES(p) (((p) >> 16) & 0xf)
@@ -617,6 +618,7 @@ struct xhci_slot_ctx {
#define ROUTE_STRING_MASK (0xfffff)
/* Device speed - values defined by PORTSC Device Speed field - 20:23 */
#define DEV_SPEED (0xf << 20)
+#define GET_DEV_SPEED(n) (((n) & DEV_SPEED) >> 20)
/* bit 24 reserved */
/* Is this LS/FS device connected through a HS hub? - bit 25 */
#define DEV_MTT (0x1 << 25)
@@ -637,6 +639,7 @@ struct xhci_slot_ctx {
#define DEVINFO_TO_ROOT_HUB_PORT(p) (((p) >> 16) & 0xff)
/* Maximum number of ports under a hub device */
#define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24)
+#define DEVINFO_TO_MAX_PORTS(p) (((p) & (0xff << 24)) >> 24)
/* tt_info bitmasks */
/*
@@ -651,6 +654,7 @@ struct xhci_slot_ctx {
*/
#define TT_PORT (0xff << 8)
#define TT_THINK_TIME(p) (((p) & 0x3) << 16)
+#define GET_TT_THINK_TIME(p) (((p) & (0x3 << 16)) >> 16)
/* dev_state bitmasks */
/* USB device address - assigned by the HC */
@@ -1562,10 +1566,8 @@ struct xhci_ring {
struct xhci_segment *last_seg;
union xhci_trb *enqueue;
struct xhci_segment *enq_seg;
- unsigned int enq_updates;
union xhci_trb *dequeue;
struct xhci_segment *deq_seg;
- unsigned int deq_updates;
struct list_head td_list;
/*
* Write the cycle state into the TRB cycle field to give ownership of
@@ -1604,7 +1606,6 @@ struct xhci_scratchpad {
u64 *sp_array;
dma_addr_t sp_dma;
void **sp_buffers;
- dma_addr_t *sp_dma_buffers;
};
struct urb_priv {
@@ -1722,7 +1723,6 @@ struct xhci_hcd {
int page_shift;
/* msi-x vectors */
int msix_count;
- struct msix_entry *msix_entries;
/* optional clock */
struct clk *clk;
/* data structures */
@@ -1818,6 +1818,7 @@ struct xhci_hcd {
#define XHCI_MISSING_CAS (1 << 24)
/* For controller with a broken Port Disable implementation */
#define XHCI_BROKEN_PORT_PED (1 << 25)
+#define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26)
unsigned int num_active_eps;
unsigned int limit_active_eps;
@@ -1843,6 +1844,7 @@ struct xhci_hcd {
/* Compliance Mode Recovery Data */
struct timer_list comp_mode_recovery_timer;
u32 port_status_u0;
+ u16 test_mode;
/* Compliance Mode Timer Triggered every 2 seconds */
#define COMP_MODE_RCVRY_MSECS 2000
@@ -1918,19 +1920,10 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num);
void xhci_print_registers(struct xhci_hcd *xhci);
void xhci_dbg_regs(struct xhci_hcd *xhci);
void xhci_print_run_regs(struct xhci_hcd *xhci);
-void xhci_print_trb_offsets(struct xhci_hcd *xhci, union xhci_trb *trb);
-void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb);
-void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg);
-void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring);
void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst);
void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci);
-void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring);
-void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep);
char *xhci_get_slot_state(struct xhci_hcd *xhci,
struct xhci_container_ctx *ctx);
-void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
- unsigned int slot_id, unsigned int ep_index,
- struct xhci_virt_ep *ep);
void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *),
const char *fmt, ...);
@@ -1944,16 +1937,8 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
struct usb_device *udev);
unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc);
unsigned int xhci_get_endpoint_address(unsigned int ep_index);
-unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);
-unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index);
unsigned int xhci_last_valid_endpoint(u32 added_ctxs);
void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep);
-void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci,
- struct xhci_bw_info *ep_bw,
- struct xhci_interval_bw_table *bw_table,
- struct usb_device *udev,
- struct xhci_virt_ep *virt_ep,
- struct xhci_tt_bw_info *tt_info);
void xhci_update_tt_active_eps(struct xhci_hcd *xhci,
struct xhci_virt_device *virt_dev,
int old_active_eps);
@@ -2010,53 +1995,25 @@ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec);
void xhci_quiesce(struct xhci_hcd *xhci);
int xhci_halt(struct xhci_hcd *xhci);
+int xhci_start(struct xhci_hcd *xhci);
int xhci_reset(struct xhci_hcd *xhci);
-int xhci_init(struct usb_hcd *hcd);
int xhci_run(struct usb_hcd *hcd);
-void xhci_stop(struct usb_hcd *hcd);
-void xhci_shutdown(struct usb_hcd *hcd);
int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
void xhci_init_driver(struct hc_driver *drv,
const struct xhci_driver_overrides *over);
+int xhci_disable_slot(struct xhci_hcd *xhci,
+ struct xhci_command *command, u32 slot_id);
-#ifdef CONFIG_PM
int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
int xhci_resume(struct xhci_hcd *xhci, bool hibernated);
-#else
-#define xhci_suspend NULL
-#define xhci_resume NULL
-#endif
-int xhci_get_frame(struct usb_hcd *hcd);
irqreturn_t xhci_irq(struct usb_hcd *hcd);
irqreturn_t xhci_msi_irq(int irq, void *hcd);
int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev);
-void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev);
int xhci_alloc_tt_info(struct xhci_hcd *xhci,
struct xhci_virt_device *virt_dev,
struct usb_device *hdev,
struct usb_tt *tt, gfp_t mem_flags);
-int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint **eps, unsigned int num_eps,
- unsigned int num_streams, gfp_t mem_flags);
-int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint **eps, unsigned int num_eps,
- gfp_t mem_flags);
-int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev);
-int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev);
-int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev);
-int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
- struct usb_device *udev, int enable);
-int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
- struct usb_tt *tt, gfp_t mem_flags);
-int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
-int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
-int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
-int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
-void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
-int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev);
-int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
-void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
/* xHCI ring, segment, TRB, and TD functions */
dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb);
@@ -2100,9 +2057,6 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
struct xhci_dequeue_state *deq_state);
void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
unsigned int ep_index, struct xhci_td *td);
-void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
- unsigned int slot_id, unsigned int ep_index,
- struct xhci_dequeue_state *deq_state);
void xhci_stop_endpoint_command_watchdog(unsigned long arg);
void xhci_handle_command_timeout(struct work_struct *work);
@@ -2113,16 +2067,13 @@ void xhci_cleanup_command_queue(struct xhci_hcd *xhci);
/* xHCI roothub code */
void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
int port_id, u32 link_state);
-int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
- struct usb_device *udev, enum usb3_link_state state);
-int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
- struct usb_device *udev, enum usb3_link_state state);
void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
int port_id, u32 port_bit);
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength);
int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
+void xhci_hc_died(struct xhci_hcd *xhci);
#ifdef CONFIG_PM
int xhci_bus_suspend(struct usb_hcd *hcd);
@@ -2153,6 +2104,22 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
urb->stream_id);
}
+static inline char *xhci_slot_state_string(u32 state)
+{
+ switch (state) {
+ case SLOT_STATE_ENABLED:
+ return "enabled/disabled";
+ case SLOT_STATE_DEFAULT:
+ return "default";
+ case SLOT_STATE_ADDRESSED:
+ return "addressed";
+ case SLOT_STATE_CONFIGURED:
+ return "configured";
+ default:
+ return "reserved";
+ }
+}
+
static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
u32 field3)
{
@@ -2162,14 +2129,12 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
switch (type) {
case TRB_LINK:
sprintf(str,
- "TRB %08x%08x status '%s' len %d slot %d ep %d type '%s' flags %c:%c",
- field1, field0,
- xhci_trb_comp_code_string(GET_COMP_CODE(field2)),
- EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3),
- /* Macro decrements 1, maybe it shouldn't?!? */
- TRB_TO_EP_INDEX(field3) + 1,
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
- field3 & EVENT_DATA ? 'E' : 'e',
+ "LINK %08x%08x intr %d type '%s' flags %c:%c:%c:%c",
+ field1, field0, GET_INTR_TARGET(field2),
+ xhci_trb_type_string(type),
+ field3 & TRB_IOC ? 'I' : 'i',
+ field3 & TRB_CHAIN ? 'C' : 'c',
+ field3 & TRB_TC ? 'T' : 't',
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_TRANSFER:
@@ -2187,37 +2152,52 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3),
/* Macro decrements 1, maybe it shouldn't?!? */
TRB_TO_EP_INDEX(field3) + 1,
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field3 & EVENT_DATA ? 'E' : 'e',
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_SETUP:
- sprintf(str,
- "bRequestType %02x bRequest %02x wValue %02x%02x wIndex %02x%02x wLength %d length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c:%c",
- field0 & 0xff,
- (field0 & 0xff00) >> 8,
- (field0 & 0xff000000) >> 24,
- (field0 & 0xff0000) >> 16,
- (field1 & 0xff00) >> 8,
- field1 & 0xff,
- (field1 & 0xff000000) >> 16 |
- (field1 & 0xff0000) >> 16,
- TRB_LEN(field2), GET_TD_SIZE(field2),
- GET_INTR_TARGET(field2),
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
- field3 & TRB_BEI ? 'B' : 'b',
- field3 & TRB_IDT ? 'I' : 'i',
- field3 & TRB_IOC ? 'I' : 'i',
- field3 & TRB_CHAIN ? 'C' : 'c',
- field3 & TRB_NO_SNOOP ? 'S' : 's',
- field3 & TRB_ISP ? 'I' : 'i',
- field3 & TRB_ENT ? 'E' : 'e',
- field3 & TRB_CYCLE ? 'C' : 'c');
+ sprintf(str, "bRequestType %02x bRequest %02x wValue %02x%02x wIndex %02x%02x wLength %d length %d TD size %d intr %d type '%s' flags %c:%c:%c",
+ field0 & 0xff,
+ (field0 & 0xff00) >> 8,
+ (field0 & 0xff000000) >> 24,
+ (field0 & 0xff0000) >> 16,
+ (field1 & 0xff00) >> 8,
+ field1 & 0xff,
+ (field1 & 0xff000000) >> 16 |
+ (field1 & 0xff0000) >> 16,
+ TRB_LEN(field2), GET_TD_SIZE(field2),
+ GET_INTR_TARGET(field2),
+ xhci_trb_type_string(type),
+ field3 & TRB_IDT ? 'I' : 'i',
+ field3 & TRB_IOC ? 'I' : 'i',
+ field3 & TRB_CYCLE ? 'C' : 'c');
break;
- case TRB_NORMAL:
case TRB_DATA:
+ sprintf(str, "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c",
+ field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
+ GET_INTR_TARGET(field2),
+ xhci_trb_type_string(type),
+ field3 & TRB_IDT ? 'I' : 'i',
+ field3 & TRB_IOC ? 'I' : 'i',
+ field3 & TRB_CHAIN ? 'C' : 'c',
+ field3 & TRB_NO_SNOOP ? 'S' : 's',
+ field3 & TRB_ISP ? 'I' : 'i',
+ field3 & TRB_ENT ? 'E' : 'e',
+ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
case TRB_STATUS:
+ sprintf(str, "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c",
+ field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
+ GET_INTR_TARGET(field2),
+ xhci_trb_type_string(type),
+ field3 & TRB_IOC ? 'I' : 'i',
+ field3 & TRB_CHAIN ? 'C' : 'c',
+ field3 & TRB_ENT ? 'E' : 'e',
+ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
+ case TRB_NORMAL:
case TRB_ISOC:
case TRB_EVENT_DATA:
case TRB_TR_NOOP:
@@ -2225,7 +2205,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
"Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c:%c",
field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
GET_INTR_TARGET(field2),
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field3 & TRB_BEI ? 'B' : 'b',
field3 & TRB_IDT ? 'I' : 'i',
field3 & TRB_IOC ? 'I' : 'i',
@@ -2240,21 +2220,21 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_ENABLE_SLOT:
sprintf(str,
"%s: flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_DISABLE_SLOT:
case TRB_NEG_BANDWIDTH:
sprintf(str,
"%s: slot %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
TRB_TO_SLOT_ID(field3),
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_ADDR_DEV:
sprintf(str,
"%s: ctx %08x%08x slot %d flags %c:%c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field1, field0,
TRB_TO_SLOT_ID(field3),
field3 & TRB_BSR ? 'B' : 'b',
@@ -2263,7 +2243,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_CONFIG_EP:
sprintf(str,
"%s: ctx %08x%08x slot %d flags %c:%c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field1, field0,
TRB_TO_SLOT_ID(field3),
field3 & TRB_DC ? 'D' : 'd',
@@ -2272,7 +2252,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_EVAL_CONTEXT:
sprintf(str,
"%s: ctx %08x%08x slot %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field1, field0,
TRB_TO_SLOT_ID(field3),
field3 & TRB_CYCLE ? 'C' : 'c');
@@ -2280,7 +2260,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_RESET_EP:
sprintf(str,
"%s: ctx %08x%08x slot %d ep %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field1, field0,
TRB_TO_SLOT_ID(field3),
/* Macro decrements 1, maybe it shouldn't?!? */
@@ -2290,7 +2270,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_STOP_RING:
sprintf(str,
"%s: slot %d sp %d ep %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
TRB_TO_SLOT_ID(field3),
TRB_TO_SUSPEND_PORT(field3),
/* Macro decrements 1, maybe it shouldn't?!? */
@@ -2300,7 +2280,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_SET_DEQ:
sprintf(str,
"%s: deq %08x%08x stream %d slot %d ep %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field1, field0,
TRB_TO_STREAM_ID(field2),
TRB_TO_SLOT_ID(field3),
@@ -2311,14 +2291,14 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_RESET_DEV:
sprintf(str,
"%s: slot %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
TRB_TO_SLOT_ID(field3),
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_FORCE_EVENT:
sprintf(str,
"%s: event %08x%08x vf intr %d vf id %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field1, field0,
TRB_TO_VF_INTR_TARGET(field2),
TRB_TO_VF_ID(field3),
@@ -2327,14 +2307,14 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_SET_LT:
sprintf(str,
"%s: belt %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
TRB_TO_BELT(field3),
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_GET_BW:
sprintf(str,
"%s: ctx %08x%08x slot %d speed %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field1, field0,
TRB_TO_SLOT_ID(field3),
TRB_TO_DEV_SPEED(field3),
@@ -2343,7 +2323,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
case TRB_FORCE_HEADER:
sprintf(str,
"%s: info %08x%08x%08x pkt type %d roothub port %d flags %c",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field2, field1, field0 & 0xffffffe0,
TRB_TO_PACKET_TYPE(field0),
TRB_TO_ROOTHUB_PORT(field3),
@@ -2352,12 +2332,155 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
default:
sprintf(str,
"type '%s' -> raw %08x %08x %08x %08x",
- xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
+ xhci_trb_type_string(type),
field0, field1, field2, field3);
}
return str;
}
+static inline const char *xhci_decode_slot_context(u32 info, u32 info2,
+ u32 tt_info, u32 state)
+{
+ static char str[1024];
+ u32 speed;
+ u32 hub;
+ u32 mtt;
+ int ret = 0;
+
+ speed = info & DEV_SPEED;
+ hub = info & DEV_HUB;
+ mtt = info & DEV_MTT;
+
+ ret = sprintf(str, "RS %05x %s%s%s Ctx Entries %d MEL %d us Port# %d/%d",
+ info & ROUTE_STRING_MASK,
+ ({ char *s;
+ switch (speed) {
+ case SLOT_SPEED_FS:
+ s = "full-speed";
+ break;
+ case SLOT_SPEED_LS:
+ s = "low-speed";
+ break;
+ case SLOT_SPEED_HS:
+ s = "high-speed";
+ break;
+ case SLOT_SPEED_SS:
+ s = "super-speed";
+ break;
+ case SLOT_SPEED_SSP:
+ s = "super-speed plus";
+ break;
+ default:
+ s = "UNKNOWN speed";
+ } s; }),
+ mtt ? " multi-TT" : "",
+ hub ? " Hub" : "",
+ (info & LAST_CTX_MASK) >> 27,
+ info2 & MAX_EXIT,
+ DEVINFO_TO_ROOT_HUB_PORT(info2),
+ DEVINFO_TO_MAX_PORTS(info2));
+
+ ret += sprintf(str + ret, " [TT Slot %d Port# %d TTT %d Intr %d] Addr %d State %s",
+ tt_info & TT_SLOT, (tt_info & TT_PORT) >> 8,
+ GET_TT_THINK_TIME(tt_info), GET_INTR_TARGET(tt_info),
+ state & DEV_ADDR_MASK,
+ xhci_slot_state_string(GET_SLOT_STATE(state)));
+
+ return str;
+}
+
+static inline const char *xhci_ep_state_string(u8 state)
+{
+ switch (state) {
+ case EP_STATE_DISABLED:
+ return "disabled";
+ case EP_STATE_RUNNING:
+ return "running";
+ case EP_STATE_HALTED:
+ return "halted";
+ case EP_STATE_STOPPED:
+ return "stopped";
+ case EP_STATE_ERROR:
+ return "error";
+ default:
+ return "INVALID";
+ }
+}
+
+static inline const char *xhci_ep_type_string(u8 type)
+{
+ switch (type) {
+ case ISOC_OUT_EP:
+ return "Isoc OUT";
+ case BULK_OUT_EP:
+ return "Bulk OUT";
+ case INT_OUT_EP:
+ return "Int OUT";
+ case CTRL_EP:
+ return "Ctrl";
+ case ISOC_IN_EP:
+ return "Isoc IN";
+ case BULK_IN_EP:
+ return "Bulk IN";
+ case INT_IN_EP:
+ return "Int IN";
+ default:
+ return "INVALID";
+ }
+}
+
+static inline const char *xhci_decode_ep_context(u32 info, u32 info2, u64 deq,
+ u32 tx_info)
+{
+ static char str[1024];
+ int ret;
+
+ u32 esit;
+ u16 maxp;
+ u16 avg;
+
+ u8 max_pstr;
+ u8 ep_state;
+ u8 interval;
+ u8 ep_type;
+ u8 burst;
+ u8 cerr;
+ u8 mult;
+ u8 lsa;
+ u8 hid;
+
+ esit = EP_MAX_ESIT_PAYLOAD_HI(info) << 16 |
+ EP_MAX_ESIT_PAYLOAD_LO(tx_info);
+
+ ep_state = info & EP_STATE_MASK;
+ max_pstr = info & EP_MAXPSTREAMS_MASK;
+ interval = CTX_TO_EP_INTERVAL(info);
+ mult = CTX_TO_EP_MULT(info) + 1;
+ lsa = info & EP_HAS_LSA;
+
+ cerr = (info2 & (3 << 1)) >> 1;
+ ep_type = CTX_TO_EP_TYPE(info2);
+ hid = info2 & (1 << 7);
+ burst = CTX_TO_MAX_BURST(info2);
+ maxp = MAX_PACKET_DECODED(info2);
+
+ avg = EP_AVG_TRB_LENGTH(tx_info);
+
+ ret = sprintf(str, "State %s mult %d max P. Streams %d %s",
+ xhci_ep_state_string(ep_state), mult,
+ max_pstr, lsa ? "LSA " : "");
+
+ ret += sprintf(str + ret, "interval %d us max ESIT payload %d CErr %d ",
+ (1 << interval) * 125, esit, cerr);
+
+ ret += sprintf(str + ret, "Type %s %sburst %d maxp %d deq %016llx ",
+ xhci_ep_type_string(ep_type), hid ? "HID" : "",
+ burst, maxp, deq);
+
+ ret += sprintf(str + ret, "avg trb len %d", avg);
+
+ return str;
+}
#endif /* __LINUX_XHCI_HCD_H */