linux_spi.c: Refactor singleton states into reentrant pattern

Move global singleton states into a struct and store within
the spi_master data field for the life-time of the driver.

This is one of the steps on the way to move spi_master data
memory management behind the initialisation API, for more
context see other patches under the same topic "register_master_api".

Change-Id: I93408c2ca846fca6a1c7eda7180862c51bd48078
Signed-off-by: Anastasia Klimchuk <aklm@chromium.org>
Original-Reviewed-on: https://review.coreboot.org/c/flashrom/+/52285
Original-Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/72169
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
diff --git a/linux_spi.c b/linux_spi.c
index f717c99..fdfec55 100644
--- a/linux_spi.c
+++ b/linux_spi.c
@@ -44,9 +44,12 @@
  * HummingBoard
  */
 
-static int fd = -1;
 #define BUF_SIZE_FROM_SYSFS	"/sys/module/spidev/parameters/bufsiz"
-static size_t max_kernel_buf_size;
+
+struct linux_spi_data {
+	int fd;
+	size_t max_kernel_buf_size;
+};
 
 static int linux_spi_shutdown(void *data);
 static int linux_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
@@ -58,7 +61,7 @@
 static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf,
 			       unsigned int start, unsigned int len);
 
-static const struct spi_master spi_master_linux = {
+static struct spi_master spi_master_linux = {
 	.features	= SPI_MASTER_4BA,
 	.max_data_read	= MAX_DATA_UNSPECIFIED, /* TODO? */
 	.max_data_write	= MAX_DATA_UNSPECIFIED, /* TODO? */
@@ -117,6 +120,9 @@
 	/* SPI mode 0 (beware this also includes: MSB first, CS active low and others */
 	const uint8_t mode = SPI_MODE_0;
 	const uint8_t bits = 8;
+	int fd = -1;
+	size_t max_kernel_buf_size;
+	struct linux_spi_data *spi_data;
 	int ret = 0;
 
 	p = extract_programmer_param("spispeed");
@@ -176,7 +182,18 @@
 	max_kernel_buf_size = get_max_kernel_buf_size();
 	msg_pdbg("%s: max_kernel_buf_size: %zu\n", __func__, max_kernel_buf_size);
 
-	if (register_shutdown(linux_spi_shutdown, NULL)) {
+	spi_data = calloc(1, sizeof(*spi_data));
+	if (!spi_data) {
+		msg_perr("Unable to allocated space for SPI master data\n");
+		ret = SPI_GENERIC_ERROR;
+		goto init_err;
+	}
+	spi_data->fd = fd;
+	spi_data->max_kernel_buf_size = max_kernel_buf_size;
+	spi_master_linux.data = spi_data;
+
+	if (register_shutdown(linux_spi_shutdown, spi_data)) {
+		free(spi_data);
 		ret = 1;
 		goto init_err;
 	}
@@ -193,10 +210,11 @@
 
 static int linux_spi_shutdown(void *data)
 {
-	if (fd != -1) {
-		close(fd);
-		fd = -1;
-	}
+	struct linux_spi_data *spi_data = (struct linux_spi_data *) data;
+	if (spi_data->fd != -1)
+		close(spi_data->fd);
+
+	free(spi_data);
 	return 0;
 }
 
@@ -205,6 +223,7 @@
 				  const unsigned char *txbuf,
 				  unsigned char *rxbuf)
 {
+	struct linux_spi_data *spi_data = flash->mst->spi.data;
 	int iocontrol_code;
 	struct spi_ioc_transfer msg[2] = {
 		{
@@ -217,7 +236,7 @@
 		},
 	};
 
-	if (fd == -1)
+	if (spi_data->fd == -1)
 		return -1;
 	/* The implementation currently does not support requests that
 	   don't start with sending a command. */
@@ -231,7 +250,7 @@
 	else
 		iocontrol_code = SPI_IOC_MESSAGE(2);
 
-	if (ioctl(fd, iocontrol_code, msg) == -1) {
+	if (ioctl(spi_data->fd, iocontrol_code, msg) == -1) {
 		msg_cerr("%s: ioctl: %s\n", __func__, strerror(errno));
 		return -1;
 	}
@@ -240,15 +259,17 @@
 
 static int linux_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
 {
+	struct linux_spi_data *spi_data = flash->mst->spi.data;
 	/* Older kernels use a single buffer for combined input and output
 	   data. So account for longest possible command + address, too. */
-	return spi_read_chunked(flash, buf, start, len, max_kernel_buf_size - 5);
+	return spi_read_chunked(flash, buf, start, len, spi_data->max_kernel_buf_size - 5);
 }
 
 static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
 {
+	struct linux_spi_data *spi_data = flash->mst->spi.data;
 	/* 5 bytes must be reserved for longest possible command + address. */
-	return spi_write_chunked(flash, buf, start, len, max_kernel_buf_size - 5);
+	return spi_write_chunked(flash, buf, start, len, spi_data->max_kernel_buf_size - 5);
 }
 
 const struct programmer_entry programmer_linux_spi = {