aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/whci/asl.c9
-rw-r--r--drivers/usb/host/whci/hw.c15
-rw-r--r--drivers/usb/host/whci/pzl.c9
-rw-r--r--drivers/usb/host/whci/whcd.h1
-rw-r--r--drivers/usb/wusbcore/devconnect.c1
-rw-r--r--drivers/usb/wusbcore/rh.c3
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)
170void asl_update(struct whc *whc, uint32_t wusbcmd) 170void 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 */
98void 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)
183void pzl_update(struct whc *whc, uint32_t wusbcmd) 183void 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 */
138void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); 138void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val);
139int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); 139int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len);
140void whc_hw_error(struct whc *whc, const char *reason);
140 141
141/* wusb.c */ 142/* wusb.c */
142int whc_wusbhc_start(struct wusbhc *wusbhc); 143int 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