Hi Iain,
your Intel 82540EM which hangs on a flashrom run should spew "Timeout!" messages with this patch. It would be nice if you could tell us how long it waits for each chip probe so I can adjust the timeout value. Please note that this patch will _not_ fix the underlying issue, but I believe that an endless loop on possibly broken hardware is worse than aborting.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-bitbang_timeout/flash.h =================================================================== --- flashrom-bitbang_timeout/flash.h (Revision 1185) +++ flashrom-bitbang_timeout/flash.h (Arbeitskopie) @@ -35,6 +35,9 @@
#define ERROR_PTR ((void*)-1)
+/* Error codes */ +#define TIMEOUT_ERROR -101 + typedef unsigned long chipaddr;
int register_shutdown(void (*function) (void *data), void *data); Index: flashrom-bitbang_timeout/bitbang_spi.c =================================================================== --- flashrom-bitbang_timeout/bitbang_spi.c (Revision 1185) +++ flashrom-bitbang_timeout/bitbang_spi.c (Arbeitskopie) @@ -53,10 +53,11 @@ return bitbang_spi_master->get_miso(); }
-static void bitbang_spi_request_bus(void) +static int bitbang_spi_request_bus(void) { if (bitbang_spi_master->request_bus) - bitbang_spi_master->request_bus(); + return bitbang_spi_master->request_bus(); + return 0; }
static void bitbang_spi_release_bus(void) @@ -86,7 +87,7 @@ bitbang_spi_master = master; bitbang_spi_half_period = halfperiod;
- /* FIXME: Run bitbang_spi_request_bus here or in programmer init? */ + /* FIXME: Run bitbang_spi_request_bus here or per command? */ bitbang_spi_set_cs(1); bitbang_spi_set_sck(0); bitbang_spi_set_mosi(0); @@ -131,13 +132,15 @@ int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) { - int i; + int i, ret;
/* FIXME: Run bitbang_spi_request_bus here or in programmer init? * Requesting and releasing the SPI bus is handled in here to allow the * programmer to use its own SPI engine for native accesses. */ - bitbang_spi_request_bus(); + ret = bitbang_spi_request_bus(); + if (ret) + return ret; bitbang_spi_set_cs(0); for (i = 0; i < writecnt; i++) bitbang_spi_readwrite_byte(writearr[i]); Index: flashrom-bitbang_timeout/nicintel_spi.c =================================================================== --- flashrom-bitbang_timeout/nicintel_spi.c (Revision 1185) +++ flashrom-bitbang_timeout/nicintel_spi.c (Arbeitskopie) @@ -58,6 +58,8 @@ // #define FL_BUSY 30 // #define FL_ER 31
+#define MAX_REQUEST_LOOPS 10000 + uint8_t *nicintel_spibar;
const struct pcidev_status nics_intel_spi[] = { @@ -68,16 +70,27 @@ {}, };
-static void nicintel_request_spibus(void) +static void nicintel_release_spibus(void); + +static int nicintel_request_spibus(void) { uint32_t tmp; + int i = 0;
tmp = pci_mmio_readl(nicintel_spibar + FLA); tmp |= 1 << FL_REQ; pci_mmio_writel(tmp, nicintel_spibar + FLA);
/* Wait until we are allowed to use the SPI bus. */ - while (!(pci_mmio_readl(nicintel_spibar + FLA) & (1 << FL_GNT))) ; + while (!(pci_mmio_readl(nicintel_spibar + FLA) & (1 << FL_GNT))) { + if (i++ > MAX_REQUEST_LOOPS) { + nicintel_release_spibus(); + msg_perr("%s: Timeout! Aborting.\n", __func__); + return TIMEOUT_ERROR; + } + } + + return 0; }
static void nicintel_release_spibus(void) Index: flashrom-bitbang_timeout/mcp6x_spi.c =================================================================== --- flashrom-bitbang_timeout/mcp6x_spi.c (Revision 1185) +++ flashrom-bitbang_timeout/mcp6x_spi.c (Arbeitskopie) @@ -40,22 +40,37 @@ #define MCP6X_SPI_REQUEST 0 #define MCP6X_SPI_GRANT 8
+#define MAX_REQUEST_LOOPS 10000 + void *mcp6x_spibar = NULL;
/* Cached value of last GPIO state. */ static uint8_t mcp_gpiostate;
-static void mcp6x_request_spibus(void) +static void mcp6x_release_spibus(void); + +static int mcp6x_request_spibus(void) { + int i = 0; + mcp_gpiostate = mmio_readb(mcp6x_spibar + 0x530); mcp_gpiostate |= 1 << MCP6X_SPI_REQUEST; mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530);
/* Wait until we are allowed to use the SPI bus. */ - while (!(mmio_readw(mcp6x_spibar + 0x530) & (1 << MCP6X_SPI_GRANT))) ; + while (!(mmio_readw(mcp6x_spibar + 0x530) & (1 << MCP6X_SPI_GRANT))) { + if (i++ > MAX_REQUEST_LOOPS) { + /* Update the cache. */ + mcp_gpiostate = mmio_readb(mcp6x_spibar + 0x530); + mcp6x_release_spibus(); + msg_perr("%s: Timeout! Aborting.\n", __func__); + return TIMEOUT_ERROR; + } + }
/* Update the cache. */ mcp_gpiostate = mmio_readb(mcp6x_spibar + 0x530); + return 0; }
static void mcp6x_release_spibus(void) Index: flashrom-bitbang_timeout/programmer.h =================================================================== --- flashrom-bitbang_timeout/programmer.h (Revision 1185) +++ flashrom-bitbang_timeout/programmer.h (Arbeitskopie) @@ -131,7 +131,7 @@ void (*set_sck) (int val); void (*set_mosi) (int val); int (*get_miso) (void); - void (*request_bus) (void); + int (*request_bus) (void); void (*release_bus) (void); };