aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/whci/hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/whci/hw.c')
-rw-r--r--drivers/usb/host/whci/hw.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/usb/host/whci/hw.c b/drivers/usb/host/whci/hw.c
index ac86e59c1225..6afa2e379160 100644
--- a/drivers/usb/host/whci/hw.c
+++ b/drivers/usb/host/whci/hw.c
@@ -50,6 +50,7 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len)
unsigned long flags;
dma_addr_t dma_addr;
int t;
+ int ret = 0;
mutex_lock(&whc->mutex);
@@ -61,7 +62,8 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len)
dev_err(&whc->umc->dev, "generic command timeout (%04x/%04x)\n",
le_readl(whc->base + WUSBGENCMDSTS),
le_readl(whc->base + WUSBGENCMDPARAMS));
- return -ETIMEDOUT;
+ ret = -ETIMEDOUT;
+ goto out;
}
if (addr) {
@@ -80,8 +82,23 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len)
whc->base + WUSBGENCMDSTS);
spin_unlock_irqrestore(&whc->lock, flags);
-
+out:
mutex_unlock(&whc->mutex);
- return 0;
+ return ret;
+}
+
+/**
+ * whc_hw_error - recover from a hardware error
+ * @whc: the WHCI HC that broke.
+ * @reason: a description of the failure.
+ *
+ * Recover from broken hardware with a full reset.
+ */
+void whc_hw_error(struct whc *whc, const char *reason)
+{
+ struct wusbhc *wusbhc = &whc->wusbhc;
+
+ dev_err(&whc->umc->dev, "hardware error: %s\n", reason);
+ wusbhc_reset_all(wusbhc);
}