summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/hcd.c5
-rw-r--r--drivers/usb/host/ehci-hcd.c4
-rw-r--r--drivers/usb/host/ehci-sched.c8
-rw-r--r--drivers/usb/host/isp116x-hcd.c1
-rw-r--r--drivers/usb/host/ohci-hcd.c4
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c6
6 files changed, 19 insertions, 9 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 10936ba9c42..ace9f8442e5 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -986,7 +986,7 @@ static int register_root_hub(struct usb_hcd *hcd)
spin_unlock_irq (&hcd_root_hub_lock);
/* Did the HC die before the root hub was registered? */
- if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT)
+ if (HCD_DEAD(hcd))
usb_hc_died (hcd); /* This time clean up */
}
@@ -2128,9 +2128,6 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
if (hcd->shared_hcd)
set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
-
- if (unlikely(hcd->state == HC_STATE_HALT))
- usb_hc_died(hcd);
rc = IRQ_HANDLED;
}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c5719cd258c..b435ed67dd5 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -777,8 +777,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
goto dead;
}
+ /* Shared IRQ? */
masked_status = status & INTR_MASK;
- if (!masked_status) { /* irq sharing? */
+ if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) {
spin_unlock(&ehci->lock);
return IRQ_NONE;
}
@@ -873,6 +874,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
dead:
ehci_reset(ehci);
ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+ usb_hc_died(hcd);
/* generic layer kills/unlinks all urbs, then
* uses ehci_stop to clean up the rest
*/
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index a7408d88fda..6c9fbe352f7 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -471,8 +471,10 @@ static int enable_periodic (struct ehci_hcd *ehci)
*/
status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
STS_PSS, 0, 9 * 125);
- if (status)
+ if (status) {
+ usb_hc_died(ehci_to_hcd(ehci));
return status;
+ }
cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
ehci_writel(ehci, cmd, &ehci->regs->command);
@@ -510,8 +512,10 @@ static int disable_periodic (struct ehci_hcd *ehci)
*/
status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
STS_PSS, STS_PSS, 9 * 125);
- if (status)
+ if (status) {
+ usb_hc_died(ehci_to_hcd(ehci));
return status;
+ }
cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
ehci_writel(ehci, cmd, &ehci->regs->command);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index c0e22f26da1..baae4ccd16a 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -612,6 +612,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd)
/* IRQ's are off, we do no DMA,
perfectly ready to die ... */
hcd->state = HC_STATE_HALT;
+ usb_hc_died(hcd);
ret = IRQ_HANDLED;
goto done;
}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 8c8dc6559ac..9aa10bdf391 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -764,6 +764,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
if (ints == ~(u32)0) {
disable (ohci);
ohci_dbg (ohci, "device removed!\n");
+ usb_hc_died(hcd);
return IRQ_HANDLED;
}
@@ -771,7 +772,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
ints &= ohci_readl(ohci, &regs->intrenable);
/* interrupt for some other device? */
- if (ints == 0)
+ if (ints == 0 || unlikely(hcd->state == HC_STATE_HALT))
return IRQ_NOTMINE;
if (ints & OHCI_INTR_UE) {
@@ -788,6 +789,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
} else {
disable (ohci);
ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
+ usb_hc_died(hcd);
}
ohci_dump (ohci, 1);
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index 4a771f6cc82..5fbe997dc6d 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
*/