diff options
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
| -rw-r--r-- | drivers/usb/host/ehci-hub.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index e7d3d8def282..796ea0c8900f 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
| @@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) | |||
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | 109 | static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, |
| 110 | bool suspending) | 110 | bool suspending, bool do_wakeup) |
| 111 | { | 111 | { |
| 112 | int port; | 112 | int port; |
| 113 | u32 temp; | 113 | u32 temp; |
| @@ -117,8 +117,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | |||
| 117 | * when the controller is suspended or resumed. In all other | 117 | * when the controller is suspended or resumed. In all other |
| 118 | * cases they don't need to be changed. | 118 | * cases they don't need to be changed. |
| 119 | */ | 119 | */ |
| 120 | if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || | 120 | if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup) |
| 121 | device_may_wakeup(ehci_to_hcd(ehci)->self.controller)) | ||
| 122 | return; | 121 | return; |
| 123 | 122 | ||
| 124 | /* clear phy low-power mode before changing wakeup flags */ | 123 | /* clear phy low-power mode before changing wakeup flags */ |
| @@ -167,6 +166,10 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | |||
| 167 | ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); | 166 | ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); |
| 168 | } | 167 | } |
| 169 | } | 168 | } |
| 169 | |||
| 170 | /* Does the root hub have a port wakeup pending? */ | ||
| 171 | if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)) | ||
| 172 | usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); | ||
| 170 | } | 173 | } |
| 171 | 174 | ||
| 172 | static int ehci_bus_suspend (struct usb_hcd *hcd) | 175 | static int ehci_bus_suspend (struct usb_hcd *hcd) |
| @@ -316,7 +319,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
| 316 | if (time_before (jiffies, ehci->next_statechange)) | 319 | if (time_before (jiffies, ehci->next_statechange)) |
| 317 | msleep(5); | 320 | msleep(5); |
| 318 | spin_lock_irq (&ehci->lock); | 321 | spin_lock_irq (&ehci->lock); |
| 319 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 322 | if (!HCD_HW_ACCESSIBLE(hcd)) { |
| 320 | spin_unlock_irq(&ehci->lock); | 323 | spin_unlock_irq(&ehci->lock); |
| 321 | return -ESHUTDOWN; | 324 | return -ESHUTDOWN; |
| 322 | } | 325 | } |
| @@ -603,6 +606,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
| 603 | u32 mask; | 606 | u32 mask; |
| 604 | int ports, i, retval = 1; | 607 | int ports, i, retval = 1; |
| 605 | unsigned long flags; | 608 | unsigned long flags; |
| 609 | u32 ppcd = 0; | ||
| 606 | 610 | ||
| 607 | /* if !USB_SUSPEND, root hub timers won't get shut down ... */ | 611 | /* if !USB_SUSPEND, root hub timers won't get shut down ... */ |
| 608 | if (!HC_IS_RUNNING(hcd->state)) | 612 | if (!HC_IS_RUNNING(hcd->state)) |
| @@ -632,7 +636,15 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
| 632 | 636 | ||
| 633 | /* port N changes (bit N)? */ | 637 | /* port N changes (bit N)? */ |
| 634 | spin_lock_irqsave (&ehci->lock, flags); | 638 | spin_lock_irqsave (&ehci->lock, flags); |
| 639 | |||
| 640 | /* get per-port change detect bits */ | ||
| 641 | if (ehci->has_ppcd) | ||
| 642 | ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16; | ||
| 643 | |||
| 635 | for (i = 0; i < ports; i++) { | 644 | for (i = 0; i < ports; i++) { |
| 645 | /* leverage per-port change bits feature */ | ||
| 646 | if (ehci->has_ppcd && !(ppcd & (1 << i))) | ||
| 647 | continue; | ||
| 636 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); | 648 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
| 637 | 649 | ||
| 638 | /* | 650 | /* |
| @@ -790,6 +802,11 @@ static int ehci_hub_control ( | |||
| 790 | status_reg); | 802 | status_reg); |
| 791 | break; | 803 | break; |
| 792 | case USB_PORT_FEAT_C_CONNECTION: | 804 | case USB_PORT_FEAT_C_CONNECTION: |
| 805 | if (ehci->has_lpm) { | ||
| 806 | /* clear PORTSC bits on disconnect */ | ||
| 807 | temp &= ~PORT_LPM; | ||
| 808 | temp &= ~PORT_DEV_ADDR; | ||
| 809 | } | ||
| 793 | ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, | 810 | ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, |
| 794 | status_reg); | 811 | status_reg); |
| 795 | break; | 812 | break; |
