diff options
Diffstat (limited to 'drivers/usb/host')
| -rw-r--r-- | drivers/usb/host/ehci-fsl.c | 7 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 12 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hub.c | 31 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-omap.c | 39 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-pci.c | 8 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-tegra.c | 3 | ||||
| -rw-r--r-- | drivers/usb/host/ehci.h | 2 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-at91.c | 12 | ||||
| -rw-r--r-- | drivers/usb/host/pci-quirks.c | 10 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-hub.c | 5 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-dbg.c | 2 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ext-caps.h | 5 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-mem.c | 9 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-pci.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 6 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.c | 12 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.h | 4 | 
17 files changed, 121 insertions, 50 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 3e7345172e0..d0a84bd3f3e 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -218,6 +218,9 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,  	u32 portsc;  	struct usb_hcd *hcd = ehci_to_hcd(ehci);  	void __iomem *non_ehci = hcd->regs; +	struct fsl_usb2_platform_data *pdata; + +	pdata = hcd->self.controller->platform_data;  	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);  	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); @@ -234,7 +237,9 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,  		/* fall through */  	case FSL_USB2_PHY_UTMI:  		/* enable UTMI PHY */ -		setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN); +		if (pdata->have_sysif_regs) +			setbits32(non_ehci + FSL_SOC_USB_CTRL, +				  CTRL_UTMI_PHY_EN);  		portsc |= PORT_PTS_UTMI;  		break;  	case FSL_USB2_PHY_NONE: diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 057cdda7a48..4a3bc5b7a06 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -347,6 +347,8 @@ static int ehci_reset (struct ehci_hcd *ehci)  	if (ehci->debug)  		dbgp_external_startup(); +	ehci->port_c_suspend = ehci->suspended_ports = +			ehci->resuming_ports = 0;  	return retval;  } @@ -856,8 +858,13 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  		goto dead;  	} +	/* +	 * We don't use STS_FLR, but some controllers don't like it to +	 * remain on, so mask it out along with the other status bits. +	 */ +	masked_status = status & (INTR_MASK | STS_FLR); +  	/* Shared IRQ? */ -	masked_status = status & INTR_MASK;  	if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {  		spin_unlock(&ehci->lock);  		return IRQ_NONE; @@ -908,7 +915,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  		pcd_status = status;  		/* resume root hub? */ -		if (!(cmd & CMD_RUN)) +		if (ehci->rh_state == EHCI_RH_SUSPENDED)  			usb_hcd_resume_root_hub(hcd);  		/* get per-port change detect bits */ @@ -939,6 +946,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  			 * like usb_port_resume() does.  			 */  			ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); +			set_bit(i, &ehci->resuming_ports);  			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);  			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);  		} diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 256fbd42e48..38fe0762315 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -223,15 +223,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)  	 * remote wakeup, we must fail the suspend.  	 */  	if (hcd->self.root_hub->do_remote_wakeup) { -		port = HCS_N_PORTS(ehci->hcs_params); -		while (port--) { -			if (ehci->reset_done[port] != 0) { -				spin_unlock_irq(&ehci->lock); -				ehci_dbg(ehci, "suspend failed because " -						"port %d is resuming\n", -						port + 1); -				return -EBUSY; -			} +		if (ehci->resuming_ports) { +			spin_unlock_irq(&ehci->lock); +			ehci_dbg(ehci, "suspend failed because a port is resuming\n"); +			return -EBUSY;  		}  	} @@ -554,16 +549,12 @@ static int  ehci_hub_status_data (struct usb_hcd *hcd, char *buf)  {  	struct ehci_hcd	*ehci = hcd_to_ehci (hcd); -	u32		temp, status = 0; +	u32		temp, status;  	u32		mask;  	int		ports, i, retval = 1;  	unsigned long	flags;  	u32		ppcd = 0; -	/* if !USB_SUSPEND, root hub timers won't get shut down ... */ -	if (ehci->rh_state != EHCI_RH_RUNNING) -		return 0; -  	/* init status to no-changes */  	buf [0] = 0;  	ports = HCS_N_PORTS (ehci->hcs_params); @@ -572,6 +563,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)  		retval++;  	} +	/* Inform the core about resumes-in-progress by returning +	 * a non-zero value even if there are no status changes. +	 */ +	status = ehci->resuming_ports; +  	/* Some boards (mostly VIA?) report bogus overcurrent indications,  	 * causing massive log spam unless we completely ignore them.  It  	 * may be relevant that VIA VT8235 controllers, where PORT_POWER is @@ -846,6 +842,7 @@ static int ehci_hub_control (  				ehci_writel(ehci,  					temp & ~(PORT_RWC_BITS | PORT_RESUME),  					status_reg); +				clear_bit(wIndex, &ehci->resuming_ports);  				retval = handshake(ehci, status_reg,  					   PORT_RESUME, 0, 2000 /* 2msec */);  				if (retval != 0) { @@ -864,6 +861,7 @@ static int ehci_hub_control (  					ehci->reset_done[wIndex])) {  			status |= USB_PORT_STAT_C_RESET << 16;  			ehci->reset_done [wIndex] = 0; +			clear_bit(wIndex, &ehci->resuming_ports);  			/* force reset to complete */  			ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET), @@ -884,8 +882,10 @@ static int ehci_hub_control (  					ehci_readl(ehci, status_reg));  		} -		if (!(temp & (PORT_RESUME|PORT_RESET))) +		if (!(temp & (PORT_RESUME|PORT_RESET))) {  			ehci->reset_done[wIndex] = 0; +			clear_bit(wIndex, &ehci->resuming_ports); +		}  		/* transfer dedicated ports to the companion hc */  		if ((temp & PORT_CONNECT) && @@ -920,6 +920,7 @@ static int ehci_hub_control (  			status |= USB_PORT_STAT_SUSPEND;  		} else if (test_bit(wIndex, &ehci->suspended_ports)) {  			clear_bit(wIndex, &ehci->suspended_ports); +			clear_bit(wIndex, &ehci->resuming_ports);  			ehci->reset_done[wIndex] = 0;  			if (temp & PORT_PE)  				set_bit(wIndex, &ehci->port_c_suspend); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index bba9850f32f..5c78f9e7146 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -42,6 +42,7 @@  #include <plat/usb.h>  #include <linux/regulator/consumer.h>  #include <linux/pm_runtime.h> +#include <linux/gpio.h>  /* EHCI Register Set */  #define EHCI_INSNREG04					(0xA0) @@ -191,6 +192,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)  		}  	} +	if (pdata->phy_reset) { +		if (gpio_is_valid(pdata->reset_gpio_port[0])) +			gpio_request_one(pdata->reset_gpio_port[0], +					 GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); + +		if (gpio_is_valid(pdata->reset_gpio_port[1])) +			gpio_request_one(pdata->reset_gpio_port[1], +					 GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); + +		/* Hold the PHY in RESET for enough time till DIR is high */ +		udelay(10); +	} +  	pm_runtime_enable(dev);  	pm_runtime_get_sync(dev); @@ -237,6 +251,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)  	/* root ports should always stay powered */  	ehci_port_power(omap_ehci, 1); +	if (pdata->phy_reset) { +		/* Hold the PHY in RESET for enough time till +		 * PHY is settled and ready +		 */ +		udelay(10); + +		if (gpio_is_valid(pdata->reset_gpio_port[0])) +			gpio_set_value(pdata->reset_gpio_port[0], 1); + +		if (gpio_is_valid(pdata->reset_gpio_port[1])) +			gpio_set_value(pdata->reset_gpio_port[1], 1); +	} +  	return 0;  err_add_hcd: @@ -259,8 +286,9 @@ err_io:   */  static int ehci_hcd_omap_remove(struct platform_device *pdev)  { -	struct device *dev	= &pdev->dev; -	struct usb_hcd *hcd	= dev_get_drvdata(dev); +	struct device *dev				= &pdev->dev; +	struct usb_hcd *hcd				= dev_get_drvdata(dev); +	struct ehci_hcd_omap_platform_data *pdata	= dev->platform_data;  	usb_remove_hcd(hcd);  	disable_put_regulator(dev->platform_data); @@ -269,6 +297,13 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)  	pm_runtime_put_sync(dev);  	pm_runtime_disable(dev); +	if (pdata->phy_reset) { +		if (gpio_is_valid(pdata->reset_gpio_port[0])) +			gpio_free(pdata->reset_gpio_port[0]); + +		if (gpio_is_valid(pdata->reset_gpio_port[1])) +			gpio_free(pdata->reset_gpio_port[1]); +	}  	return 0;  } diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 01bb7241d6e..fe8dc069164 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd)  			hcd->has_tt = 1;  			tdi_reset(ehci);  		} +		if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) { +			/* EHCI #1 or #2 on 6 Series/C200 Series chipset */ +			if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) { +				ehci_info(ehci, "broken D3 during system sleep on ASUS\n"); +				hcd->broken_pci_sleep = 1; +				device_set_wakeup_capable(&pdev->dev, false); +			} +		}  		break;  	case PCI_VENDOR_ID_TDI:  		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 3de48a2d795..86183366647 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -224,6 +224,7 @@ static int tegra_ehci_hub_control(  		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);  		/* start resume signalling */  		ehci_writel(ehci, temp | PORT_RESUME, status_reg); +		set_bit(wIndex-1, &ehci->resuming_ports);  		spin_unlock_irqrestore(&ehci->lock, flags);  		msleep(20); @@ -236,6 +237,7 @@ static int tegra_ehci_hub_control(  			pr_err("%s: timeout waiting for SUSPEND\n", __func__);  		ehci->reset_done[wIndex-1] = 0; +		clear_bit(wIndex-1, &ehci->resuming_ports);  		tegra->port_resuming = 1;  		goto done; @@ -729,7 +731,6 @@ static int tegra_ehci_probe(struct platform_device *pdev)  		err = -ENODEV;  		goto fail;  	} -	set_irq_flags(irq, IRQF_VALID);  #ifdef CONFIG_USB_OTG_UTILS  	if (pdata->operating_mode == TEGRA_USB_OTG) { diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 8f9acbc96fd..2694ed6558d 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -117,6 +117,8 @@ struct ehci_hcd {			/* one per controller */  			the change-suspend feature turned on */  	unsigned long		suspended_ports;	/* which ports are  			suspended */ +	unsigned long		resuming_ports;		/* which ports have +			started to resume */  	/* per-HC memory pools (could be per-bus, but ...) */  	struct dma_pool		*qh_pool;	/* qh per active urb */ diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 09f597ad6e0..13ebeca8e73 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -94,7 +94,7 @@ static void at91_stop_hc(struct platform_device *pdev)  /*-------------------------------------------------------------------------*/ -static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); +static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);  /* configure so an HC device and id are always provided */  /* always called with process context; sleeping is OK */ @@ -108,7 +108,7 @@ static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);   * then invokes the start() method for the HCD associated with it   * through the hotplug entry's driver_data.   */ -static int usb_hcd_at91_probe(const struct hc_driver *driver, +static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,  			struct platform_device *pdev)  {  	int retval; @@ -203,7 +203,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,   * context, "rmmod" or something similar.   *   */ -static void usb_hcd_at91_remove(struct usb_hcd *hcd, +static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,  				struct platform_device *pdev)  {  	usb_remove_hcd(hcd); @@ -545,7 +545,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)  /*-------------------------------------------------------------------------*/ -static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) +static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)  {  	struct at91_usbh_data	*pdata;  	int			i; @@ -620,7 +620,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)  	return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);  } -static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) +static int __devexit ohci_hcd_at91_drv_remove(struct platform_device *pdev)  {  	struct at91_usbh_data	*pdata = pdev->dev.platform_data;  	int			i; @@ -696,7 +696,7 @@ MODULE_ALIAS("platform:at91_ohci");  static struct platform_driver ohci_hcd_at91_driver = {  	.probe		= ohci_hcd_at91_drv_probe, -	.remove		= ohci_hcd_at91_drv_remove, +	.remove		= __devexit_p(ohci_hcd_at91_drv_remove),  	.shutdown	= usb_hcd_platform_shutdown,  	.suspend	= ohci_hcd_at91_drv_suspend,  	.resume		= ohci_hcd_at91_drv_resume, diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 11de5f1be98..32dada8c8b4 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -825,9 +825,13 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)  		}  	} -	/* Disable any BIOS SMIs */ -	writel(XHCI_LEGACY_DISABLE_SMI, -			base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); +	val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); +	/* Mask off (turn off) any enabled SMIs */ +	val &= XHCI_LEGACY_DISABLE_SMI; +	/* Mask all SMI events bits, RW1C */ +	val |= XHCI_LEGACY_SMI_EVENTS; +	/* Disable any BIOS SMIs and clear all SMI events*/ +	writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);  	if (usb_is_intel_switchable_xhci(pdev))  		usb_enable_xhci_ports(pdev); diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 045cde4cbc3..768d54295a2 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -196,11 +196,12 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)  	status = get_hub_status_data(uhci, buf);  	switch (uhci->rh_state) { -	    case UHCI_RH_SUSPENDING:  	    case UHCI_RH_SUSPENDED:  		/* if port change, ask to be resumed */ -		if (status || uhci->resuming_ports) +		if (status || uhci->resuming_ports) { +			status = 1;  			usb_hcd_resume_root_hub(hcd); +		}  		break;  	    case UHCI_RH_AUTO_STOPPED: diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index e9b0f043455..4b436f5a417 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -119,7 +119,7 @@ static void xhci_print_command_reg(struct xhci_hcd *xhci)  	xhci_dbg(xhci, "  Event Interrupts %s\n",  			(temp & CMD_EIE) ? "enabled " : "disabled");  	xhci_dbg(xhci, "  Host System Error Interrupts %s\n", -			(temp & CMD_EIE) ? "enabled " : "disabled"); +			(temp & CMD_HSEIE) ? "enabled " : "disabled");  	xhci_dbg(xhci, "  HC has %sfinished light reset\n",  			(temp & CMD_LRESET) ? "not " : "");  } diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h index c7f33123d4c..377f4242dab 100644 --- a/drivers/usb/host/xhci-ext-caps.h +++ b/drivers/usb/host/xhci-ext-caps.h @@ -62,8 +62,9 @@  /* USB Legacy Support Control and Status Register  - section 7.1.2 */  /* Add this offset, plus the value of xECP in HCCPARAMS to the base address */  #define XHCI_LEGACY_CONTROL_OFFSET	(0x04) -/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ -#define	XHCI_LEGACY_DISABLE_SMI		((0x3 << 1) + (0xff << 5) + (0x7 << 17)) +/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ +#define	XHCI_LEGACY_DISABLE_SMI		((0x7 << 1) + (0xff << 5) + (0x7 << 17)) +#define XHCI_LEGACY_SMI_EVENTS		(0x7 << 29)  /* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */  #define XHCI_L1C               (1 << 16) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index cae4c6f2845..68eaa908ac8 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1796,11 +1796,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)  	int i;  	/* Free the Event Ring Segment Table and the actual Event Ring */ -	if (xhci->ir_set) { -		xhci_writel(xhci, 0, &xhci->ir_set->erst_size); -		xhci_write_64(xhci, 0, &xhci->ir_set->erst_base); -		xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue); -	}  	size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);  	if (xhci->erst.entries)  		dma_free_coherent(&pdev->dev, size, @@ -1812,7 +1807,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)  	xhci->event_ring = NULL;  	xhci_dbg(xhci, "Freed event ring\n"); -	xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);  	if (xhci->cmd_ring)  		xhci_ring_free(xhci, xhci->cmd_ring);  	xhci->cmd_ring = NULL; @@ -1841,7 +1835,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)  	xhci->medium_streams_pool = NULL;  	xhci_dbg(xhci, "Freed medium stream array pool\n"); -	xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);  	if (xhci->dcbaa)  		dma_free_coherent(&pdev->dev, sizeof(*xhci->dcbaa),  				xhci->dcbaa, xhci->dcbaa->dma); @@ -2459,6 +2452,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)  fail:  	xhci_warn(xhci, "Couldn't initialize memory\n"); +	xhci_halt(xhci); +	xhci_reset(xhci);  	xhci_mem_cleanup(xhci);  	return -ENOMEM;  } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index ef98b38626f..7a856a767e7 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -95,6 +95,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)  		xhci->quirks |= XHCI_RESET_ON_RESUME;  		xhci_dbg(xhci, "QUIRK: Resetting on resume\n");  	} +	if (pdev->vendor == PCI_VENDOR_ID_VIA) +		xhci->quirks |= XHCI_RESET_ON_RESUME;  }  /* called during probe() after chip reset completes */ @@ -326,7 +328,7 @@ int __init xhci_register_pci(void)  	return pci_register_driver(&xhci_pci_driver);  } -void __exit xhci_unregister_pci(void) +void xhci_unregister_pci(void)  {  	pci_unregister_driver(&xhci_pci_driver);  } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 6bd9d53062e..3d9422f16a2 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2417,7 +2417,7 @@ hw_died:  		u32 irq_pending;  		/* Acknowledge the PCI interrupt */  		irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); -		irq_pending |= 0x3; +		irq_pending |= IMAN_IP;  		xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending);  	} @@ -2734,7 +2734,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  				urb->dev->speed == USB_SPEED_FULL)  			urb->interval /= 8;  	} -	return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); +	return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index);  }  /* @@ -3514,7 +3514,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,  	}  	ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free; -	return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); +	return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index);  }  /****		Command Ring Operations		****/ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index e1963d4a430..36641a7f237 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -106,6 +106,9 @@ int xhci_halt(struct xhci_hcd *xhci)  			STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);  	if (!ret)  		xhci->xhc_state |= XHCI_STATE_HALTED; +	else +		xhci_warn(xhci, "Host not halted after %u microseconds.\n", +				XHCI_MAX_HALT_USEC);  	return ret;  } @@ -664,11 +667,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci)  	xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification);  	xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);  	xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg); -	xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); -	xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);  	xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size);  	xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);  	xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); +	xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); +	xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);  }  static void xhci_restore_registers(struct xhci_hcd *xhci) @@ -677,10 +680,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci)  	xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification);  	xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);  	xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg); -	xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending); -	xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);  	xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size);  	xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base); +	xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue); +	xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending); +	xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);  }  static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 91074fdab3e..3d69c4b2b54 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -205,6 +205,10 @@ struct xhci_op_regs {  #define CMD_PM_INDEX	(1 << 11)  /* bits 12:31 are reserved (and should be preserved on writes). */ +/* IMAN - Interrupt Management Register */ +#define IMAN_IP		(1 << 1) +#define IMAN_IE		(1 << 0) +  /* USBSTS - USB status - status bitmasks */  /* HC not running - set to 1 when run/stop bit is cleared. */  #define STS_HALT	XHCI_STS_HALT  |