diff options
| author | David Vrabel <david.vrabel@csr.com> | 2009-01-07 05:54:22 -0500 | 
|---|---|---|
| committer | David Vrabel <david.vrabel@csr.com> | 2009-01-07 05:54:22 -0500 | 
| commit | a5e6ced58d423cb09c4fc0087dcfdb0b5deb5e1c (patch) | |
| tree | 56ab507e1df59cae1f57c2f5883bc676f1147441 | |
| parent | a23e66f3b8cfdedec14541e71ef29a754870a20c (diff) | |
wusb: timeout when waiting for ASL/PZL updates in whci-hcd
Timeout if an ASL or PZL update doesn't not complete and reset the
hardware.
Signed-off-by: David Vrabel <david.vrabel@csr.com>
| -rw-r--r-- | drivers/usb/host/whci/asl.c | 9 | ||||
| -rw-r--r-- | drivers/usb/host/whci/hw.c | 15 | ||||
| -rw-r--r-- | drivers/usb/host/whci/pzl.c | 9 | ||||
| -rw-r--r-- | drivers/usb/host/whci/whcd.h | 1 | 
4 files changed, 30 insertions, 4 deletions
| diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index 577c0d29849d..2291c5f5af51 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
| @@ -170,12 +170,17 @@ void asl_stop(struct whc *whc) | |||
| 170 | void asl_update(struct whc *whc, uint32_t wusbcmd) | 170 | void asl_update(struct whc *whc, uint32_t wusbcmd) | 
| 171 | { | 171 | { | 
| 172 | struct wusbhc *wusbhc = &whc->wusbhc; | 172 | struct wusbhc *wusbhc = &whc->wusbhc; | 
| 173 | long t; | ||
| 173 | 174 | ||
| 174 | mutex_lock(&wusbhc->mutex); | 175 | mutex_lock(&wusbhc->mutex); | 
| 175 | if (wusbhc->active) { | 176 | if (wusbhc->active) { | 
| 176 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 177 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 
| 177 | wait_event(whc->async_list_wq, | 178 | t = wait_event_timeout( | 
| 178 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0); | 179 | whc->async_list_wq, | 
| 180 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0, | ||
| 181 | msecs_to_jiffies(1000)); | ||
| 182 | if (t == 0) | ||
| 183 | whc_hw_error(whc, "ASL update timeout"); | ||
| 179 | } | 184 | } | 
| 180 | mutex_unlock(&wusbhc->mutex); | 185 | mutex_unlock(&wusbhc->mutex); | 
| 181 | } | 186 | } | 
| diff --git a/drivers/usb/host/whci/hw.c b/drivers/usb/host/whci/hw.c index d498e7203217..6afa2e379160 100644 --- a/drivers/usb/host/whci/hw.c +++ b/drivers/usb/host/whci/hw.c | |||
| @@ -87,3 +87,18 @@ out: | |||
| 87 | 87 | ||
| 88 | return ret; | 88 | return ret; | 
| 89 | } | 89 | } | 
| 90 | |||
| 91 | /** | ||
| 92 | * whc_hw_error - recover from a hardware error | ||
| 93 | * @whc: the WHCI HC that broke. | ||
| 94 | * @reason: a description of the failure. | ||
| 95 | * | ||
| 96 | * Recover from broken hardware with a full reset. | ||
| 97 | */ | ||
| 98 | void whc_hw_error(struct whc *whc, const char *reason) | ||
| 99 | { | ||
| 100 | struct wusbhc *wusbhc = &whc->wusbhc; | ||
| 101 | |||
| 102 | dev_err(&whc->umc->dev, "hardware error: %s\n", reason); | ||
| 103 | wusbhc_reset_all(wusbhc); | ||
| 104 | } | ||
| diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index 2ae5abf69a6a..7dc85a0bee7c 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c | |||
| @@ -183,12 +183,17 @@ void pzl_stop(struct whc *whc) | |||
| 183 | void pzl_update(struct whc *whc, uint32_t wusbcmd) | 183 | void pzl_update(struct whc *whc, uint32_t wusbcmd) | 
| 184 | { | 184 | { | 
| 185 | struct wusbhc *wusbhc = &whc->wusbhc; | 185 | struct wusbhc *wusbhc = &whc->wusbhc; | 
| 186 | long t; | ||
| 186 | 187 | ||
| 187 | mutex_lock(&wusbhc->mutex); | 188 | mutex_lock(&wusbhc->mutex); | 
| 188 | if (wusbhc->active) { | 189 | if (wusbhc->active) { | 
| 189 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 190 | whc_write_wusbcmd(whc, wusbcmd, wusbcmd); | 
| 190 | wait_event(whc->periodic_list_wq, | 191 | t = wait_event_timeout( | 
| 191 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0); | 192 | whc->periodic_list_wq, | 
| 193 | (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0, | ||
| 194 | msecs_to_jiffies(1000)); | ||
| 195 | if (t == 0) | ||
| 196 | whc_hw_error(whc, "PZL update timeout"); | ||
| 192 | } | 197 | } | 
| 193 | mutex_unlock(&wusbhc->mutex); | 198 | mutex_unlock(&wusbhc->mutex); | 
| 194 | } | 199 | } | 
| diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index 0f3540f04f53..d3543a181dc9 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h | |||
| @@ -137,6 +137,7 @@ void whc_clean_up(struct whc *whc); | |||
| 137 | /* hw.c */ | 137 | /* hw.c */ | 
| 138 | void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); | 138 | void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); | 
| 139 | int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); | 139 | int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); | 
| 140 | void whc_hw_error(struct whc *whc, const char *reason); | ||
| 140 | 141 | ||
| 141 | /* wusb.c */ | 142 | /* wusb.c */ | 
| 142 | int whc_wusbhc_start(struct wusbhc *wusbhc); | 143 | int whc_wusbhc_start(struct wusbhc *wusbhc); | 
