diff options
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 70 |
1 files changed, 23 insertions, 47 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 82e608a4bbd0..25a718eb1d0f 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -84,6 +84,8 @@ static char *errbuf; | |||
84 | 84 | ||
85 | static kmem_cache_t *uhci_up_cachep; /* urb_priv */ | 85 | static kmem_cache_t *uhci_up_cachep; /* urb_priv */ |
86 | 86 | ||
87 | static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); | ||
88 | static void wakeup_rh(struct uhci_hcd *uhci); | ||
87 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | 89 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); |
88 | 90 | ||
89 | /* If a transfer is still active after this much time, turn off FSBR */ | 91 | /* If a transfer is still active after this much time, turn off FSBR */ |
@@ -133,12 +135,12 @@ static void reset_hc(struct uhci_hcd *uhci) | |||
133 | outw(0, uhci->io_addr + USBINTR); | 135 | outw(0, uhci->io_addr + USBINTR); |
134 | outw(0, uhci->io_addr + USBCMD); | 136 | outw(0, uhci->io_addr + USBCMD); |
135 | 137 | ||
136 | uhci->resume_detect = 0; | ||
137 | uhci->port_c_suspend = uhci->suspended_ports = | 138 | uhci->port_c_suspend = uhci->suspended_ports = |
138 | uhci->resuming_ports = 0; | 139 | uhci->resuming_ports = 0; |
139 | uhci->rh_state = UHCI_RH_RESET; | 140 | uhci->rh_state = UHCI_RH_RESET; |
140 | uhci->is_stopped = UHCI_IS_STOPPED; | 141 | uhci->is_stopped = UHCI_IS_STOPPED; |
141 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; | 142 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; |
143 | uhci_to_hcd(uhci)->poll_rh = 0; | ||
142 | } | 144 | } |
143 | 145 | ||
144 | /* | 146 | /* |
@@ -148,6 +150,7 @@ static void hc_died(struct uhci_hcd *uhci) | |||
148 | { | 150 | { |
149 | reset_hc(uhci); | 151 | reset_hc(uhci); |
150 | uhci->hc_inaccessible = 1; | 152 | uhci->hc_inaccessible = 1; |
153 | del_timer(&uhci->stall_timer); | ||
151 | } | 154 | } |
152 | 155 | ||
153 | /* | 156 | /* |
@@ -302,14 +305,14 @@ __acquires(uhci->lock) | |||
302 | 305 | ||
303 | uhci->rh_state = new_state; | 306 | uhci->rh_state = new_state; |
304 | uhci->is_stopped = UHCI_IS_STOPPED; | 307 | uhci->is_stopped = UHCI_IS_STOPPED; |
305 | uhci->resume_detect = 0; | 308 | del_timer(&uhci->stall_timer); |
309 | uhci_to_hcd(uhci)->poll_rh = !int_enable; | ||
306 | 310 | ||
307 | uhci_scan_schedule(uhci, NULL); | 311 | uhci_scan_schedule(uhci, NULL); |
308 | } | 312 | } |
309 | 313 | ||
310 | static void start_rh(struct uhci_hcd *uhci) | 314 | static void start_rh(struct uhci_hcd *uhci) |
311 | { | 315 | { |
312 | uhci->rh_state = UHCI_RH_RUNNING; | ||
313 | uhci->is_stopped = 0; | 316 | uhci->is_stopped = 0; |
314 | smp_wmb(); | 317 | smp_wmb(); |
315 | 318 | ||
@@ -320,6 +323,9 @@ static void start_rh(struct uhci_hcd *uhci) | |||
320 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, | 323 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, |
321 | uhci->io_addr + USBINTR); | 324 | uhci->io_addr + USBINTR); |
322 | mb(); | 325 | mb(); |
326 | uhci->rh_state = UHCI_RH_RUNNING; | ||
327 | uhci_to_hcd(uhci)->poll_rh = 1; | ||
328 | restart_timer(uhci); | ||
323 | } | 329 | } |
324 | 330 | ||
325 | static void wakeup_rh(struct uhci_hcd *uhci) | 331 | static void wakeup_rh(struct uhci_hcd *uhci) |
@@ -353,36 +359,9 @@ __acquires(uhci->lock) | |||
353 | } | 359 | } |
354 | 360 | ||
355 | start_rh(uhci); | 361 | start_rh(uhci); |
356 | } | ||
357 | |||
358 | static void rh_state_transitions(struct uhci_hcd *uhci) | ||
359 | { | ||
360 | switch (uhci->rh_state) { | ||
361 | case UHCI_RH_RUNNING: | ||
362 | /* are any devices attached? */ | ||
363 | if (!any_ports_active(uhci)) { | ||
364 | uhci->rh_state = UHCI_RH_RUNNING_NODEVS; | ||
365 | uhci->auto_stop_time = jiffies + HZ; | ||
366 | } | ||
367 | break; | ||
368 | 362 | ||
369 | case UHCI_RH_RUNNING_NODEVS: | 363 | /* Restart root hub polling */ |
370 | /* auto-stop if nothing connected for 1 second */ | 364 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); |
371 | if (any_ports_active(uhci)) | ||
372 | uhci->rh_state = UHCI_RH_RUNNING; | ||
373 | else if (time_after_eq(jiffies, uhci->auto_stop_time)) | ||
374 | suspend_rh(uhci, UHCI_RH_AUTO_STOPPED); | ||
375 | break; | ||
376 | |||
377 | case UHCI_RH_AUTO_STOPPED: | ||
378 | /* wakeup if requested by a device */ | ||
379 | if (uhci->resume_detect) | ||
380 | wakeup_rh(uhci); | ||
381 | break; | ||
382 | |||
383 | default: | ||
384 | break; | ||
385 | } | ||
386 | } | 365 | } |
387 | 366 | ||
388 | static void stall_callback(unsigned long _uhci) | 367 | static void stall_callback(unsigned long _uhci) |
@@ -394,14 +373,8 @@ static void stall_callback(unsigned long _uhci) | |||
394 | uhci_scan_schedule(uhci, NULL); | 373 | uhci_scan_schedule(uhci, NULL); |
395 | check_fsbr(uhci); | 374 | check_fsbr(uhci); |
396 | 375 | ||
397 | /* Poll for and perform state transitions */ | 376 | if (!uhci->is_stopped) |
398 | if (!uhci->hc_inaccessible) { | 377 | restart_timer(uhci); |
399 | rh_state_transitions(uhci); | ||
400 | if (uhci->suspended_ports) | ||
401 | uhci_check_ports(uhci); | ||
402 | } | ||
403 | |||
404 | restart_timer(uhci); | ||
405 | spin_unlock_irqrestore(&uhci->lock, flags); | 378 | spin_unlock_irqrestore(&uhci->lock, flags); |
406 | } | 379 | } |
407 | 380 | ||
@@ -443,7 +416,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
443 | } | 416 | } |
444 | 417 | ||
445 | if (status & USBSTS_RD) | 418 | if (status & USBSTS_RD) |
446 | uhci->resume_detect = 1; | 419 | usb_hcd_poll_rh_status(hcd); |
447 | 420 | ||
448 | spin_lock_irqsave(&uhci->lock, flags); | 421 | spin_lock_irqsave(&uhci->lock, flags); |
449 | uhci_scan_schedule(uhci, regs); | 422 | uhci_scan_schedule(uhci, regs); |
@@ -542,6 +515,7 @@ static int uhci_start(struct usb_hcd *hcd) | |||
542 | struct dentry *dentry; | 515 | struct dentry *dentry; |
543 | 516 | ||
544 | io_size = (unsigned) hcd->rsrc_len; | 517 | io_size = (unsigned) hcd->rsrc_len; |
518 | hcd->uses_new_polling = 1; | ||
545 | if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM)) | 519 | if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM)) |
546 | hcd->can_wakeup = 1; /* Assume it supports PME# */ | 520 | hcd->can_wakeup = 1; /* Assume it supports PME# */ |
547 | 521 | ||
@@ -714,8 +688,6 @@ static int uhci_start(struct usb_hcd *hcd) | |||
714 | configure_hc(uhci); | 688 | configure_hc(uhci); |
715 | start_rh(uhci); | 689 | start_rh(uhci); |
716 | 690 | ||
717 | restart_timer(uhci); | ||
718 | |||
719 | udev->speed = USB_SPEED_FULL; | 691 | udev->speed = USB_SPEED_FULL; |
720 | 692 | ||
721 | if (usb_hcd_register_root_hub(udev, hcd) != 0) { | 693 | if (usb_hcd_register_root_hub(udev, hcd) != 0) { |
@@ -730,8 +702,8 @@ static int uhci_start(struct usb_hcd *hcd) | |||
730 | * error exits: | 702 | * error exits: |
731 | */ | 703 | */ |
732 | err_start_root_hub: | 704 | err_start_root_hub: |
733 | del_timer_sync(&uhci->stall_timer); | ||
734 | reset_hc(uhci); | 705 | reset_hc(uhci); |
706 | del_timer_sync(&uhci->stall_timer); | ||
735 | 707 | ||
736 | err_alloc_skelqh: | 708 | err_alloc_skelqh: |
737 | for (i = 0; i < UHCI_NUM_SKELQH; i++) | 709 | for (i = 0; i < UHCI_NUM_SKELQH; i++) |
@@ -771,13 +743,12 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
771 | { | 743 | { |
772 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 744 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
773 | 745 | ||
774 | del_timer_sync(&uhci->stall_timer); | ||
775 | |||
776 | spin_lock_irq(&uhci->lock); | 746 | spin_lock_irq(&uhci->lock); |
777 | reset_hc(uhci); | 747 | reset_hc(uhci); |
778 | uhci_scan_schedule(uhci, NULL); | 748 | uhci_scan_schedule(uhci, NULL); |
779 | spin_unlock_irq(&uhci->lock); | 749 | spin_unlock_irq(&uhci->lock); |
780 | 750 | ||
751 | del_timer_sync(&uhci->stall_timer); | ||
781 | release_uhci(uhci); | 752 | release_uhci(uhci); |
782 | } | 753 | } |
783 | 754 | ||
@@ -844,6 +815,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
844 | 815 | ||
845 | done: | 816 | done: |
846 | spin_unlock_irq(&uhci->lock); | 817 | spin_unlock_irq(&uhci->lock); |
818 | if (rc == 0) | ||
819 | del_timer_sync(&hcd->rh_timer); | ||
847 | return rc; | 820 | return rc; |
848 | } | 821 | } |
849 | 822 | ||
@@ -875,6 +848,9 @@ static int uhci_resume(struct usb_hcd *hcd) | |||
875 | suspend_rh(uhci, UHCI_RH_SUSPENDED); | 848 | suspend_rh(uhci, UHCI_RH_SUSPENDED); |
876 | 849 | ||
877 | spin_unlock_irq(&uhci->lock); | 850 | spin_unlock_irq(&uhci->lock); |
851 | |||
852 | if (hcd->poll_rh) | ||
853 | usb_hcd_poll_rh_status(hcd); | ||
878 | return 0; | 854 | return 0; |
879 | } | 855 | } |
880 | #endif | 856 | #endif |