summaryrefslogtreecommitdiff
path: root/drivers/usb/host/whci/asl.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2008-11-25 14:23:40 +0000
committerDavid Vrabel <david.vrabel@csr.com>2008-11-25 14:23:40 +0000
commit56968d0c1a920eb165c06318f5c458724e1df0af (patch)
tree9516fdc8ef8bc67bf6a51a1e4940d3ae59008dfa /drivers/usb/host/whci/asl.c
parent65d76f368295973a35d195c9b13053502a67b6bc (diff)
wusb: whci-hcd shouldn't do ASL/PZL updates while channel is inactive
ASL/PZL updates while the WUSB channel is inactive (i.e., the PZL and ASL are stopped) may not complete. This causes hangs when removing the whci-hcd module if a device is still connected (removing the device does an endpoint_disable which results in an ASL update to remove the qset). If the WUSB channel is inactive the update can simply be skipped as the WHC doesn't care about the state of the ASL/PZL. Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/usb/host/whci/asl.c')
-rw-r--r--drivers/usb/host/whci/asl.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c
index 4d7078e50572..ba99a7a3f81a 100644
--- a/drivers/usb/host/whci/asl.c
+++ b/drivers/usb/host/whci/asl.c
@@ -179,11 +179,26 @@ void asl_stop(struct whc *whc)
1000, "stop ASL");
}
+/**
+ * asl_update - request an ASL update and wait for the hardware to be synced
+ * @whc: the WHCI HC
+ * @wusbcmd: WUSBCMD value to start the update.
+ *
+ * If the WUSB HC is inactive (i.e., the ASL is stopped) then the
+ * update must be skipped as the hardware may not respond to update
+ * requests.
+ */
void asl_update(struct whc *whc, uint32_t wusbcmd)
{
- whc_write_wusbcmd(whc, wusbcmd, wusbcmd);
- wait_event(whc->async_list_wq,
- (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0);
+ struct wusbhc *wusbhc = &whc->wusbhc;
+
+ mutex_lock(&wusbhc->mutex);
+ if (wusbhc->active) {
+ whc_write_wusbcmd(whc, wusbcmd, wusbcmd);
+ wait_event(whc->async_list_wq,
+ (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0);
+ }
+ mutex_unlock(&wusbhc->mutex);
}
/**