aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/whci/pzl.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2008-11-25 09:23:40 -0500
committerDavid Vrabel <david.vrabel@csr.com>2008-11-25 09:23:40 -0500
commit56968d0c1a920eb165c06318f5c458724e1df0af (patch)
tree9516fdc8ef8bc67bf6a51a1e4940d3ae59008dfa /drivers/usb/host/whci/pzl.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/pzl.c')
-rw-r--r--drivers/usb/host/whci/pzl.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c
index 8d62df0c330b..34d3a0aeab2b 100644
--- a/drivers/usb/host/whci/pzl.c
+++ b/drivers/usb/host/whci/pzl.c
@@ -195,11 +195,26 @@ void pzl_stop(struct whc *whc)
195 1000, "stop PZL"); 195 1000, "stop PZL");
196} 196}
197 197
198/**
199 * pzl_update - request a PZL update and wait for the hardware to be synced
200 * @whc: the WHCI HC
201 * @wusbcmd: WUSBCMD value to start the update.
202 *
203 * If the WUSB HC is inactive (i.e., the PZL is stopped) then the
204 * update must be skipped as the hardware may not respond to update
205 * requests.
206 */
198void pzl_update(struct whc *whc, uint32_t wusbcmd) 207void pzl_update(struct whc *whc, uint32_t wusbcmd)
199{ 208{
200 whc_write_wusbcmd(whc, wusbcmd, wusbcmd); 209 struct wusbhc *wusbhc = &whc->wusbhc;
201 wait_event(whc->periodic_list_wq, 210
202 (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0); 211 mutex_lock(&wusbhc->mutex);
212 if (wusbhc->active) {
213 whc_write_wusbcmd(whc, wusbcmd, wusbcmd);
214 wait_event(whc->periodic_list_wq,
215 (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0);
216 }
217 mutex_unlock(&wusbhc->mutex);
203} 218}
204 219
205static void update_pzl_hw_view(struct whc *whc) 220static void update_pzl_hw_view(struct whc *whc)