aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ohci-hub.c')
-rw-r--r--drivers/usb/host/ohci-hub.c172
1 files changed, 90 insertions, 82 deletions
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 6995ea36f2e8..2441642cb7b4 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -41,7 +41,11 @@ 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 ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); 44 spin_lock_irq(&ohci->lock);
45 if (!ohci->autostop)
46 del_timer(&hcd->rh_timer); /* Prevent next poll */
47 ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
48 spin_unlock_irq(&ohci->lock);
45} 49}
46 50
47#define OHCI_SCHED_ENABLES \ 51#define OHCI_SCHED_ENABLES \
@@ -50,6 +54,9 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
50static void dl_done_list (struct ohci_hcd *); 54static void dl_done_list (struct ohci_hcd *);
51static void finish_unlinks (struct ohci_hcd *, u16); 55static void finish_unlinks (struct ohci_hcd *, u16);
52 56
57#ifdef CONFIG_PM
58static int ohci_restart(struct ohci_hcd *ohci);
59
53static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop) 60static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
54__releases(ohci->lock) 61__releases(ohci->lock)
55__acquires(ohci->lock) 62__acquires(ohci->lock)
@@ -132,8 +139,6 @@ static inline struct ed *find_head (struct ed *ed)
132 return ed; 139 return ed;
133} 140}
134 141
135static int ohci_restart (struct ohci_hcd *ohci);
136
137/* caller has locked the root hub */ 142/* caller has locked the root hub */
138static int ohci_rh_resume (struct ohci_hcd *ohci) 143static int ohci_rh_resume (struct ohci_hcd *ohci)
139__releases(ohci->lock) 144__releases(ohci->lock)
@@ -169,7 +174,7 @@ __acquires(ohci->lock)
169 break; 174 break;
170 case OHCI_USB_RESUME: 175 case OHCI_USB_RESUME:
171 /* HCFS changes sometime after INTR_RD */ 176 /* HCFS changes sometime after INTR_RD */
172 ohci_info(ohci, "%swakeup\n", 177 ohci_dbg(ohci, "%swakeup root hub\n",
173 autostopped ? "auto-" : ""); 178 autostopped ? "auto-" : "");
174 break; 179 break;
175 case OHCI_USB_OPER: 180 case OHCI_USB_OPER:
@@ -181,7 +186,6 @@ __acquires(ohci->lock)
181 ohci_dbg (ohci, "lost power\n"); 186 ohci_dbg (ohci, "lost power\n");
182 status = -EBUSY; 187 status = -EBUSY;
183 } 188 }
184#ifdef CONFIG_PM
185 if (status == -EBUSY) { 189 if (status == -EBUSY) {
186 if (!autostopped) { 190 if (!autostopped) {
187 spin_unlock_irq (&ohci->lock); 191 spin_unlock_irq (&ohci->lock);
@@ -191,25 +195,12 @@ __acquires(ohci->lock)
191 } 195 }
192 return status; 196 return status;
193 } 197 }
194#endif
195 if (status != -EINPROGRESS) 198 if (status != -EINPROGRESS)
196 return status; 199 return status;
197 if (autostopped) 200 if (autostopped)
198 goto skip_resume; 201 goto skip_resume;
199 spin_unlock_irq (&ohci->lock); 202 spin_unlock_irq (&ohci->lock);
200 203
201 temp = ohci->num_ports;
202 while (temp--) {
203 u32 stat = ohci_readl (ohci,
204 &ohci->regs->roothub.portstatus [temp]);
205
206 /* force global, not selective, resume */
207 if (!(stat & RH_PS_PSS))
208 continue;
209 ohci_writel (ohci, RH_PS_POCI,
210 &ohci->regs->roothub.portstatus [temp]);
211 }
212
213 /* Some controllers (lucent erratum) need extra-long delays */ 204 /* Some controllers (lucent erratum) need extra-long delays */
214 msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1); 205 msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
215 206
@@ -217,6 +208,7 @@ __acquires(ohci->lock)
217 temp &= OHCI_CTRL_HCFS; 208 temp &= OHCI_CTRL_HCFS;
218 if (temp != OHCI_USB_RESUME) { 209 if (temp != OHCI_USB_RESUME) {
219 ohci_err (ohci, "controller won't resume\n"); 210 ohci_err (ohci, "controller won't resume\n");
211 spin_lock_irq(&ohci->lock);
220 return -EBUSY; 212 return -EBUSY;
221 } 213 }
222 214
@@ -296,8 +288,6 @@ skip_resume:
296 return 0; 288 return 0;
297} 289}
298 290
299#ifdef CONFIG_PM
300
301static int ohci_bus_suspend (struct usb_hcd *hcd) 291static int ohci_bus_suspend (struct usb_hcd *hcd)
302{ 292{
303 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 293 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
@@ -335,6 +325,83 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
335 return rc; 325 return rc;
336} 326}
337 327
328/* Carry out polling-, autostop-, and autoresume-related state changes */
329static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
330 int any_connected)
331{
332 int poll_rh = 1;
333
334 switch (ohci->hc_control & OHCI_CTRL_HCFS) {
335
336 case OHCI_USB_OPER:
337 /* keep on polling until we know a device is connected
338 * and RHSC is enabled */
339 if (!ohci->autostop) {
340 if (any_connected ||
341 !device_may_wakeup(&ohci_to_hcd(ohci)
342 ->self.root_hub->dev)) {
343 if (ohci_readl(ohci, &ohci->regs->intrenable) &
344 OHCI_INTR_RHSC)
345 poll_rh = 0;
346 } else {
347 ohci->autostop = 1;
348 ohci->next_statechange = jiffies + HZ;
349 }
350
351 /* if no devices have been attached for one second, autostop */
352 } else {
353 if (changed || any_connected) {
354 ohci->autostop = 0;
355 ohci->next_statechange = jiffies +
356 STATECHANGE_DELAY;
357 } else if (time_after_eq(jiffies,
358 ohci->next_statechange)
359 && !ohci->ed_rm_list
360 && !(ohci->hc_control &
361 OHCI_SCHED_ENABLES)) {
362 ohci_rh_suspend(ohci, 1);
363 }
364 }
365 break;
366
367 /* if there is a port change, autostart or ask to be resumed */
368 case OHCI_USB_SUSPEND:
369 case OHCI_USB_RESUME:
370 if (changed) {
371 if (ohci->autostop)
372 ohci_rh_resume(ohci);
373 else
374 usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
375 } else {
376 /* everything is idle, no need for polling */
377 poll_rh = 0;
378 }
379 break;
380 }
381 return poll_rh;
382}
383
384#else /* CONFIG_PM */
385
386static inline int ohci_rh_resume(struct ohci_hcd *ohci)
387{
388 return 0;
389}
390
391/* Carry out polling-related state changes.
392 * autostop isn't used when CONFIG_PM is turned off.
393 */
394static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
395 int any_connected)
396{
397 int poll_rh = 1;
398
399 /* keep on polling until RHSC is enabled */
400 if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
401 poll_rh = 0;
402 return poll_rh;
403}
404
338#endif /* CONFIG_PM */ 405#endif /* CONFIG_PM */
339 406
340/*-------------------------------------------------------------------------*/ 407/*-------------------------------------------------------------------------*/
@@ -346,7 +413,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
346{ 413{
347 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 414 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
348 int i, changed = 0, length = 1; 415 int i, changed = 0, length = 1;
349 int any_connected = 0, rhsc_enabled = 1; 416 int any_connected = 0;
350 unsigned long flags; 417 unsigned long flags;
351 418
352 spin_lock_irqsave (&ohci->lock, flags); 419 spin_lock_irqsave (&ohci->lock, flags);
@@ -387,67 +454,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
387 } 454 }
388 } 455 }
389 456
390 /* NOTE: vendors didn't always make the same implementation 457 hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
391 * choices for RHSC. Sometimes it triggers on an edge (like 458 any_connected);
392 * setting and maybe clearing a port status change bit); and
393 * it's level-triggered on other silicon, active until khubd
394 * clears all active port status change bits. If it's still
395 * set (level-triggered) we must disable it and rely on
396 * polling until khubd re-enables it.
397 */
398 if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
399 ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
400 (void) ohci_readl (ohci, &ohci->regs->intrdisable);
401 rhsc_enabled = 0;
402 }
403 hcd->poll_rh = 1;
404
405 /* carry out appropriate state changes */
406 switch (ohci->hc_control & OHCI_CTRL_HCFS) {
407
408 case OHCI_USB_OPER:
409 /* keep on polling until we know a device is connected
410 * and RHSC is enabled */
411 if (!ohci->autostop) {
412 if (any_connected) {
413 if (rhsc_enabled)
414 hcd->poll_rh = 0;
415 } else {
416 ohci->autostop = 1;
417 ohci->next_statechange = jiffies + HZ;
418 }
419
420 /* if no devices have been attached for one second, autostop */
421 } else {
422 if (changed || any_connected) {
423 ohci->autostop = 0;
424 ohci->next_statechange = jiffies +
425 STATECHANGE_DELAY;
426 } else if (device_may_wakeup(&hcd->self.root_hub->dev)
427 && time_after_eq(jiffies,
428 ohci->next_statechange)
429 && !ohci->ed_rm_list
430 && !(ohci->hc_control &
431 OHCI_SCHED_ENABLES)) {
432 ohci_rh_suspend (ohci, 1);
433 }
434 }
435 break;
436
437 /* if there is a port change, autostart or ask to be resumed */
438 case OHCI_USB_SUSPEND:
439 case OHCI_USB_RESUME:
440 if (changed) {
441 if (ohci->autostop)
442 ohci_rh_resume (ohci);
443 else
444 usb_hcd_resume_root_hub (hcd);
445 } else {
446 /* everything is idle, no need for polling */
447 hcd->poll_rh = 0;
448 }
449 break;
450 }
451 459
452done: 460done:
453 spin_unlock_irqrestore (&ohci->lock, flags); 461 spin_unlock_irqrestore (&ohci->lock, flags);