diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2010-02-05 11:49:05 -0600 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 14:54:58 -0800 |
commit | 815e173e1d71742f1135fb4d4931e8115a3ca0ef (patch) | |
tree | 14ccc8eb7e1082a896e3ae6906c52b6a21cac264 /drivers/usb/early | |
parent | 5272098365514ab232fa6a695d58c3961fec6b7a (diff) |
USB: ehci-dbgp: split PID register updates for IN and OUT pipes
This patch addresses two problems:
1) Bulk reads should always use the DATA0 for the pid, and the write
PID should toggle between DATA0 and DATA1. The fix is using
dbgp_pid_write_update() and dbgp_pid_read_update().
2) The delay loop for waiting for a transaction was not long enough to
always complete the initial handshake inside dbgp_wait_until_done().
After the initial handshake the maximum delay length is never reached.
The combined result of these two changes allows for the removal of the
forced resynchronization where a bulk write was issued with a dummy
data payload only to get the device to start accepting data writes
again.
CC: Eric Biederman <ebiederm@xmission.com>
CC: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/early')
-rw-r--r-- | drivers/usb/early/ehci-dbgp.c | 68 |
1 files changed, 28 insertions, 40 deletions
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 2958a1271b20..6e98a3697844 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -66,8 +66,6 @@ static struct ehci_dev ehci_dev; #define USB_DEBUG_DEVNUM 127 -#define DBGP_DATA_TOGGLE 0x8800 - #ifdef DBGP_DEBUG #define dbgp_printk printk static void dbgp_ehci_status(char *str) @@ -88,11 +86,6 @@ static inline void dbgp_ehci_status(char *str) { } static inline void dbgp_printk(const char *fmt, ...) { } #endif -static inline u32 dbgp_pid_update(u32 x, u32 tok) -{ - return ((x ^ DBGP_DATA_TOGGLE) & 0xffff00) | (tok & 0xff); -} - static inline u32 dbgp_len_update(u32 x, u32 len) { return (x & ~0x0f) | (len & 0x0f); @@ -136,6 +129,19 @@ static inline u32 dbgp_len_update(u32 x, u32 len) #define DBGP_MAX_PACKET 8 #define DBGP_TIMEOUT (250 * 1000) +#define DBGP_LOOPS 1000 + +static inline u32 dbgp_pid_write_update(u32 x, u32 tok) +{ + static int data0 = USB_PID_DATA1; + data0 ^= USB_PID_DATA_TOGGLE; + return (x & 0xffff0000) | (data0 << 8) | (tok & 0xff); +} + +static inline u32 dbgp_pid_read_update(u32 x, u32 tok) +{ + return (x & 0xffff0000) | (USB_PID_DATA0 << 8) | (tok & 0xff); +} static int dbgp_wait_until_complete(void) { @@ -180,7 +186,7 @@ static int dbgp_wait_until_done(unsigned ctrl) { u32 pids, lpid; int ret; - int loop = 3; + int loop = DBGP_LOOPS; retry: writel(ctrl | DBGP_GO, &ehci_debug->control); @@ -197,6 +203,8 @@ retry: */ if (ret == -DBGP_TIMEOUT && !dbgp_not_safe) dbgp_not_safe = 1; + if (ret == -DBGP_ERR_BAD && --loop > 0) + goto retry; return ret; } @@ -245,12 +253,20 @@ static inline void dbgp_get_data(void *buf, int size) bytes[i] = (hi >> (8*(i - 4))) & 0xff; } -static int dbgp_out(u32 addr, const char *bytes, int size) +static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, + const char *bytes, int size) { + int ret; + u32 addr; u32 pids, ctrl; + if (size > DBGP_MAX_PACKET) + return -1; + + addr = DBGP_EPADDR(devnum, endpoint); + pids = readl(&ehci_debug->pids); - pids = dbgp_pid_update(pids, USB_PID_OUT); + pids = dbgp_pid_write_update(pids, USB_PID_OUT); ctrl = readl(&ehci_debug->control); ctrl = dbgp_len_update(ctrl, size); @@ -260,34 +276,7 @@ static int dbgp_out(u32 addr, const char *bytes, int size) dbgp_set_data(bytes, size); writel(addr, &ehci_debug->address); writel(pids, &ehci_debug->pids); - return dbgp_wait_until_done(ctrl); -} - -static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, - const char *bytes, int size) -{ - int ret; - int loops = 5; - u32 addr; - if (size > DBGP_MAX_PACKET) - return -1; - - addr = DBGP_EPADDR(devnum, endpoint); -try_again: - if (loops--) { - ret = dbgp_out(addr, bytes, size); - if (ret == -DBGP_ERR_BAD) { - int try_loops = 3; - do { - /* Emit a dummy packet to re-sync communication - * with the debug device */ - if (dbgp_out(addr, "12345678", 8) >= 0) { - udelay(2); - goto try_again; - } - } while (try_loops--); - } - } + ret = dbgp_wait_until_done(ctrl); return ret; } @@ -304,7 +293,7 @@ static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, addr = DBGP_EPADDR(devnum, endpoint); pids = readl(&ehci_debug->pids); - pids = dbgp_pid_update(pids, USB_PID_IN); + pids = dbgp_pid_read_update(pids, USB_PID_IN); ctrl = readl(&ehci_debug->control); ctrl = dbgp_len_update(ctrl, size); @@ -362,7 +351,6 @@ static int dbgp_control_msg(unsigned devnum, int requesttype, return dbgp_bulk_read(devnum, 0, data, size); } - /* Find a PCI capability */ static u32 __init find_cap(u32 num, u32 slot, u32 func, int cap) { |