ft2232_spi: add some error handling
Pretty much everybody who used the FT2232 SPI driver had problems with
incorrect reads from time to time. One reason was that the hardware is
pretty timing sensitive even for reads.
The other reason was that the code silently ignored errors. This patch
doesn't add any error recovery, but it will emit error messages if
FT2232 communication goes wrong. That allows us to track down errors
without investing hours in driver debugging.
Thanks to Jeremy Buseman <naviathan@gmail.com> for testing. He found out
that certain libftdi/libusb/kernel/hardware combinations drop some bytes
without returning any error codes.
Corresponding to flashrom svn r769.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Paul Fox <pgf@laptop.org>
diff --git a/ft2232_spi.c b/ft2232_spi.c
index 17930eb..aa00753 100644
--- a/ft2232_spi.c
+++ b/ft2232_spi.c
@@ -198,7 +198,8 @@
{
struct ftdi_context *ftdic = &ftdic_context;
static unsigned char *buf = NULL;
- int i = 0, ret = 0;
+ /* failed is special. We use bitwise ops, but it is essentially bool. */
+ int i = 0, ret = 0, failed = 0;
if (writecnt > 65536 || readcnt > 65536)
return SPI_INVALID_LENGTH;
@@ -237,6 +238,11 @@
buf[i++] = (readcnt - 1) & 0xff;
buf[i++] = ((readcnt - 1) >> 8) & 0xff;
ret = send_buf(ftdic, buf, i);
+ failed = ret;
+ /* We can't abort here, we still have to deassert CS#. */
+ if (ret)
+ fprintf(stderr, "send_buf failed before read: %i\n",
+ ret);
i = 0;
if (ret == 0) {
/*
@@ -245,6 +251,10 @@
* command. We may be scheduled out etc.
*/
ret = get_buf(ftdic, readarr, readcnt);
+ failed |= ret;
+ /* We can't abort here either. */
+ if (ret)
+ fprintf(stderr, "get_buf failed: %i\n", ret);
}
}
@@ -252,10 +262,12 @@
buf[i++] = SET_BITS_LOW;
buf[i++] = CS_BIT;
buf[i++] = 0x0b;
- if (send_buf(ftdic, buf, i))
- return -1;
+ ret = send_buf(ftdic, buf, i);
+ failed |= ret;
+ if (ret)
+ fprintf(stderr, "send_buf failed at end: %i\n", ret);
- return ret;
+ return failed ? -1 : 0;
}
int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)