[flashrom] Add timeout check to SPI bitbang bus request

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Tue Oct 5 14:34:37 CEST 2010


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 at 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);
 };
 


-- 
http://www.hailfinger.org/





More information about the flashrom mailing list