Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+30 -4
+7 -2
drivers/usb/host/whci/asl.c
··· 170 170 void asl_update(struct whc *whc, uint32_t wusbcmd) 171 171 { 172 172 struct wusbhc *wusbhc = &whc->wusbhc; 173 + long t; 173 174 174 175 mutex_lock(&wusbhc->mutex); 175 176 if (wusbhc->active) { 176 177 whc_write_wusbcmd(whc, wusbcmd, wusbcmd); 177 - wait_event(whc->async_list_wq, 178 - (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0); 178 + t = wait_event_timeout( 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 185 mutex_unlock(&wusbhc->mutex); 181 186 }
+15
drivers/usb/host/whci/hw.c
··· 87 87 88 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 + }
+7 -2
drivers/usb/host/whci/pzl.c
··· 183 183 void pzl_update(struct whc *whc, uint32_t wusbcmd) 184 184 { 185 185 struct wusbhc *wusbhc = &whc->wusbhc; 186 + long t; 186 187 187 188 mutex_lock(&wusbhc->mutex); 188 189 if (wusbhc->active) { 189 190 whc_write_wusbcmd(whc, wusbcmd, wusbcmd); 190 - wait_event(whc->periodic_list_wq, 191 - (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0); 191 + t = wait_event_timeout( 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 198 mutex_unlock(&wusbhc->mutex); 194 199 }
+1
drivers/usb/host/whci/whcd.h
··· 137 137 /* hw.c */ 138 138 void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); 139 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 142 /* wusb.c */ 142 143 int whc_wusbhc_start(struct wusbhc *wusbhc);