aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-hub.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-09-26 14:46:16 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-28 18:36:46 -0400
commit8d1a243ba5dda5c1a3cca5df8fb19ab8b138f074 (patch)
treec9be9a9d8d4f5477a47bfc5f8a6f612a0c4867ca /drivers/usb/host/ohci-hub.c
parent1f7e1a3b7e05c833229c4b6e9d3c96262df59e99 (diff)
OHCI: add auto-stop support
This patch (as790b) adds "autostop" support to ohci-hcd: the driver will automatically stop the host controller when no devices have been connected for at least one second. This feature is useful when the USB autosuspend facility isn't available, such as when CONFIG_USB_SUSPEND hasn't been set. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ohci-hub.c')
-rw-r--r--drivers/usb/host/ohci-hub.c229
1 files changed, 156 insertions, 73 deletions
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index ef4965450de5..f36cbd02736d 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -41,31 +41,20 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
41{ 41{
42 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 42 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
43 43
44 hcd->poll_rh = 0;
45 ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); 44 ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
46} 45}
47 46
48#ifdef CONFIG_PM
49
50#define OHCI_SCHED_ENABLES \ 47#define OHCI_SCHED_ENABLES \
51 (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) 48 (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
52 49
53static void dl_done_list (struct ohci_hcd *, struct pt_regs *); 50static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
54static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); 51static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
55static int ohci_restart (struct ohci_hcd *ohci);
56 52
57static int ohci_bus_suspend (struct usb_hcd *hcd) 53static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
54__releases(ohci->lock)
55__acquires(ohci->lock)
58{ 56{
59 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
60 int status = 0; 57 int status = 0;
61 unsigned long flags;
62
63 spin_lock_irqsave (&ohci->lock, flags);
64
65 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
66 spin_unlock_irqrestore (&ohci->lock, flags);
67 return -ESHUTDOWN;
68 }
69 58
70 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); 59 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
71 switch (ohci->hc_control & OHCI_CTRL_HCFS) { 60 switch (ohci->hc_control & OHCI_CTRL_HCFS) {
@@ -81,15 +70,16 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
81 ohci_dbg (ohci, "needs reinit!\n"); 70 ohci_dbg (ohci, "needs reinit!\n");
82 goto done; 71 goto done;
83 case OHCI_USB_SUSPEND: 72 case OHCI_USB_SUSPEND:
84 ohci_dbg (ohci, "already suspended\n"); 73 if (!ohci->autostop) {
85 goto done; 74 ohci_dbg (ohci, "already suspended\n");
75 goto done;
76 }
86 } 77 }
87 ohci_dbg (ohci, "suspend root hub\n"); 78 ohci_dbg (ohci, "%s root hub\n",
79 autostop ? "auto-stop" : "suspend");
88 80
89 /* First stop any processing */ 81 /* First stop any processing */
90 if (ohci->hc_control & OHCI_SCHED_ENABLES) { 82 if (!autostop && (ohci->hc_control & OHCI_SCHED_ENABLES)) {
91 int limit;
92
93 ohci->hc_control &= ~OHCI_SCHED_ENABLES; 83 ohci->hc_control &= ~OHCI_SCHED_ENABLES;
94 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 84 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
95 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); 85 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
@@ -99,24 +89,17 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
99 * then the last WDH could take 6+ msec 89 * then the last WDH could take 6+ msec
100 */ 90 */
101 ohci_dbg (ohci, "stopping schedules ...\n"); 91 ohci_dbg (ohci, "stopping schedules ...\n");
102 limit = 2000; 92 ohci->autostop = 0;
103 while (limit > 0) { 93 spin_unlock_irq (&ohci->lock);
104 udelay (250); 94 msleep (8);
105 limit =- 250; 95 spin_lock_irq (&ohci->lock);
106 if (ohci_readl (ohci, &ohci->regs->intrstatus)
107 & OHCI_INTR_SF)
108 break;
109 }
110 dl_done_list (ohci, NULL);
111 mdelay (7);
112 } 96 }
113 dl_done_list (ohci, NULL); 97 dl_done_list (ohci, NULL);
114 finish_unlinks (ohci, ohci_frame_no(ohci), NULL); 98 finish_unlinks (ohci, ohci_frame_no(ohci), NULL);
115 ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
116 &ohci->regs->intrstatus);
117 99
118 /* maybe resume can wake root hub */ 100 /* maybe resume can wake root hub */
119 if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev)) 101 if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
102 autostop)
120 ohci->hc_control |= OHCI_CTRL_RWE; 103 ohci->hc_control |= OHCI_CTRL_RWE;
121 else { 104 else {
122 ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable); 105 ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
@@ -132,13 +115,12 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
132 (void) ohci_readl (ohci, &ohci->regs->control); 115 (void) ohci_readl (ohci, &ohci->regs->control);
133 116
134 /* no resumes until devices finish suspending */ 117 /* no resumes until devices finish suspending */
135 ohci->next_statechange = jiffies + msecs_to_jiffies (5); 118 if (!autostop) {
136 119 ohci->next_statechange = jiffies + msecs_to_jiffies (5);
137 /* no timer polling */ 120 ohci->autostop = 0;
138 hcd->poll_rh = 0; 121 }
139 122
140done: 123done:
141 spin_unlock_irqrestore (&ohci->lock, flags);
142 return status; 124 return status;
143} 125}
144 126
@@ -151,24 +133,16 @@ static inline struct ed *find_head (struct ed *ed)
151} 133}
152 134
153/* caller has locked the root hub */ 135/* caller has locked the root hub */
154static int ohci_bus_resume (struct usb_hcd *hcd) 136static int ohci_rh_resume (struct ohci_hcd *ohci)
137__releases(ohci->lock)
138__acquires(ohci->lock)
155{ 139{
156 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 140 struct usb_hcd *hcd = ohci_to_hcd (ohci);
157 u32 temp, enables; 141 u32 temp, enables;
158 int status = -EINPROGRESS; 142 int status = -EINPROGRESS;
159 unsigned long flags; 143 int autostopped = ohci->autostop;
160
161 if (time_before (jiffies, ohci->next_statechange))
162 msleep(5);
163
164 spin_lock_irqsave (&ohci->lock, flags);
165
166 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
167 spin_unlock_irqrestore (&ohci->lock, flags);
168 return -ESHUTDOWN;
169 }
170
171 144
145 ohci->autostop = 0;
172 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); 146 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
173 147
174 if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { 148 if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
@@ -188,7 +162,8 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
188 ohci->hc_control |= OHCI_USB_RESUME; 162 ohci->hc_control |= OHCI_USB_RESUME;
189 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 163 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
190 (void) ohci_readl (ohci, &ohci->regs->control); 164 (void) ohci_readl (ohci, &ohci->regs->control);
191 ohci_dbg (ohci, "resume root hub\n"); 165 ohci_dbg (ohci, "%s root hub\n",
166 autostopped ? "auto-start" : "resume");
192 break; 167 break;
193 case OHCI_USB_RESUME: 168 case OHCI_USB_RESUME:
194 /* HCFS changes sometime after INTR_RD */ 169 /* HCFS changes sometime after INTR_RD */
@@ -203,16 +178,26 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
203 ohci_dbg (ohci, "lost power\n"); 178 ohci_dbg (ohci, "lost power\n");
204 status = -EBUSY; 179 status = -EBUSY;
205 } 180 }
206 spin_unlock_irqrestore (&ohci->lock, flags); 181#ifdef CONFIG_PM
207 if (status == -EBUSY) { 182 if (status == -EBUSY) {
208 (void) ohci_init (ohci); 183 if (!autostopped) {
209 return ohci_restart (ohci); 184 static int ohci_restart (struct ohci_hcd *ohci);
185
186 spin_unlock_irq (&ohci->lock);
187 (void) ohci_init (ohci);
188 status = ohci_restart (ohci);
189 spin_lock_irq (&ohci->lock);
190 }
191 return status;
210 } 192 }
193#endif
211 if (status != -EINPROGRESS) 194 if (status != -EINPROGRESS)
212 return status; 195 return status;
196 if (autostopped)
197 goto skip_resume;
198 spin_unlock_irq (&ohci->lock);
213 199
214 temp = ohci->num_ports; 200 temp = ohci->num_ports;
215 enables = 0;
216 while (temp--) { 201 while (temp--) {
217 u32 stat = ohci_readl (ohci, 202 u32 stat = ohci_readl (ohci,
218 &ohci->regs->roothub.portstatus [temp]); 203 &ohci->regs->roothub.portstatus [temp]);
@@ -245,17 +230,21 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
245 /* Sometimes PCI D3 suspend trashes frame timings ... */ 230 /* Sometimes PCI D3 suspend trashes frame timings ... */
246 periodic_reinit (ohci); 231 periodic_reinit (ohci);
247 232
233 /* the following code is executed with ohci->lock held and
234 * irqs disabled if and only if autostopped is true
235 */
236
237skip_resume:
248 /* interrupts might have been disabled */ 238 /* interrupts might have been disabled */
249 ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable); 239 ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
250 if (ohci->ed_rm_list) 240 if (ohci->ed_rm_list)
251 ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable); 241 ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable);
252 ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus),
253 &ohci->regs->intrstatus);
254 242
255 /* Then re-enable operations */ 243 /* Then re-enable operations */
256 ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control); 244 ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control);
257 (void) ohci_readl (ohci, &ohci->regs->control); 245 (void) ohci_readl (ohci, &ohci->regs->control);
258 msleep (3); 246 if (!autostopped)
247 msleep (3);
259 248
260 temp = ohci->hc_control; 249 temp = ohci->hc_control;
261 temp &= OHCI_CTRL_RWC; 250 temp &= OHCI_CTRL_RWC;
@@ -265,7 +254,11 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
265 (void) ohci_readl (ohci, &ohci->regs->control); 254 (void) ohci_readl (ohci, &ohci->regs->control);
266 255
267 /* TRSMRCY */ 256 /* TRSMRCY */
268 msleep (10); 257 if (!autostopped) {
258 msleep (10);
259 spin_lock_irq (&ohci->lock);
260 }
261 /* now ohci->lock is always held and irqs are always disabled */
269 262
270 /* keep it alive for more than ~5x suspend + resume costs */ 263 /* keep it alive for more than ~5x suspend + resume costs */
271 ohci->next_statechange = jiffies + STATECHANGE_DELAY; 264 ohci->next_statechange = jiffies + STATECHANGE_DELAY;
@@ -302,6 +295,45 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
302 return 0; 295 return 0;
303} 296}
304 297
298#ifdef CONFIG_PM
299
300static int ohci_bus_suspend (struct usb_hcd *hcd)
301{
302 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
303 int rc;
304
305 spin_lock_irq (&ohci->lock);
306
307 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
308 rc = -ESHUTDOWN;
309 else
310 rc = ohci_rh_suspend (ohci, 0);
311 spin_unlock_irq (&ohci->lock);
312 return rc;
313}
314
315static int ohci_bus_resume (struct usb_hcd *hcd)
316{
317 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
318 int rc;
319
320 if (time_before (jiffies, ohci->next_statechange))
321 msleep(5);
322
323 spin_lock_irq (&ohci->lock);
324
325 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
326 rc = -ESHUTDOWN;
327 else
328 rc = ohci_rh_resume (ohci);
329 spin_unlock_irq (&ohci->lock);
330
331 /* poll until we know a device is connected or we autostop */
332 if (rc == 0)
333 usb_hcd_poll_rh_status(hcd);
334 return rc;
335}
336
305#endif /* CONFIG_PM */ 337#endif /* CONFIG_PM */
306 338
307/*-------------------------------------------------------------------------*/ 339/*-------------------------------------------------------------------------*/
@@ -313,17 +345,11 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
313{ 345{
314 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 346 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
315 int i, changed = 0, length = 1; 347 int i, changed = 0, length = 1;
348 int any_connected = 0, rhsc_enabled = 1;
316 unsigned long flags; 349 unsigned long flags;
317 350
318 spin_lock_irqsave (&ohci->lock, flags); 351 spin_lock_irqsave (&ohci->lock, flags);
319 352
320 /* handle autosuspended root: finish resuming before
321 * letting khubd or root hub timer see state changes.
322 */
323 if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
324 || !HC_IS_RUNNING(hcd->state)))
325 goto done;
326
327 /* undocumented erratum seen on at least rev D */ 353 /* undocumented erratum seen on at least rev D */
328 if ((ohci->flags & OHCI_QUIRK_AMD756) 354 if ((ohci->flags & OHCI_QUIRK_AMD756)
329 && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) { 355 && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
@@ -347,6 +373,9 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
347 for (i = 0; i < ohci->num_ports; i++) { 373 for (i = 0; i < ohci->num_ports; i++) {
348 u32 status = roothub_portstatus (ohci, i); 374 u32 status = roothub_portstatus (ohci, i);
349 375
376 /* can't autostop if ports are connected */
377 any_connected |= (status & RH_PS_CCS);
378
350 if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC 379 if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
351 | RH_PS_OCIC | RH_PS_PRSC)) { 380 | RH_PS_OCIC | RH_PS_PRSC)) {
352 changed = 1; 381 changed = 1;
@@ -354,15 +383,69 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
354 buf [0] |= 1 << (i + 1); 383 buf [0] |= 1 << (i + 1);
355 else 384 else
356 buf [1] |= 1 << (i - 7); 385 buf [1] |= 1 << (i - 7);
357 continue;
358 } 386 }
359 } 387 }
360 388
361 /* after root hub changes, stop polling after debouncing 389 /* NOTE: vendors didn't always make the same implementation
362 * for a while and maybe kicking in autosuspend 390 * choices for RHSC. Sometimes it triggers on an edge (like
391 * setting and maybe clearing a port status change bit); and
392 * it's level-triggered on other silicon, active until khubd
393 * clears all active port status change bits. If it's still
394 * set (level-triggered) we must disable it and rely on
395 * polling until khubd re-enables it.
363 */ 396 */
364 if (changed) 397 if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
365 ohci->next_statechange = jiffies + STATECHANGE_DELAY; 398 ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
399 (void) ohci_readl (ohci, &ohci->regs->intrdisable);
400 rhsc_enabled = 0;
401 }
402 hcd->poll_rh = 1;
403
404 /* carry out appropriate state changes */
405 switch (ohci->hc_control & OHCI_CTRL_HCFS) {
406
407 case OHCI_USB_OPER:
408 /* keep on polling until we know a device is connected
409 * and RHSC is enabled */
410 if (!ohci->autostop) {
411 if (any_connected) {
412 if (rhsc_enabled)
413 hcd->poll_rh = 0;
414 } else {
415 ohci->autostop = 1;
416 ohci->next_statechange = jiffies + HZ;
417 }
418
419 /* if no devices have been attached for one second, autostop */
420 } else {
421 if (changed || any_connected) {
422 ohci->autostop = 0;
423 ohci->next_statechange = jiffies +
424 STATECHANGE_DELAY;
425 } else if (time_after_eq (jiffies,
426 ohci->next_statechange)
427 && !ohci->ed_rm_list
428 && !(ohci->hc_control &
429 OHCI_SCHED_ENABLES)) {
430 ohci_rh_suspend (ohci, 1);
431 }
432 }
433 break;
434
435 /* if there is a port change, autostart or ask to be resumed */
436 case OHCI_USB_SUSPEND:
437 case OHCI_USB_RESUME:
438 if (changed) {
439 if (ohci->autostop)
440 ohci_rh_resume (ohci);
441 else
442 usb_hcd_resume_root_hub (hcd);
443 } else {
444 /* everything is idle, no need for polling */
445 hcd->poll_rh = 0;
446 }
447 break;
448 }
366 449
367done: 450done:
368 spin_unlock_irqrestore (&ohci->lock, flags); 451 spin_unlock_irqrestore (&ohci->lock, flags);