diff options
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
| -rw-r--r-- | drivers/usb/host/uhci-hcd.c | 62 |
1 files changed, 22 insertions, 40 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 0d5d2545bf07..0c024898cbea 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
| @@ -97,14 +97,9 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | |||
| 97 | /* to make sure it doesn't hog all of the bandwidth */ | 97 | /* to make sure it doesn't hog all of the bandwidth */ |
| 98 | #define DEPTH_INTERVAL 5 | 98 | #define DEPTH_INTERVAL 5 |
| 99 | 99 | ||
| 100 | static inline void restart_timer(struct uhci_hcd *uhci) | ||
| 101 | { | ||
| 102 | mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100)); | ||
| 103 | } | ||
| 104 | |||
| 105 | #include "uhci-hub.c" | ||
| 106 | #include "uhci-debug.c" | 100 | #include "uhci-debug.c" |
| 107 | #include "uhci-q.c" | 101 | #include "uhci-q.c" |
| 102 | #include "uhci-hub.c" | ||
| 108 | 103 | ||
| 109 | /* | 104 | /* |
| 110 | * Make sure the controller is completely inactive, unable to | 105 | * Make sure the controller is completely inactive, unable to |
| @@ -160,7 +155,6 @@ static void hc_died(struct uhci_hcd *uhci) | |||
| 160 | { | 155 | { |
| 161 | reset_hc(uhci); | 156 | reset_hc(uhci); |
| 162 | uhci->hc_inaccessible = 1; | 157 | uhci->hc_inaccessible = 1; |
| 163 | del_timer(&uhci->stall_timer); | ||
| 164 | } | 158 | } |
| 165 | 159 | ||
| 166 | /* | 160 | /* |
| @@ -287,8 +281,11 @@ __acquires(uhci->lock) | |||
| 287 | /* Enable resume-detect interrupts if they work. | 281 | /* Enable resume-detect interrupts if they work. |
| 288 | * Then enter Global Suspend mode, still configured. | 282 | * Then enter Global Suspend mode, still configured. |
| 289 | */ | 283 | */ |
| 290 | int_enable = (resume_detect_interrupts_are_broken(uhci) ? | 284 | uhci->working_RD = 1; |
| 291 | 0 : USBINTR_RESUME); | 285 | int_enable = USBINTR_RESUME; |
| 286 | if (resume_detect_interrupts_are_broken(uhci)) { | ||
| 287 | uhci->working_RD = int_enable = 0; | ||
| 288 | } | ||
| 292 | outw(int_enable, uhci->io_addr + USBINTR); | 289 | outw(int_enable, uhci->io_addr + USBINTR); |
| 293 | outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); | 290 | outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); |
| 294 | mb(); | 291 | mb(); |
| @@ -315,7 +312,6 @@ __acquires(uhci->lock) | |||
| 315 | 312 | ||
| 316 | uhci->rh_state = new_state; | 313 | uhci->rh_state = new_state; |
| 317 | uhci->is_stopped = UHCI_IS_STOPPED; | 314 | uhci->is_stopped = UHCI_IS_STOPPED; |
| 318 | del_timer(&uhci->stall_timer); | ||
| 319 | uhci_to_hcd(uhci)->poll_rh = !int_enable; | 315 | uhci_to_hcd(uhci)->poll_rh = !int_enable; |
| 320 | 316 | ||
| 321 | uhci_scan_schedule(uhci, NULL); | 317 | uhci_scan_schedule(uhci, NULL); |
| @@ -335,7 +331,6 @@ static void start_rh(struct uhci_hcd *uhci) | |||
| 335 | mb(); | 331 | mb(); |
| 336 | uhci->rh_state = UHCI_RH_RUNNING; | 332 | uhci->rh_state = UHCI_RH_RUNNING; |
| 337 | uhci_to_hcd(uhci)->poll_rh = 1; | 333 | uhci_to_hcd(uhci)->poll_rh = 1; |
| 338 | restart_timer(uhci); | ||
| 339 | } | 334 | } |
| 340 | 335 | ||
| 341 | static void wakeup_rh(struct uhci_hcd *uhci) | 336 | static void wakeup_rh(struct uhci_hcd *uhci) |
| @@ -374,20 +369,6 @@ __acquires(uhci->lock) | |||
| 374 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); | 369 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); |
| 375 | } | 370 | } |
| 376 | 371 | ||
| 377 | static void stall_callback(unsigned long _uhci) | ||
| 378 | { | ||
| 379 | struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; | ||
| 380 | unsigned long flags; | ||
| 381 | |||
| 382 | spin_lock_irqsave(&uhci->lock, flags); | ||
| 383 | uhci_scan_schedule(uhci, NULL); | ||
| 384 | check_fsbr(uhci); | ||
| 385 | |||
| 386 | if (!uhci->is_stopped) | ||
| 387 | restart_timer(uhci); | ||
| 388 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
| 389 | } | ||
| 390 | |||
| 391 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | 372 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) |
| 392 | { | 373 | { |
| 393 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 374 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
| @@ -418,8 +399,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
| 418 | "host controller halted, " | 399 | "host controller halted, " |
| 419 | "very bad!\n"); | 400 | "very bad!\n"); |
| 420 | hc_died(uhci); | 401 | hc_died(uhci); |
| 421 | spin_unlock_irqrestore(&uhci->lock, flags); | 402 | |
| 422 | return IRQ_HANDLED; | 403 | /* Force a callback in case there are |
| 404 | * pending unlinks */ | ||
| 405 | mod_timer(&hcd->rh_timer, jiffies); | ||
| 423 | } | 406 | } |
| 424 | spin_unlock_irqrestore(&uhci->lock, flags); | 407 | spin_unlock_irqrestore(&uhci->lock, flags); |
| 425 | } | 408 | } |
| @@ -427,10 +410,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
| 427 | 410 | ||
| 428 | if (status & USBSTS_RD) | 411 | if (status & USBSTS_RD) |
| 429 | usb_hcd_poll_rh_status(hcd); | 412 | usb_hcd_poll_rh_status(hcd); |
| 430 | 413 | else { | |
| 431 | spin_lock_irqsave(&uhci->lock, flags); | 414 | spin_lock_irqsave(&uhci->lock, flags); |
| 432 | uhci_scan_schedule(uhci, regs); | 415 | uhci_scan_schedule(uhci, regs); |
| 433 | spin_unlock_irqrestore(&uhci->lock, flags); | 416 | spin_unlock_irqrestore(&uhci->lock, flags); |
| 417 | } | ||
| 434 | 418 | ||
| 435 | return IRQ_HANDLED; | 419 | return IRQ_HANDLED; |
| 436 | } | 420 | } |
| @@ -595,10 +579,6 @@ static int uhci_start(struct usb_hcd *hcd) | |||
| 595 | 579 | ||
| 596 | init_waitqueue_head(&uhci->waitqh); | 580 | init_waitqueue_head(&uhci->waitqh); |
| 597 | 581 | ||
| 598 | init_timer(&uhci->stall_timer); | ||
| 599 | uhci->stall_timer.function = stall_callback; | ||
| 600 | uhci->stall_timer.data = (unsigned long) uhci; | ||
| 601 | |||
| 602 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | 582 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), |
| 603 | &dma_handle, 0); | 583 | &dma_handle, 0); |
| 604 | if (!uhci->fl) { | 584 | if (!uhci->fl) { |
| @@ -745,11 +725,11 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
| 745 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 725 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
| 746 | 726 | ||
| 747 | spin_lock_irq(&uhci->lock); | 727 | spin_lock_irq(&uhci->lock); |
| 748 | reset_hc(uhci); | 728 | if (!uhci->hc_inaccessible) |
| 729 | reset_hc(uhci); | ||
| 749 | uhci_scan_schedule(uhci, NULL); | 730 | uhci_scan_schedule(uhci, NULL); |
| 750 | spin_unlock_irq(&uhci->lock); | 731 | spin_unlock_irq(&uhci->lock); |
| 751 | 732 | ||
| 752 | del_timer_sync(&uhci->stall_timer); | ||
| 753 | release_uhci(uhci); | 733 | release_uhci(uhci); |
| 754 | } | 734 | } |
| 755 | 735 | ||
| @@ -811,13 +791,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
| 811 | */ | 791 | */ |
| 812 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | 792 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); |
| 813 | uhci->hc_inaccessible = 1; | 793 | uhci->hc_inaccessible = 1; |
| 794 | hcd->poll_rh = 0; | ||
| 814 | 795 | ||
| 815 | /* FIXME: Enable non-PME# remote wakeup? */ | 796 | /* FIXME: Enable non-PME# remote wakeup? */ |
| 816 | 797 | ||
| 817 | done: | 798 | done: |
| 818 | spin_unlock_irq(&uhci->lock); | 799 | spin_unlock_irq(&uhci->lock); |
| 819 | if (rc == 0) | ||
| 820 | del_timer_sync(&hcd->rh_timer); | ||
| 821 | return rc; | 800 | return rc; |
| 822 | } | 801 | } |
| 823 | 802 | ||
| @@ -850,8 +829,11 @@ static int uhci_resume(struct usb_hcd *hcd) | |||
| 850 | 829 | ||
| 851 | spin_unlock_irq(&uhci->lock); | 830 | spin_unlock_irq(&uhci->lock); |
| 852 | 831 | ||
| 853 | if (hcd->poll_rh) | 832 | if (!uhci->working_RD) { |
| 833 | /* Suspended root hub needs to be polled */ | ||
| 834 | hcd->poll_rh = 1; | ||
| 854 | usb_hcd_poll_rh_status(hcd); | 835 | usb_hcd_poll_rh_status(hcd); |
| 836 | } | ||
| 855 | return 0; | 837 | return 0; |
| 856 | } | 838 | } |
| 857 | #endif | 839 | #endif |
