diff options
Diffstat (limited to 'drivers/usb')
-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 | ||||
-rw-r--r-- | drivers/usb/wusbcore/devconnect.c | 1 | ||||
-rw-r--r-- | drivers/usb/wusbcore/rh.c | 3 |
6 files changed, 34 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); |
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index e2e7e4bc8463..8e18141bb2e0 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c | |||
@@ -386,6 +386,7 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, | |||
386 | | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); | 386 | | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); |
387 | port->change |= USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE; | 387 | port->change |= USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE; |
388 | if (wusb_dev) { | 388 | if (wusb_dev) { |
389 | dev_dbg(wusbhc->dev, "disconnecting device from port %d\n", wusb_dev->port_idx); | ||
389 | if (!list_empty(&wusb_dev->cack_node)) | 390 | if (!list_empty(&wusb_dev->cack_node)) |
390 | list_del_init(&wusb_dev->cack_node); | 391 | list_del_init(&wusb_dev->cack_node); |
391 | /* For the one in cack_add() */ | 392 | /* For the one in cack_add() */ |
diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index 3937bf6f8cef..9fe4246cecb9 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c | |||
@@ -100,6 +100,9 @@ static int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx) | |||
100 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); | 100 | struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); |
101 | struct wusb_dev *wusb_dev = port->wusb_dev; | 101 | struct wusb_dev *wusb_dev = port->wusb_dev; |
102 | 102 | ||
103 | if (wusb_dev == NULL) | ||
104 | return -ENOTCONN; | ||
105 | |||
103 | port->status |= USB_PORT_STAT_RESET; | 106 | port->status |= USB_PORT_STAT_RESET; |
104 | port->change |= USB_PORT_STAT_C_RESET; | 107 | port->change |= USB_PORT_STAT_C_RESET; |
105 | 108 | ||