diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:05:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:05:02 -0400 |
commit | 9895850b23886e030cd1e7241d5529a57e969c3d (patch) | |
tree | 1061626db450aeb72dcfcd247c24b33e5238c8c4 /drivers/usb/host/ehci-hub.c | |
parent | fc385c313275b114bc6ad36e60c5177d63250548 (diff) | |
parent | b58af4066d240b18b43f202e07b9ec7461d90b17 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (148 commits)
USB: serial: fix stalled writes
USB: remove fake "address-of" expressions
USB: fix thread-unsafe anchor utiliy routines
USB: usbtest: support test device with only one iso-in or iso-out endpoint
USB: usbtest: avoid to free coherent buffer in atomic context
USB: xhci: Set DMA mask for host.
USB: xhci: Don't flush doorbell writes.
USB: xhci: Reduce reads and writes of interrupter registers.
USB: xhci: Make xhci_set_hc_event_deq() static.
USB: xhci: Minimize HW event ring dequeue pointer writes.
USB: xhci: Make xhci_handle_event() static.
USB: xhci: Remove unnecessary reads of IRQ_PENDING register.
USB: xhci: Performance - move xhci_work() into xhci_irq()
USB: xhci: Performance - move interrupt handlers into xhci-ring.c
USB: xhci: Performance - move functions that find ep ring.
USB:: fix linux/usb.h kernel-doc warnings
USB: add USB serial ssu100 driver
USB: usb-storage: implement autosuspend
USB: ehci: fix remove of ehci debugfs dir
USB: Add USB 2.0 to ssb ohci driver
...
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 e7d3d8def28..796ea0c8900 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; |