aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2009-08-20 16:39:56 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:38 -0400
commit68d2956a810b5c1b8213a1a9f59eacc54d7ce087 (patch)
treece63aa5c1580b217af7ddd21fecee7cd2cca6c77
parentaab2d4086a1876fcff282aa36e2d4a92aa9935c9 (diff)
USB: ehci-dbgp: errata for EHCI debug/host controller synchronization
On some EHCI debug controllers after the host controller driver is activated, the debug controller will occasionally fail to submit a bulk write URB. On controllers that exhibit this behavior a dummy bulk write must get submitted to resynchronize the device. The "dummy bulk write" does not get received by the host attached to the other end of the usb debug device. The usb debug device simply acknowledges the "dummy bulk write" and returns to a usable state. The behavior, without this patch is that you see missing text from a complete kernel boot when using the keep option to the earlyprintk kernel argument. Signed-off-by: Jason Wessel <jason.wessel@windriver.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/early/ehci-dbgp.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index f0a41c647bef..1206a26ef893 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -245,16 +245,9 @@ static inline void dbgp_get_data(void *buf, int size)
245 bytes[i] = (hi >> (8*(i - 4))) & 0xff; 245 bytes[i] = (hi >> (8*(i - 4))) & 0xff;
246} 246}
247 247
248static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, 248static int dbgp_out(u32 addr, const char *bytes, int size)
249 const char *bytes, int size)
250{ 249{
251 u32 pids, addr, ctrl; 250 u32 pids, ctrl;
252 int ret;
253
254 if (size > DBGP_MAX_PACKET)
255 return -1;
256
257 addr = DBGP_EPADDR(devnum, endpoint);
258 251
259 pids = readl(&ehci_debug->pids); 252 pids = readl(&ehci_debug->pids);
260 pids = dbgp_pid_update(pids, USB_PID_OUT); 253 pids = dbgp_pid_update(pids, USB_PID_OUT);
@@ -267,10 +260,34 @@ static int dbgp_bulk_write(unsigned devnum, unsigned endpoint,
267 dbgp_set_data(bytes, size); 260 dbgp_set_data(bytes, size);
268 writel(addr, &ehci_debug->address); 261 writel(addr, &ehci_debug->address);
269 writel(pids, &ehci_debug->pids); 262 writel(pids, &ehci_debug->pids);
263 return dbgp_wait_until_done(ctrl);
264}
270 265
271 ret = dbgp_wait_until_done(ctrl); 266static int dbgp_bulk_write(unsigned devnum, unsigned endpoint,
272 if (ret < 0) 267 const char *bytes, int size)
273 return ret; 268{
269 int ret;
270 int loops = 5;
271 u32 addr;
272 if (size > DBGP_MAX_PACKET)
273 return -1;
274
275 addr = DBGP_EPADDR(devnum, endpoint);
276try_again:
277 if (loops--) {
278 ret = dbgp_out(addr, bytes, size);
279 if (ret == -DBGP_ERR_BAD) {
280 int try_loops = 3;
281 do {
282 /* Emit a dummy packet to re-sync communication
283 * with the debug device */
284 if (dbgp_out(addr, "12345678", 8) >= 0) {
285 udelay(2);
286 goto try_again;
287 }
288 } while (try_loops--);
289 }
290 }
274 291
275 return ret; 292 return ret;
276} 293}