diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mxc.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 16 | ||||
-rw-r--r-- | drivers/usb/host/isp1760-hcd.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/pci-quirks.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 19 |
6 files changed, 48 insertions, 7 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index bf2c8f65e1ae..e051b30c1847 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -1046,7 +1046,19 @@ static int ehci_hub_control ( | |||
1046 | if (!selector || selector > 5) | 1046 | if (!selector || selector > 5) |
1047 | goto error; | 1047 | goto error; |
1048 | ehci_quiesce(ehci); | 1048 | ehci_quiesce(ehci); |
1049 | |||
1050 | /* Put all enabled ports into suspend */ | ||
1051 | while (ports--) { | ||
1052 | u32 __iomem *sreg = | ||
1053 | &ehci->regs->port_status[ports]; | ||
1054 | |||
1055 | temp = ehci_readl(ehci, sreg) & ~PORT_RWC_BITS; | ||
1056 | if (temp & PORT_PE) | ||
1057 | ehci_writel(ehci, temp | PORT_SUSPEND, | ||
1058 | sreg); | ||
1059 | } | ||
1049 | ehci_halt(ehci); | 1060 | ehci_halt(ehci); |
1061 | temp = ehci_readl(ehci, status_reg); | ||
1050 | temp |= selector << 16; | 1062 | temp |= selector << 16; |
1051 | ehci_writel(ehci, temp, status_reg); | 1063 | ehci_writel(ehci, temp, status_reg); |
1052 | break; | 1064 | break; |
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 0c058be35a38..555a73c864b5 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/usb/ulpi.h> | 24 | #include <linux/usb/ulpi.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | 26 | ||
27 | #include <mach/hardware.h> | ||
27 | #include <mach/mxc_ehci.h> | 28 | #include <mach/mxc_ehci.h> |
28 | 29 | ||
29 | #include <asm/mach-types.h> | 30 | #include <asm/mach-types.h> |
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 55a57c23dd0f..45240321ca09 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -98,6 +98,18 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) | |||
98 | } | 98 | } |
99 | } | 99 | } |
100 | 100 | ||
101 | static void disable_put_regulator( | ||
102 | struct ehci_hcd_omap_platform_data *pdata) | ||
103 | { | ||
104 | int i; | ||
105 | |||
106 | for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { | ||
107 | if (pdata->regulator[i]) { | ||
108 | regulator_disable(pdata->regulator[i]); | ||
109 | regulator_put(pdata->regulator[i]); | ||
110 | } | ||
111 | } | ||
112 | } | ||
101 | 113 | ||
102 | /* configure so an HC device and id are always provided */ | 114 | /* configure so an HC device and id are always provided */ |
103 | /* always called with process context; sleeping is OK */ | 115 | /* always called with process context; sleeping is OK */ |
@@ -231,9 +243,11 @@ err_add_hcd: | |||
231 | omap_usbhs_disable(dev); | 243 | omap_usbhs_disable(dev); |
232 | 244 | ||
233 | err_enable: | 245 | err_enable: |
246 | disable_put_regulator(pdata); | ||
234 | usb_put_hcd(hcd); | 247 | usb_put_hcd(hcd); |
235 | 248 | ||
236 | err_io: | 249 | err_io: |
250 | iounmap(regs); | ||
237 | return ret; | 251 | return ret; |
238 | } | 252 | } |
239 | 253 | ||
@@ -253,6 +267,8 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) | |||
253 | 267 | ||
254 | usb_remove_hcd(hcd); | 268 | usb_remove_hcd(hcd); |
255 | omap_usbhs_disable(dev); | 269 | omap_usbhs_disable(dev); |
270 | disable_put_regulator(dev->platform_data); | ||
271 | iounmap(hcd->regs); | ||
256 | usb_put_hcd(hcd); | 272 | usb_put_hcd(hcd); |
257 | return 0; | 273 | return 0; |
258 | } | 274 | } |
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 55d3d5859ac5..840beda66dd9 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c | |||
@@ -1583,6 +1583,9 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, | |||
1583 | int retval = 0; | 1583 | int retval = 0; |
1584 | 1584 | ||
1585 | spin_lock_irqsave(&priv->lock, spinflags); | 1585 | spin_lock_irqsave(&priv->lock, spinflags); |
1586 | retval = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
1587 | if (retval) | ||
1588 | goto out; | ||
1586 | 1589 | ||
1587 | qh = urb->ep->hcpriv; | 1590 | qh = urb->ep->hcpriv; |
1588 | if (!qh) { | 1591 | if (!qh) { |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index a9d315906e3d..629a96813fd6 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -535,7 +535,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) | |||
535 | iounmap(base); | 535 | iounmap(base); |
536 | } | 536 | } |
537 | 537 | ||
538 | static const struct dmi_system_id __initconst ehci_dmi_nohandoff_table[] = { | 538 | static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { |
539 | { | 539 | { |
540 | /* Pegatron Lucid (ExoPC) */ | 540 | /* Pegatron Lucid (ExoPC) */ |
541 | .matches = { | 541 | .matches = { |
@@ -817,7 +817,7 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) | |||
817 | 817 | ||
818 | /* If the BIOS owns the HC, signal that the OS wants it, and wait */ | 818 | /* If the BIOS owns the HC, signal that the OS wants it, and wait */ |
819 | if (val & XHCI_HC_BIOS_OWNED) { | 819 | if (val & XHCI_HC_BIOS_OWNED) { |
820 | writel(val & XHCI_HC_OS_OWNED, base + ext_cap_offset); | 820 | writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset); |
821 | 821 | ||
822 | /* Wait for 5 seconds with 10 microsecond polling interval */ | 822 | /* Wait for 5 seconds with 10 microsecond polling interval */ |
823 | timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, | 823 | timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 763f484bc092..1c4432d8fc10 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -345,7 +345,8 @@ static void xhci_event_ring_work(unsigned long arg) | |||
345 | spin_lock_irqsave(&xhci->lock, flags); | 345 | spin_lock_irqsave(&xhci->lock, flags); |
346 | temp = xhci_readl(xhci, &xhci->op_regs->status); | 346 | temp = xhci_readl(xhci, &xhci->op_regs->status); |
347 | xhci_dbg(xhci, "op reg status = 0x%x\n", temp); | 347 | xhci_dbg(xhci, "op reg status = 0x%x\n", temp); |
348 | if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING)) { | 348 | if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) || |
349 | (xhci->xhc_state & XHCI_STATE_HALTED)) { | ||
349 | xhci_dbg(xhci, "HW died, polling stopped.\n"); | 350 | xhci_dbg(xhci, "HW died, polling stopped.\n"); |
350 | spin_unlock_irqrestore(&xhci->lock, flags); | 351 | spin_unlock_irqrestore(&xhci->lock, flags); |
351 | return; | 352 | return; |
@@ -939,8 +940,11 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, | |||
939 | return 0; | 940 | return 0; |
940 | } | 941 | } |
941 | 942 | ||
943 | xhci = hcd_to_xhci(hcd); | ||
944 | if (xhci->xhc_state & XHCI_STATE_HALTED) | ||
945 | return -ENODEV; | ||
946 | |||
942 | if (check_virt_dev) { | 947 | if (check_virt_dev) { |
943 | xhci = hcd_to_xhci(hcd); | ||
944 | if (!udev->slot_id || !xhci->devs | 948 | if (!udev->slot_id || !xhci->devs |
945 | || !xhci->devs[udev->slot_id]) { | 949 | || !xhci->devs[udev->slot_id]) { |
946 | printk(KERN_DEBUG "xHCI %s called with unaddressed " | 950 | printk(KERN_DEBUG "xHCI %s called with unaddressed " |
@@ -1242,7 +1246,8 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
1242 | xhci_urb_free_priv(xhci, urb_priv); | 1246 | xhci_urb_free_priv(xhci, urb_priv); |
1243 | return ret; | 1247 | return ret; |
1244 | } | 1248 | } |
1245 | if (xhci->xhc_state & XHCI_STATE_DYING) { | 1249 | if ((xhci->xhc_state & XHCI_STATE_DYING) || |
1250 | (xhci->xhc_state & XHCI_STATE_HALTED)) { | ||
1246 | xhci_dbg(xhci, "Ep 0x%x: URB %p to be canceled on " | 1251 | xhci_dbg(xhci, "Ep 0x%x: URB %p to be canceled on " |
1247 | "non-responsive xHCI host.\n", | 1252 | "non-responsive xHCI host.\n", |
1248 | urb->ep->desc.bEndpointAddress, urb); | 1253 | urb->ep->desc.bEndpointAddress, urb); |
@@ -2665,7 +2670,10 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
2665 | int i, ret; | 2670 | int i, ret; |
2666 | 2671 | ||
2667 | ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); | 2672 | ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); |
2668 | if (ret <= 0) | 2673 | /* If the host is halted due to driver unload, we still need to free the |
2674 | * device. | ||
2675 | */ | ||
2676 | if (ret <= 0 && ret != -ENODEV) | ||
2669 | return; | 2677 | return; |
2670 | 2678 | ||
2671 | virt_dev = xhci->devs[udev->slot_id]; | 2679 | virt_dev = xhci->devs[udev->slot_id]; |
@@ -2679,7 +2687,8 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
2679 | spin_lock_irqsave(&xhci->lock, flags); | 2687 | spin_lock_irqsave(&xhci->lock, flags); |
2680 | /* Don't disable the slot if the host controller is dead. */ | 2688 | /* Don't disable the slot if the host controller is dead. */ |
2681 | state = xhci_readl(xhci, &xhci->op_regs->status); | 2689 | state = xhci_readl(xhci, &xhci->op_regs->status); |
2682 | if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING)) { | 2690 | if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) || |
2691 | (xhci->xhc_state & XHCI_STATE_HALTED)) { | ||
2683 | xhci_free_virt_device(xhci, udev->slot_id); | 2692 | xhci_free_virt_device(xhci, udev->slot_id); |
2684 | spin_unlock_irqrestore(&xhci->lock, flags); | 2693 | spin_unlock_irqrestore(&xhci->lock, flags); |
2685 | return; | 2694 | return; |