aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/ehci-hcd.c6
-rw-r--r--drivers/usb/host/ehci-hub.c67
-rw-r--r--drivers/usb/host/ehci-pci.c40
-rw-r--r--drivers/usb/host/ehci.h1
4 files changed, 61 insertions, 53 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index f2ceb5fdbeb7..025d33313681 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -619,9 +619,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
619 unsigned i = HCS_N_PORTS (ehci->hcs_params); 619 unsigned i = HCS_N_PORTS (ehci->hcs_params);
620 620
621 /* resume root hub? */ 621 /* resume root hub? */
622 status = readl (&ehci->regs->command); 622 if (!(readl(&ehci->regs->command) & CMD_RUN))
623 if (!(status & CMD_RUN)) 623 usb_hcd_resume_root_hub(hcd);
624 writel (status | CMD_RUN, &ehci->regs->command);
625 624
626 while (i--) { 625 while (i--) {
627 int pstatus = readl (&ehci->regs->port_status [i]); 626 int pstatus = readl (&ehci->regs->port_status [i]);
@@ -638,7 +637,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
638 */ 637 */
639 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); 638 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
640 ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); 639 ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
641 usb_hcd_resume_root_hub(hcd);
642 } 640 }
643 } 641 }
644 642
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 0a56dfa2745d..bfe5f307cba6 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -34,6 +34,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
34{ 34{
35 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 35 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
36 int port; 36 int port;
37 int mask;
37 38
38 if (time_before (jiffies, ehci->next_statechange)) 39 if (time_before (jiffies, ehci->next_statechange))
39 msleep(5); 40 msleep(5);
@@ -51,14 +52,25 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
51 ehci->reclaim_ready = 1; 52 ehci->reclaim_ready = 1;
52 ehci_work(ehci); 53 ehci_work(ehci);
53 54
54 /* suspend any active/unsuspended ports, maybe allow wakeup */ 55 /* Unlike other USB host controller types, EHCI doesn't have
56 * any notion of "global" or bus-wide suspend. The driver has
57 * to manually suspend all the active unsuspended ports, and
58 * then manually resume them in the bus_resume() routine.
59 */
60 ehci->bus_suspended = 0;
55 while (port--) { 61 while (port--) {
56 u32 __iomem *reg = &ehci->regs->port_status [port]; 62 u32 __iomem *reg = &ehci->regs->port_status [port];
57 u32 t1 = readl (reg) & ~PORT_RWC_BITS; 63 u32 t1 = readl (reg) & ~PORT_RWC_BITS;
58 u32 t2 = t1; 64 u32 t2 = t1;
59 65
60 if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) 66 /* keep track of which ports we suspend */
67 if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
68 !(t1 & PORT_SUSPEND)) {
61 t2 |= PORT_SUSPEND; 69 t2 |= PORT_SUSPEND;
70 set_bit(port, &ehci->bus_suspended);
71 }
72
73 /* enable remote wakeup on all ports */
62 if (device_may_wakeup(&hcd->self.root_hub->dev)) 74 if (device_may_wakeup(&hcd->self.root_hub->dev))
63 t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; 75 t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
64 else 76 else
@@ -76,6 +88,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
76 ehci_halt (ehci); 88 ehci_halt (ehci);
77 hcd->state = HC_STATE_SUSPENDED; 89 hcd->state = HC_STATE_SUSPENDED;
78 90
91 /* allow remote wakeup */
92 mask = INTR_MASK;
93 if (!device_may_wakeup(&hcd->self.root_hub->dev))
94 mask &= ~STS_PCD;
95 writel(mask, &ehci->regs->intr_enable);
96 readl(&ehci->regs->intr_enable);
97
79 ehci->next_statechange = jiffies + msecs_to_jiffies(10); 98 ehci->next_statechange = jiffies + msecs_to_jiffies(10);
80 spin_unlock_irq (&ehci->lock); 99 spin_unlock_irq (&ehci->lock);
81 return 0; 100 return 0;
@@ -88,7 +107,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
88 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 107 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
89 u32 temp; 108 u32 temp;
90 int i; 109 int i;
91 int intr_enable;
92 110
93 if (time_before (jiffies, ehci->next_statechange)) 111 if (time_before (jiffies, ehci->next_statechange))
94 msleep(5); 112 msleep(5);
@@ -100,31 +118,30 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
100 * the last user of the controller, not reset/pm hardware keeping 118 * the last user of the controller, not reset/pm hardware keeping
101 * state we gave to it. 119 * state we gave to it.
102 */ 120 */
121 temp = readl(&ehci->regs->intr_enable);
122 ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
103 123
104 /* re-init operational registers in case we lost power */ 124 /* at least some APM implementations will try to deliver
105 if (readl (&ehci->regs->intr_enable) == 0) { 125 * IRQs right away, so delay them until we're ready.
106 /* at least some APM implementations will try to deliver 126 */
107 * IRQs right away, so delay them until we're ready. 127 writel(0, &ehci->regs->intr_enable);
108 */ 128
109 intr_enable = 1; 129 /* re-init operational registers */
110 writel (0, &ehci->regs->segment); 130 writel(0, &ehci->regs->segment);
111 writel (ehci->periodic_dma, &ehci->regs->frame_list); 131 writel(ehci->periodic_dma, &ehci->regs->frame_list);
112 writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); 132 writel((u32) ehci->async->qh_dma, &ehci->regs->async_next);
113 } else
114 intr_enable = 0;
115 ehci_dbg(ehci, "resume root hub%s\n",
116 intr_enable ? " after power loss" : "");
117 133
118 /* restore CMD_RUN, framelist size, and irq threshold */ 134 /* restore CMD_RUN, framelist size, and irq threshold */
119 writel (ehci->command, &ehci->regs->command); 135 writel (ehci->command, &ehci->regs->command);
120 136
121 /* take ports out of suspend */ 137 /* manually resume the ports we suspended during bus_suspend() */
122 i = HCS_N_PORTS (ehci->hcs_params); 138 i = HCS_N_PORTS (ehci->hcs_params);
123 while (i--) { 139 while (i--) {
124 temp = readl (&ehci->regs->port_status [i]); 140 temp = readl (&ehci->regs->port_status [i]);
125 temp &= ~(PORT_RWC_BITS 141 temp &= ~(PORT_RWC_BITS
126 | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); 142 | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
127 if (temp & PORT_SUSPEND) { 143 if (test_bit(i, &ehci->bus_suspended) &&
144 (temp & PORT_SUSPEND)) {
128 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); 145 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
129 temp |= PORT_RESUME; 146 temp |= PORT_RESUME;
130 } 147 }
@@ -134,11 +151,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
134 mdelay (20); 151 mdelay (20);
135 while (i--) { 152 while (i--) {
136 temp = readl (&ehci->regs->port_status [i]); 153 temp = readl (&ehci->regs->port_status [i]);
137 if ((temp & PORT_SUSPEND) == 0) 154 if (test_bit(i, &ehci->bus_suspended) &&
138 continue; 155 (temp & PORT_SUSPEND)) {
139 temp &= ~(PORT_RWC_BITS | PORT_RESUME); 156 temp &= ~(PORT_RWC_BITS | PORT_RESUME);
140 writel (temp, &ehci->regs->port_status [i]); 157 writel (temp, &ehci->regs->port_status [i]);
141 ehci_vdbg (ehci, "resumed port %d\n", i + 1); 158 ehci_vdbg (ehci, "resumed port %d\n", i + 1);
159 }
142 } 160 }
143 (void) readl (&ehci->regs->command); 161 (void) readl (&ehci->regs->command);
144 162
@@ -157,8 +175,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
157 hcd->state = HC_STATE_RUNNING; 175 hcd->state = HC_STATE_RUNNING;
158 176
159 /* Now we can safely re-enable irqs */ 177 /* Now we can safely re-enable irqs */
160 if (intr_enable) 178 writel(INTR_MASK, &ehci->regs->intr_enable);
161 writel (INTR_MASK, &ehci->regs->intr_enable);
162 179
163 spin_unlock_irq (&ehci->lock); 180 spin_unlock_irq (&ehci->lock);
164 return 0; 181 return 0;
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index e51c1ed81ac4..4bc7970ba3ef 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -257,9 +257,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
257static int ehci_pci_resume(struct usb_hcd *hcd) 257static int ehci_pci_resume(struct usb_hcd *hcd)
258{ 258{
259 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 259 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
260 unsigned port;
261 struct pci_dev *pdev = to_pci_dev(hcd->self.controller); 260 struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
262 int retval = -EINVAL;
263 261
264 // maybe restore FLADJ 262 // maybe restore FLADJ
265 263
@@ -269,27 +267,19 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
269 /* Mark hardware accessible again as we are out of D3 state by now */ 267 /* Mark hardware accessible again as we are out of D3 state by now */
270 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 268 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
271 269
272 /* If CF is clear, we lost PCI Vaux power and need to restart. */ 270 /* If CF is still set, we maintained PCI Vaux power.
273 if (readl(&ehci->regs->configured_flag) != FLAG_CF) 271 * Just undo the effect of ehci_pci_suspend().
274 goto restart;
275
276 /* If any port is suspended (or owned by the companion),
277 * we know we can/must resume the HC (and mustn't reset it).
278 * We just defer that to the root hub code.
279 */ 272 */
280 for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) { 273 if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
281 u32 status; 274 int mask = INTR_MASK;
282 port--; 275
283 status = readl(&ehci->regs->port_status [port]); 276 if (!device_may_wakeup(&hcd->self.root_hub->dev))
284 if (!(status & PORT_POWER)) 277 mask &= ~STS_PCD;
285 continue; 278 writel(mask, &ehci->regs->intr_enable);
286 if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) { 279 readl(&ehci->regs->intr_enable);
287 usb_hcd_resume_root_hub(hcd); 280 return 0;
288 return 0;
289 }
290 } 281 }
291 282
292restart:
293 ehci_dbg(ehci, "lost power, restarting\n"); 283 ehci_dbg(ehci, "lost power, restarting\n");
294 usb_root_hub_lost_power(hcd->self.root_hub); 284 usb_root_hub_lost_power(hcd->self.root_hub);
295 285
@@ -307,13 +297,15 @@ restart:
307 ehci_work(ehci); 297 ehci_work(ehci);
308 spin_unlock_irq(&ehci->lock); 298 spin_unlock_irq(&ehci->lock);
309 299
310 /* restart; khubd will disconnect devices */
311 retval = ehci_run(hcd);
312
313 /* here we "know" root ports should always stay powered */ 300 /* here we "know" root ports should always stay powered */
314 ehci_port_power(ehci, 1); 301 ehci_port_power(ehci, 1);
315 302
316 return retval; 303 writel(ehci->command, &ehci->regs->command);
304 writel(FLAG_CF, &ehci->regs->configured_flag);
305 readl(&ehci->regs->command); /* unblock posted writes */
306
307 hcd->state = HC_STATE_SUSPENDED;
308 return 0;
317} 309}
318#endif 310#endif
319 311
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bbc3082a73d7..74dbc6c8228f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -74,6 +74,7 @@ struct ehci_hcd { /* one per controller */
74 74
75 /* per root hub port */ 75 /* per root hub port */
76 unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; 76 unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
77 unsigned long bus_suspended;
77 78
78 /* per-HC memory pools (could be per-bus, but ...) */ 79 /* per-HC memory pools (could be per-bus, but ...) */
79 struct dma_pool *qh_pool; /* qh per active urb */ 80 struct dma_pool *qh_pool; /* qh per active urb */