diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2011-05-17 17:27:12 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-19 16:34:04 -0700 |
commit | 69fff59de4d844f8b4c2454c3c23d32b69dcbfd7 (patch) | |
tree | 3d88efbce85e3a8c25651d07f9c9ddafbda86ae5 /drivers/usb/host/oxu210hp-hcd.c | |
parent | d23894402b33338c51f1863d7f866fdc6f073a02 (diff) |
USB: remove remaining usages of hcd->state from usbcore and fix regression
This patch (as1467) removes the last usages of hcd->state from
usbcore. We no longer check to see if an interrupt handler finds that
a controller has died; instead we rely on host controller drivers to
make an explicit call to usb_hc_died().
This fixes a regression introduced by commit
9b37596a2e860404503a3f2a6513db60c296bfdc (USB: move usbcore away from
hcd->state). It used to be that when a controller shared an IRQ with
another device and an interrupt arrived while hcd->state was set to
HC_STATE_HALT, the interrupt handler would be skipped. The commit
removed that test; as a result the current code doesn't skip calling
the handler and ends up believing the controller has died, even though
it's only temporarily stopped. The solution is to ignore HC_STATE_HALT
following the handler's return.
As a consequence of this change, several of the host controller
drivers need to be modified. They can no longer implicitly rely on
usbcore realizing that a controller has died because of hcd->state.
The patch adds calls to usb_hc_died() in the appropriate places.
The patch also changes a few of the interrupt handlers. They don't
expect to be called when hcd->state is equal to HC_STATE_HALT, even if
the controller is still alive. Early returns were added to avoid any
confusion.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: Manuel Lauss <manuel.lauss@googlemail.com>
CC: Rodolfo Giometti <giometti@linux.it>
CC: Olav Kongas <ok@artecdesign.ee>
CC: <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/oxu210hp-hcd.c')
-rw-r--r-- | drivers/usb/host/oxu210hp-hcd.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 4a771f6cc822..5fbe997dc6df 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -1884,6 +1884,7 @@ static int enable_periodic(struct oxu_hcd *oxu) status = handshake(oxu, &oxu->regs->status, STS_PSS, 0, 9 * 125); if (status != 0) { oxu_to_hcd(oxu)->state = HC_STATE_HALT; + usb_hc_died(oxu_to_hcd(oxu)); return status; } @@ -1909,6 +1910,7 @@ static int disable_periodic(struct oxu_hcd *oxu) status = handshake(oxu, &oxu->regs->status, STS_PSS, STS_PSS, 9 * 125); if (status != 0) { oxu_to_hcd(oxu)->state = HC_STATE_HALT; + usb_hc_died(oxu_to_hcd(oxu)); return status; } @@ -2449,8 +2451,9 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd) goto dead; } + /* Shared IRQ? */ status &= INTR_MASK; - if (!status) { /* irq sharing? */ + if (!status || unlikely(hcd->state == HC_STATE_HALT)) { spin_unlock(&oxu->lock); return IRQ_NONE; } @@ -2516,6 +2519,7 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd) dead: ehci_reset(oxu); writel(0, &oxu->regs->configured_flag); + usb_hc_died(hcd); /* generic layer kills/unlinks all urbs, then * uses oxu_stop to clean up the rest */ |