diff options
Diffstat (limited to 'drivers/usb/host')
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) |
