diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-10-24 12:04:22 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-11-16 17:26:11 -0500 |
commit | 583ceada075597a5b6acab1140d61ac81586a2a6 (patch) | |
tree | 27ea85087cc6d09333f0121534e866f5e65c1c83 /drivers/usb/host/ohci-hcd.c | |
parent | 51b5bce8c253b82d4789161cc3b0c74bee313bb1 (diff) |
USB: OHCI: fix root-hub resume bug
When a suspended OHCI controller sees a port's status change, it sets
both the Root-Hub-Status-Change and the Resume-Detect bits in the
Interrupt Status register. Processing both these bits, the driver
tries to resume the root hub twice!
This patch (as807) fixes the bug by ignoring RD if RHSC is set. It
also prints a slightly more informative log message when a
remote-wakeup event occurs.
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-hcd.c')
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 9be6b303e784..ea4714e557e4 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -715,13 +715,6 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
715 | return IRQ_NOTMINE; | 715 | return IRQ_NOTMINE; |
716 | } | 716 | } |
717 | 717 | ||
718 | if (ints & OHCI_INTR_RHSC) { | ||
719 | ohci_vdbg (ohci, "rhsc\n"); | ||
720 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; | ||
721 | ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrstatus); | ||
722 | usb_hcd_poll_rh_status(hcd); | ||
723 | } | ||
724 | |||
725 | if (ints & OHCI_INTR_UE) { | 718 | if (ints & OHCI_INTR_UE) { |
726 | disable (ohci); | 719 | disable (ohci); |
727 | ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); | 720 | ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); |
@@ -731,9 +724,21 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
731 | ohci_usb_reset (ohci); | 724 | ohci_usb_reset (ohci); |
732 | } | 725 | } |
733 | 726 | ||
734 | if (ints & OHCI_INTR_RD) { | 727 | if (ints & OHCI_INTR_RHSC) { |
735 | ohci_vdbg (ohci, "resume detect\n"); | 728 | ohci_vdbg(ohci, "rhsc\n"); |
736 | ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus); | 729 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; |
730 | ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC, | ||
731 | ®s->intrstatus); | ||
732 | usb_hcd_poll_rh_status(hcd); | ||
733 | } | ||
734 | |||
735 | /* For connect and disconnect events, we expect the controller | ||
736 | * to turn on RHSC along with RD. But for remote wakeup events | ||
737 | * this might not happen. | ||
738 | */ | ||
739 | else if (ints & OHCI_INTR_RD) { | ||
740 | ohci_vdbg(ohci, "resume detect\n"); | ||
741 | ohci_writel(ohci, OHCI_INTR_RD, ®s->intrstatus); | ||
737 | hcd->poll_rh = 1; | 742 | hcd->poll_rh = 1; |
738 | if (ohci->autostop) { | 743 | if (ohci->autostop) { |
739 | spin_lock (&ohci->lock); | 744 | spin_lock (&ohci->lock); |