diff --git a/raiden_debug_spi.c b/raiden_debug_spi.c index 08f8928bc..1f30b6a2c 100644 --- a/raiden_debug_spi.c +++ b/raiden_debug_spi.c @@ -132,6 +132,16 @@ enum raiden_debug_spi_request { #define MAX_PACKET_SIZE (64) #define PAYLOAD_SIZE (MAX_PACKET_SIZE - PACKET_HEADER_SIZE) +/* + * Servo Micro has an error where it is capable of acknowledging USB packets + * without loading it into the USB endpoint buffers or triggering interrupts. + * See crbug.com/952494. Retry mechanisms have been implemented to recover + * from these rare failures allowing the process to continue. + */ +#define WRITE_RETY_ATTEMPTS (3) +#define READ_RETY_ATTEMPTS (3) +#define RETY_INTERVAL_US (100 * 1000) + /* * This timeout is so large because the Raiden SPI timeout is 800ms. */ @@ -245,16 +255,40 @@ static int send_command(struct flashctx *flash, { int status = -1; - status = write_command(flash, write_count, read_count, - write_buffer, read_buffer); + for (int write_attempt = 0; write_attempt < WRITE_RETY_ATTEMPTS; + write_attempt++) { - if (status) { - return status; + status = write_command(flash, write_count, read_count, + write_buffer, read_buffer); + + if (status) { + /* Write operation failed. */ + msg_perr("Raiden: Write command failed\n" + "Write attempt = %d\n" + "status = %d\n", + write_attempt + 1, status); + programmer_delay(RETY_INTERVAL_US); + continue; + } + for (int read_attempt = 0; read_attempt < READ_RETY_ATTEMPTS; read_attempt++) { + + status = read_response(flash, write_count, read_count, + write_buffer, read_buffer); + + if (status != 0) { + /* Read operation failed. */ + msg_perr("Raiden: Read response failed\n" + "Write attempt = %d\n" + "Read attempt = %d\n" + "status = %d\n", + write_attempt + 1, read_attempt + 1, status); + programmer_delay(RETY_INTERVAL_US); + } else { + /* We were successful at performing the SPI transfer. */ + return status; + } + } } - - status = read_response(flash, write_count, read_count, - write_buffer, read_buffer); - return status; }