1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 15:12:36 +02:00

raiden_debug_spi.c: Implement retry mechanism

This overcomes a problem with the ServoMicro where USB packets can be
ack'd by the device without triggering interrupts or loading data into
the USB endpoints. The retry mechanism attempts the USB read 3 times
before reattempting the write call to avoid performing multiple SPI
transfers due to a USB problem. This process repeats 3 times before we
return the last error code. Intermediary problems are reported in the
status code.

Based off the downstream commit:
  https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/+/2038271

Change-Id: I76cde68852fa4963582d57c7dcb9f24de32c6da8
Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/39310
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Edward O'Callaghan 2020-03-05 14:56:47 +11:00 committed by Edward O'Callaghan
parent e8c0ee7c7e
commit 2141250162

View File

@ -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;
}