diff options
| -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); |
