aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-hub.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-11-20 11:06:59 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-12-01 17:25:52 -0500
commit1f9fc882d92f3ff390455836f98d7ddc36d4e4c3 (patch)
tree55e23959337683a5dc0d5b3b00c8c5f83b61ed7e /drivers/usb/host/ohci-hub.c
parent40f122f343797d02390c5a157372cac0c5b50bb7 (diff)
OHCI: make autostop conditional on CONFIG_PM
Unlike UHCI, OHCI does not exert any DMA load on the system when no devices are connected. Consequently there is no advantage to doing an autostop other than the power savings, so we shouldn't compile the necessary code unless CONFIG_PM is enabled. This patch (as820) makes the root-hub suspend and resume routines conditional on CONFIG_PM. It also prevents autostop from activating if the device_may_wakeup flag isn't set; some people use this flag to alert the driver about Resume-Detect bugs in the hardware. 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.c133
1 files changed, 79 insertions, 54 deletions
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 4c9492779ede..2441642cb7b4 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -56,7 +56,6 @@ static void finish_unlinks (struct ohci_hcd *, u16);
56 56
57#ifdef CONFIG_PM 57#ifdef CONFIG_PM
58static int ohci_restart(struct ohci_hcd *ohci); 58static int ohci_restart(struct ohci_hcd *ohci);
59#endif
60 59
61static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop) 60static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
62__releases(ohci->lock) 61__releases(ohci->lock)
@@ -187,7 +186,6 @@ __acquires(ohci->lock)
187 ohci_dbg (ohci, "lost power\n"); 186 ohci_dbg (ohci, "lost power\n");
188 status = -EBUSY; 187 status = -EBUSY;
189 } 188 }
190#ifdef CONFIG_PM
191 if (status == -EBUSY) { 189 if (status == -EBUSY) {
192 if (!autostopped) { 190 if (!autostopped) {
193 spin_unlock_irq (&ohci->lock); 191 spin_unlock_irq (&ohci->lock);
@@ -197,7 +195,6 @@ __acquires(ohci->lock)
197 } 195 }
198 return status; 196 return status;
199 } 197 }
200#endif
201 if (status != -EINPROGRESS) 198 if (status != -EINPROGRESS)
202 return status; 199 return status;
203 if (autostopped) 200 if (autostopped)
@@ -291,8 +288,6 @@ skip_resume:
291 return 0; 288 return 0;
292} 289}
293 290
294#ifdef CONFIG_PM
295
296static int ohci_bus_suspend (struct usb_hcd *hcd) 291static int ohci_bus_suspend (struct usb_hcd *hcd)
297{ 292{
298 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 293 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
@@ -330,6 +325,83 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
330 return rc; 325 return rc;
331} 326}
332 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
333#endif /* CONFIG_PM */ 405#endif /* CONFIG_PM */
334 406
335/*-------------------------------------------------------------------------*/ 407/*-------------------------------------------------------------------------*/
@@ -382,55 +454,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
382 } 454 }
383 } 455 }
384 456
385 hcd->poll_rh = 1; 457 hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
386 458 any_connected);
387 /* carry out appropriate state changes */
388 switch (ohci->hc_control & OHCI_CTRL_HCFS) {
389
390 case OHCI_USB_OPER:
391 /* keep on polling until we know a device is connected
392 * and RHSC is enabled */
393 if (!ohci->autostop) {
394 if (any_connected) {
395 if (ohci_readl(ohci, &ohci->regs->intrenable) &
396 OHCI_INTR_RHSC)
397 hcd->poll_rh = 0;
398 } else {
399 ohci->autostop = 1;
400 ohci->next_statechange = jiffies + HZ;
401 }
402
403 /* if no devices have been attached for one second, autostop */
404 } else {
405 if (changed || any_connected) {
406 ohci->autostop = 0;
407 ohci->next_statechange = jiffies +
408 STATECHANGE_DELAY;
409 } else if (device_may_wakeup(&hcd->self.root_hub->dev)
410 && time_after_eq(jiffies,
411 ohci->next_statechange)
412 && !ohci->ed_rm_list
413 && !(ohci->hc_control &
414 OHCI_SCHED_ENABLES)) {
415 ohci_rh_suspend (ohci, 1);
416 }
417 }
418 break;
419
420 /* if there is a port change, autostart or ask to be resumed */
421 case OHCI_USB_SUSPEND:
422 case OHCI_USB_RESUME:
423 if (changed) {
424 if (ohci->autostop)
425 ohci_rh_resume (ohci);
426 else
427 usb_hcd_resume_root_hub (hcd);
428 } else {
429 /* everything is idle, no need for polling */
430 hcd->poll_rh = 0;
431 }
432 break;
433 }
434 459
435done: 460done:
436 spin_unlock_irqrestore (&ohci->lock, flags); 461 spin_unlock_irqrestore (&ohci->lock, flags);