diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/host/bcma-hcd.c | 169 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-platform.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/fhci-hcd.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/fsl-mph-dr-of.c | 18 | ||||
-rw-r--r-- | drivers/usb/host/max3421-hcd.c | 10 | ||||
-rw-r--r-- | drivers/usb/host/ohci-at91.c | 69 | ||||
-rw-r--r-- | drivers/usb/host/ohci-omap.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ohci-sa1111.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/whci/init.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 22 | ||||
-rw-r--r-- | drivers/usb/host/xhci-tegra.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 4 |
17 files changed, 224 insertions, 100 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2e710a4cca52..0b80cee30da4 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -472,7 +472,7 @@ config USB_OHCI_HCD_AT91 config USB_OHCI_HCD_OMAP3 tristate "OHCI support for OMAP3 and later chips" - depends on (ARCH_OMAP3 || ARCH_OMAP4) + depends on (ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5) default y ---help--- Enables support for the on-chip OHCI controller on diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index 172ef17911aa..5f425c89faf1 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -27,6 +27,7 @@ #include <linux/slab.h> #include <linux/of.h> #include <linux/of_gpio.h> +#include <linux/of_platform.h> #include <linux/usb/ehci_pdriver.h> #include <linux/usb/ohci_pdriver.h> @@ -34,6 +35,9 @@ MODULE_AUTHOR("Hauke Mehrtens"); MODULE_DESCRIPTION("Common USB driver for BCMA Bus"); MODULE_LICENSE("GPL"); +/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */ +#define USB_BCMA_CLKCTLST_USB_CLK_REQ 0x00000100 + struct bcma_hcd_device { struct bcma_device *core; struct platform_device *ehci_dev; @@ -165,44 +169,80 @@ static void bcma_hcd_init_chip_mips(struct bcma_device *dev) } } -static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev) +/** + * bcma_hcd_usb20_old_arm_init - Initialize old USB 2.0 controller on ARM + * + * Old USB 2.0 core is identified as BCMA_CORE_USB20_HOST and was introduced + * long before Northstar devices. It seems some cheaper chipsets like BCM53573 + * still use it. + * Initialization of this old core differs between MIPS and ARM. + */ +static int bcma_hcd_usb20_old_arm_init(struct bcma_hcd_device *usb_dev) { - struct bcma_device *arm_core; - void __iomem *dmu; - - arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9); - if (!arm_core) { - dev_err(&dev->dev, "can not find ARM Cortex A9 ihost core\n"); - return; + struct bcma_device *core = usb_dev->core; + struct device *dev = &core->dev; + struct bcma_device *pmu_core; + + usleep_range(10000, 20000); + if (core->id.rev < 5) + return 0; + + pmu_core = bcma_find_core(core->bus, BCMA_CORE_PMU); + if (!pmu_core) { + dev_err(dev, "Could not find PMU core\n"); + return -ENOENT; } - dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000); - if (!dmu) { - dev_err(&dev->dev, "can not map ARM Cortex A9 ihost core\n"); - return; - } - - /* Unlock DMU PLL settings */ - iowrite32(0x0000ea68, dmu + 0x180); - - /* Write USB 2.0 PLL control setting */ - iowrite32(0x00dd10c3, dmu + 0x164); + /* Take USB core out of reset */ + bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK | BCMA_IOCTL_FGC); + usleep_range(100, 200); + bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); + usleep_range(100, 200); + bcma_awrite32(core, BCMA_RESET_CTL, 0); + usleep_range(100, 200); + bcma_awrite32(core, BCMA_IOCTL, BCMA_IOCTL_CLK); + usleep_range(100, 200); + + /* Enable Misc PLL */ + bcma_write32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT | + BCMA_CLKCTLST_HQCLKREQ | + USB_BCMA_CLKCTLST_USB_CLK_REQ); + usleep_range(100, 200); + + bcma_write32(core, 0x510, 0xc7f85000); + bcma_write32(core, 0x510, 0xc7f85003); + usleep_range(300, 600); + + /* Program USB PHY PLL parameters */ + bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x6); + bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x005360c1); + usleep_range(100, 200); + bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_ADDR, 0x7); + bcma_write32(pmu_core, BCMA_CC_PMU_PLLCTL_DATA, 0x0); + usleep_range(100, 200); + bcma_set32(pmu_core, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); + usleep_range(100, 200); + + bcma_write32(core, 0x510, 0x7f8d007); + udelay(1000); + + /* Take controller out of reset */ + bcma_write32(core, 0x200, 0x4ff); + usleep_range(25, 50); + bcma_write32(core, 0x200, 0x6ff); + usleep_range(25, 50); + bcma_write32(core, 0x200, 0x7ff); + usleep_range(25, 50); + + of_platform_default_populate(dev->of_node, NULL, dev); - /* Lock DMU PLL settings */ - iowrite32(0x00000000, dmu + 0x180); - - iounmap(dmu); + return 0; } -static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev) +static void bcma_hcd_usb20_ns_init_hc(struct bcma_device *dev) { u32 val; - /* - * Delay after PHY initialized to ensure HC is ready to be configured - */ - usleep_range(1000, 2000); - /* Set packet buffer OUT threshold */ val = bcma_read32(dev, 0x94); val &= 0xffff; @@ -213,20 +253,33 @@ static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev) val = bcma_read32(dev, 0x9c); val |= 1; bcma_write32(dev, 0x9c, val); + + /* + * Broadcom initializes PHY and then waits to ensure HC is ready to be + * configured. In our case the order is reversed. We just initialized + * controller and we let HCD initialize PHY, so let's wait (sleep) now. + */ + usleep_range(1000, 2000); } -static void bcma_hcd_init_chip_arm(struct bcma_device *dev) +/** + * bcma_hcd_usb20_ns_init - Initialize Northstar USB 2.0 controller + */ +static int bcma_hcd_usb20_ns_init(struct bcma_hcd_device *bcma_hcd) { - bcma_core_enable(dev, 0); + struct bcma_device *core = bcma_hcd->core; + struct bcma_chipinfo *ci = &core->bus->chipinfo; + struct device *dev = &core->dev; - if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 || - dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) { - if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 || - dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708) - bcma_hcd_init_chip_arm_phy(dev); + bcma_core_enable(core, 0); - bcma_hcd_init_chip_arm_hc(dev); - } + if (ci->id == BCMA_CHIP_ID_BCM4707 || + ci->id == BCMA_CHIP_ID_BCM53018) + bcma_hcd_usb20_ns_init_hc(core); + + of_platform_default_populate(dev->of_node, NULL, dev); + + return 0; } static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val) @@ -299,16 +352,7 @@ static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev) if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) return -EOPNOTSUPP; - switch (dev->id.id) { - case BCMA_CORE_NS_USB20: - bcma_hcd_init_chip_arm(dev); - break; - case BCMA_CORE_USB20_HOST: - bcma_hcd_init_chip_mips(dev); - break; - default: - return -ENODEV; - } + bcma_hcd_init_chip_mips(dev); /* In AI chips EHCI is addrspace 0, OHCI is 1 */ ohci_addr = dev->addr_s[0]; @@ -338,6 +382,18 @@ err_unregister_ohci_dev: return err; } +static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd) +{ + struct bcma_device *core = bcma_hcd->core; + struct device *dev = &core->dev; + + bcma_core_enable(core, 0); + + of_platform_default_populate(dev->of_node, NULL, dev); + + return 0; +} + static int bcma_hcd_probe(struct bcma_device *core) { int err; @@ -357,14 +413,24 @@ static int bcma_hcd_probe(struct bcma_device *core) switch (core->id.id) { case BCMA_CORE_USB20_HOST: + if (IS_ENABLED(CONFIG_ARM)) + err = bcma_hcd_usb20_old_arm_init(usb_dev); + else if (IS_ENABLED(CONFIG_MIPS)) + err = bcma_hcd_usb20_init(usb_dev); + else + err = -ENOTSUPP; + break; case BCMA_CORE_NS_USB20: - err = bcma_hcd_usb20_init(usb_dev); - if (err) - return err; + err = bcma_hcd_usb20_ns_init(usb_dev); + break; + case BCMA_CORE_NS_USB30: + err = bcma_hcd_usb30_init(usb_dev); break; default: return -ENODEV; } + if (err) + return err; bcma_set_drvdata(core, usb_dev); return 0; @@ -416,6 +482,7 @@ static int bcma_hcd_resume(struct bcma_device *dev) static const struct bcma_device_id bcma_hcd_table[] = { BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS), + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB30, BCMA_ANY_REV, BCMA_ANY_CLASS), {}, }; MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a962b89b65a6..1e5f529d51a2 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -332,11 +332,11 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci) int port = HCS_N_PORTS(ehci->hcs_params); while (port--) { - ehci_writel(ehci, PORT_RWC_BITS, - &ehci->regs->port_status[port]); spin_unlock_irq(&ehci->lock); ehci_port_power(ehci, port, false); spin_lock_irq(&ehci->lock); + ehci_writel(ehci, PORT_RWC_BITS, + &ehci->regs->port_status[port]); } } diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 6816b8c371d0..876dca4fc216 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -38,7 +38,7 @@ #include "ehci.h" #define DRIVER_DESC "EHCI generic platform driver" -#define EHCI_MAX_CLKS 3 +#define EHCI_MAX_CLKS 4 #define EHCI_MAX_RSTS 3 #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv) diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 0960f41f945a..55a0ae6f2d74 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -310,10 +310,8 @@ static struct fhci_usb *fhci_create_lld(struct fhci_hcd *fhci) /* allocate memory for SCC data structure */ usb = kzalloc(sizeof(*usb), GFP_KERNEL); - if (!usb) { - fhci_err(fhci, "no memory for SCC data struct\n"); + if (!usb) return NULL; - } usb->fhci = fhci; usb->hc_list = fhci->hc_list; diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 1044b0f9d656..f07ccb25bc24 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -222,23 +222,17 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) pdata->controller_ver = usb_get_ver_info(np); /* Activate Erratum by reading property in device tree */ - if (of_get_property(np, "fsl,usb-erratum-a007792", NULL)) - pdata->has_fsl_erratum_a007792 = 1; - else - pdata->has_fsl_erratum_a007792 = 0; - if (of_get_property(np, "fsl,usb-erratum-a005275", NULL)) - pdata->has_fsl_erratum_a005275 = 1; - else - pdata->has_fsl_erratum_a005275 = 0; + pdata->has_fsl_erratum_a007792 = + of_property_read_bool(np, "fsl,usb-erratum-a007792"); + pdata->has_fsl_erratum_a005275 = + of_property_read_bool(np, "fsl,usb-erratum-a005275"); /* * Determine whether phy_clk_valid needs to be checked * by reading property in device tree */ - if (of_get_property(np, "phy-clk-valid", NULL)) - pdata->check_phy_clk_valid = 1; - else - pdata->check_phy_clk_valid = 0; + pdata->check_phy_clk_valid = + of_property_read_bool(np, "phy-clk-valid"); if (pdata->have_sysif_regs) { if (pdata->controller_ver == FSL_USB_VER_NONE) { diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index c369c29e496d..369869a29ebd 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1675,7 +1675,7 @@ max3421_gpout_set_value(struct usb_hcd *hcd, u8 pin_number, u8 value) if (pin_number > 7) return; - mask = 1u << pin_number; + mask = 1u << (pin_number % 4); idx = pin_number / 4; if (value) @@ -1856,15 +1856,11 @@ max3421_probe(struct spi_device *spi) INIT_LIST_HEAD(&max3421_hcd->ep_list); max3421_hcd->tx = kmalloc(sizeof(*max3421_hcd->tx), GFP_KERNEL); - if (!max3421_hcd->tx) { - dev_err(&spi->dev, "failed to kmalloc tx buffer\n"); + if (!max3421_hcd->tx) goto error; - } max3421_hcd->rx = kmalloc(sizeof(*max3421_hcd->rx), GFP_KERNEL); - if (!max3421_hcd->rx) { - dev_err(&spi->dev, "failed to kmalloc rx buffer\n"); + if (!max3421_hcd->rx) goto error; - } max3421_hcd->spi_thread = kthread_run(max3421_spi_thread, hcd, "max3421_spi_thread"); diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index d177372bb357..5b5880c0ae19 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -21,8 +21,11 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> #include <linux/usb.h> #include <linux/usb/hcd.h> +#include <soc/at91/atmel-sfr.h> #include "ohci.h" @@ -51,6 +54,7 @@ struct ohci_at91_priv { struct clk *hclk; bool clocked; bool wakeup; /* Saved wake-up state for resume */ + struct regmap *sfr_regmap; }; /* interface and function clocks; sometimes also an AHB clock */ @@ -134,6 +138,17 @@ static void at91_stop_hc(struct platform_device *pdev) static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); +static struct regmap *at91_dt_syscon_sfr(void) +{ + struct regmap *regmap; + + regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr"); + if (IS_ERR(regmap)) + regmap = NULL; + + return regmap; +} + /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -197,6 +212,10 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, goto err; } + ohci_at91->sfr_regmap = at91_dt_syscon_sfr(); + if (!ohci_at91->sfr_regmap) + dev_warn(dev, "failed to find sfr node\n"); + board = hcd->self.controller->platform_data; ohci = hcd_to_ohci(hcd); ohci->num_ports = board->ports; @@ -282,6 +301,28 @@ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf) return length; } +static int ohci_at91_port_suspend(struct regmap *regmap, u8 set) +{ + u32 regval; + int ret; + + if (!regmap) + return 0; + + ret = regmap_read(regmap, AT91_SFR_OHCIICR, ®val); + if (ret) + return ret; + + if (set) + regval |= AT91_OHCIICR_USB_SUSPEND; + else + regval &= ~AT91_OHCIICR_USB_SUSPEND; + + regmap_write(regmap, AT91_SFR_OHCIICR, regval); + + return 0; +} + /* * Look at the control requests to the root hub and see if we need to override. */ @@ -289,6 +330,7 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct at91_usbh_data *pdata = dev_get_platdata(hcd->self.controller); + struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd); struct usb_hub_descriptor *desc; int ret = -EINVAL; u32 *data = (u32 *)buf; @@ -301,7 +343,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, switch (typeReq) { case SetPortFeature: - if (wValue == USB_PORT_FEAT_POWER) { + switch (wValue) { + case USB_PORT_FEAT_POWER: dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); if (valid_port(wIndex)) { ohci_at91_usb_set_power(pdata, wIndex, 1); @@ -309,6 +352,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } goto out; + + case USB_PORT_FEAT_SUSPEND: + dev_dbg(hcd->self.controller, "SetPortFeat: SUSPEND\n"); + if (valid_port(wIndex)) { + ohci_at91_port_suspend(ohci_at91->sfr_regmap, + 1); + return 0; + } + break; } break; @@ -342,6 +394,16 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ohci_at91_usb_set_power(pdata, wIndex, 0); return 0; } + break; + + case USB_PORT_FEAT_SUSPEND: + dev_dbg(hcd->self.controller, "ClearPortFeature: SUSPEND\n"); + if (valid_port(wIndex)) { + ohci_at91_port_suspend(ohci_at91->sfr_regmap, + 0); + return 0; + } + break; } break; } @@ -599,6 +661,8 @@ ohci_hcd_at91_drv_suspend(struct device *dev) if (ohci_at91->wakeup) enable_irq_wake(hcd->irq); + ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1); + ret = ohci_suspend(hcd, ohci_at91->wakeup); if (ret) { if (ohci_at91->wakeup) @@ -638,6 +702,9 @@ ohci_hcd_at91_drv_resume(struct device *dev) at91_start_clock(ohci_at91); ohci_resume(hcd, false); + + ohci_at91_port_suspend(ohci_at91->sfr_regmap, 0); + return 0; } diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index de7c68602a7e..495c1454b9e8 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -36,7 +36,6 @@ #include <mach/mux.h> #include <mach/hardware.h> -#include <mach/irqs.h> #include <mach/usb.h> diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index 2ac266d692a2..3a9ea32508df 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -13,9 +13,7 @@ * This file is licenced under the GPL. */ -#include <mach/hardware.h> #include <asm/mach-types.h> -#include <mach/assabet.h> #include <asm/hardware/sa1111.h> #ifndef CONFIG_SA1111 @@ -127,7 +125,7 @@ static int sa1111_start_hc(struct sa1111_dev *dev) dev_dbg(&dev->dev, "starting SA-1111 OHCI USB Controller\n"); if (machine_is_xp860() || - machine_has_neponset() || + machine_is_assabet() || machine_is_pfs168() || machine_is_badge4()) usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index a7de8e8bb458..5d3d914ab4fb 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -601,11 +601,8 @@ static int uhci_start(struct usb_hcd *hcd) uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu), GFP_KERNEL); - if (!uhci->frame_cpu) { - dev_err(uhci_dev(uhci), - "unable to allocate memory for frame pointers\n"); + if (!uhci->frame_cpu) goto err_alloc_frame_cpu; - } uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci), sizeof(struct uhci_td), 16, 0); diff --git a/drivers/usb/host/whci/init.c b/drivers/usb/host/whci/init.c index e36372393bb1..ad8eb575c30a 100644 --- a/drivers/usb/host/whci/init.c +++ b/drivers/usb/host/whci/init.c @@ -65,7 +65,7 @@ int whc_init(struct whc *whc) init_waitqueue_head(&whc->cmd_wq); init_waitqueue_head(&whc->async_list_wq); init_waitqueue_head(&whc->periodic_list_wq); - whc->workqueue = create_singlethread_workqueue(dev_name(&whc->umc->dev)); + whc->workqueue = alloc_ordered_workqueue(dev_name(&whc->umc->dev), 0); if (whc->workqueue == NULL) { ret = -ENOMEM; goto error; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index d61fcc48099e..730b9fd26685 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -386,6 +386,9 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) ret = 0; virt_dev = xhci->devs[slot_id]; + if (!virt_dev) + return -ENODEV; + cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO); if (!cmd) { xhci_dbg(xhci, "Couldn't allocate command structure.\n"); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 4fd041bec332..d7b0f97abbad 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -314,11 +314,12 @@ static void xhci_pci_remove(struct pci_dev *dev) usb_remove_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd); } - usb_hcd_pci_remove(dev); /* Workaround for spurious wakeups at shutdown with HSW */ if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) pci_set_power_state(dev, PCI_D3hot); + + usb_hcd_pci_remove(dev); } #ifdef CONFIG_PM diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 918e0c739b79..797137e26549 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -850,6 +850,10 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg) spin_lock_irqsave(&xhci->lock, flags); ep->stop_cmds_pending--; + if (xhci->xhc_state & XHCI_STATE_REMOVING) { + spin_unlock_irqrestore(&xhci->lock, flags); + return; + } if (xhci->xhc_state & XHCI_STATE_DYING) { xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "Stop EP timer ran, but another timer marked " @@ -903,7 +907,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg) 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)->primary_hcd); + usb_hc_died(xhci_to_hcd(xhci)); xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, "xHCI host controller is dead."); } @@ -1334,12 +1338,6 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, cmd = list_entry(xhci->cmd_list.next, struct xhci_command, cmd_list); - if (cmd->command_trb != xhci->cmd_ring->dequeue) { - xhci_err(xhci, - "Command completion event does not match command\n"); - return; - } - del_timer(&xhci->cmd_timer); trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event); @@ -1351,6 +1349,13 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci_handle_stopped_cmd_ring(xhci, cmd); return; } + + if (cmd->command_trb != xhci->cmd_ring->dequeue) { + xhci_err(xhci, + "Command completion event does not match command\n"); + return; + } + /* * Host aborted the command ring, check if the current command was * supposed to be aborted, otherwise continue normally. @@ -3243,7 +3248,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, send_addr = addr; /* Queue the TRBs, even if they are zero-length */ - for (enqd_len = 0; enqd_len < full_len; enqd_len += trb_buff_len) { + for (enqd_len = 0; first_trb || enqd_len < full_len; + enqd_len += trb_buff_len) { field = TRB_TYPE(TRB_NORMAL); /* TRB buffer should not cross 64KB boundaries */ diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 0f53ae0f464e..a59fafb4b329 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -1033,7 +1033,6 @@ static int tegra_xusb_probe(struct platform_device *pdev) tegra->phys = devm_kcalloc(&pdev->dev, tegra->num_phys, sizeof(*tegra->phys), GFP_KERNEL); if (!tegra->phys) { - dev_err(&pdev->dev, "failed to allocate PHY array\n"); err = -ENOMEM; goto put_padctl; } @@ -1117,6 +1116,7 @@ static int tegra_xusb_probe(struct platform_device *pdev) tegra->hcd); if (!xhci->shared_hcd) { dev_err(&pdev->dev, "failed to create shared HCD\n"); + err = -ENOMEM; goto remove_usb2; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 01d96c9b3a75..1a4ca02729c2 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -295,10 +295,8 @@ static int xhci_setup_msix(struct xhci_hcd *xhci) xhci->msix_entries = kmalloc((sizeof(struct msix_entry))*xhci->msix_count, GFP_KERNEL); - if (!xhci->msix_entries) { - xhci_err(xhci, "Failed to allocate MSI-X entries\n"); + if (!xhci->msix_entries) return -ENOMEM; - } for (i = 0; i < xhci->msix_count; i++) { xhci->msix_entries[i].entry = i; |