aboutsummaryrefslogtreecommitdiffstats
path: root/raiden_debug_spi.c
diff options
context:
space:
mode:
authorEdward O'Callaghan <quasisec@google.com>2020-03-05 14:56:47 +1100
committerEdward O'Callaghan <quasisec@chromium.org>2020-03-11 06:24:10 +0000
commit2141250162934159f1158c640e0737e872fccb5b (patch)
tree54691c71f72c0445d6259e12caad81bed75870d1 /raiden_debug_spi.c
parente8c0ee7c7eb93225de1bb0d16d8bbeda4f3ed542 (diff)
downloadflashrom-2141250162934159f1158c640e0737e872fccb5b.tar.gz
flashrom-2141250162934159f1158c640e0737e872fccb5b.tar.bz2
flashrom-2141250162934159f1158c640e0737e872fccb5b.zip
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>
Diffstat (limited to 'raiden_debug_spi.c')
-rw-r--r--raiden_debug_spi.c50
1 files changed, 42 insertions, 8 deletions
diff --git a/raiden_debug_spi.c b/raiden_debug_spi.c
index 08f8928b..1f30b6a2 100644
--- a/raiden_debug_spi.c
+++ b/raiden_debug_spi.c
@@ -133,6 +133,16 @@ enum raiden_debug_spi_request {
#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.
*/
#define TRANSFER_TIMEOUT_MS (200 + 800)
@@ -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);
-
- if (status) {
- return status;
- }
+ for (int write_attempt = 0; write_attempt < WRITE_RETY_ATTEMPTS;
+ write_attempt++) {
- status = read_response(flash, write_count, read_count,
- write_buffer, read_buffer);
+ 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;
+ }
+ }
+ }
return status;
}