usbdebug: Adjust transaction retries

Transaction consistently completes with 80 to 150 status reads on my
setups. Hardware should always be able to complete this within 125us
as the debug port is serviced at the beginning of each microframe.

Timeout is set to DBGP_MICROFRAME_TIMEOUT_LOOPS=1000 status reads. Do not
retry transactions if this timeout is reached as the host controller
probably needs full re-initialisation to recover.

If this timeout is not reached, but a transaction is corrupted
on the wire, or it is otherwise not properly delivered to the USB device,
transaction is retried upto DBGP_MICROFRAME_RETRIES=10 times.

Change-Id: I44bc0a1bd194cdb5a2c13d5b81fc39bc568ae054
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: http://review.coreboot.org/3881
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@google.com>
This commit is contained in:
Kyösti Mälkki 2013-08-19 12:45:16 +03:00
parent 9a91ba1994
commit 2de841b355
1 changed files with 17 additions and 8 deletions

View File

@ -107,6 +107,8 @@ static int dbgp_enabled(void);
#define HUB_LONG_RESET_TIME 200 #define HUB_LONG_RESET_TIME 200
#define HUB_RESET_TIMEOUT 500 #define HUB_RESET_TIMEOUT 500
#define DBGP_MICROFRAME_TIMEOUT_LOOPS 1000
#define DBGP_MICROFRAME_RETRIES 10
#define DBGP_MAX_PACKET 8 #define DBGP_MAX_PACKET 8
#define DBGP_LOOPS 1000 #define DBGP_LOOPS 1000
@ -124,17 +126,17 @@ static inline struct ehci_debug_info *dbgp_ehci_info(void)
static int dbgp_wait_until_complete(struct ehci_dbg_port *ehci_debug) static int dbgp_wait_until_complete(struct ehci_dbg_port *ehci_debug)
{ {
u32 ctrl; u32 ctrl;
int loop = 0x100000; int loop = 0;
do { do {
ctrl = read32((unsigned long)&ehci_debug->control); ctrl = read32((unsigned long)&ehci_debug->control);
/* Stop when the transaction is finished */ /* Stop when the transaction is finished */
if (ctrl & DBGP_DONE) if (ctrl & DBGP_DONE)
break; break;
} while (--loop > 0); } while (++loop < DBGP_MICROFRAME_TIMEOUT_LOOPS);
if (!loop) if (! (ctrl & DBGP_DONE))
return -1; return -DBGP_ERR_SIGNAL;
/* Now that we have observed the completed transaction, /* Now that we have observed the completed transaction,
* clear the done bit. * clear the done bit.
@ -153,18 +155,25 @@ static int dbgp_wait_until_done(struct ehci_dbg_port *ehci_debug, struct dbgp_pi
{ {
u32 rd_ctrl, rd_pids; u32 rd_ctrl, rd_pids;
u8 lpid; u8 lpid;
int ret; int ret, host_retries;
retry: retry:
host_retries = 0;
host_retry:
if (host_retries++ >= DBGP_MICROFRAME_RETRIES)
return -DBGP_ERR_BAD;
write32((unsigned long)&ehci_debug->control, ctrl | DBGP_GO); write32((unsigned long)&ehci_debug->control, ctrl | DBGP_GO);
ret = dbgp_wait_until_complete(ehci_debug); ret = dbgp_wait_until_complete(ehci_debug);
rd_ctrl = read32((unsigned long)&ehci_debug->control); rd_ctrl = read32((unsigned long)&ehci_debug->control);
rd_pids = read32((unsigned long)&ehci_debug->pids); rd_pids = read32((unsigned long)&ehci_debug->pids);
if (ret < 0) { /* Controller hardware failure. */
if (ret == -DBGP_ERR_BAD && --loop > 0) if (ret == -DBGP_ERR_SIGNAL) {
goto retry;
return ret; return ret;
/* Bus failure (corrupted microframe). */
} else if (ret == -DBGP_ERR_BAD) {
goto host_retry;
} }
lpid = DBGP_PID_GET(rd_pids); lpid = DBGP_PID_GET(rd_pids);