Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 2 Mar 2019 20:58:51 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r344728 - head/sys/dev/flash
Message-ID:  <201903022058.x22Kwp5u017774@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sat Mar  2 20:58:51 2019
New Revision: 344728
URL: https://svnweb.freebsd.org/changeset/base/344728

Log:
  Bugfix: use a dummy buffer for the inactive side of a transfer.
  
  This is especially important for writes.  SPI is inherently a bidirectional
  bus; you receive data (even if it's garbage) while writing.  We should not
  receive that data into the same buffer we're writing to the device.
  
  When reading it doesn't matter what we send to the device, but using the
  dummy buffer for that as well is pleasingly symmetrical.

Modified:
  head/sys/dev/flash/at45d.c

Modified: head/sys/dev/flash/at45d.c
==============================================================================
--- head/sys/dev/flash/at45d.c	Sat Mar  2 16:28:29 2019	(r344727)
+++ head/sys/dev/flash/at45d.c	Sat Mar  2 20:58:51 2019	(r344728)
@@ -95,6 +95,7 @@ struct at45d_softc
 	uint16_t		pagecount;
 	uint16_t		pageoffset;
 	uint16_t		pagesize;
+	void			*dummybuf;
 };
 
 #define	TSTATE_STOPPED	0
@@ -285,6 +286,7 @@ at45d_detach(device_t dev)
 	if (err == 0 && sc->taskstate == TSTATE_STOPPED) {
 		disk_destroy(sc->disk);
 		bioq_flush(&sc->bio_queue, NULL, ENXIO);
+		free(sc->dummybuf, M_DEVBUF);
 		AT45D_LOCK_DESTROY(sc);
 	}
 	return (err);
@@ -334,6 +336,8 @@ at45d_delayed_attach(void *xsc)
 		pagesize = ident->pagesize;
 	sc->pagesize = pagesize;
 
+	sc->dummybuf = malloc(pagesize, M_DEVBUF, M_WAITOK | M_ZERO);
+
 	sc->disk = disk_alloc();
 	sc->disk->d_open = at45d_open;
 	sc->disk->d_close = at45d_close;
@@ -444,11 +448,13 @@ at45d_task(void *arg)
 		case BIO_READ:
 			txBuf[0] = CONTINUOUS_ARRAY_READ;
 			cmd.tx_cmd_sz = cmd.rx_cmd_sz = 8;
-			cmd.tx_data = cmd.rx_data = buf;
+			cmd.tx_data = sc->dummybuf;
+			cmd.rx_data = buf;
 			break;
 		case BIO_WRITE:
 			cmd.tx_cmd_sz = cmd.rx_cmd_sz = 4;
-			cmd.tx_data = cmd.rx_data = buf;
+			cmd.tx_data = buf;
+			cmd.rx_data = sc->dummybuf;
 			if (resid + offset > sc->pagesize)
 				len = sc->pagesize - offset;
 			break;
@@ -524,7 +530,10 @@ at45d_task(void *arg)
 				len = sc->pagesize;
 			else
 				len = resid;
-			cmd.tx_data = cmd.rx_data = buf;
+			if (bp->bio_cmd == BIO_READ)
+				cmd.rx_data = buf;
+			else
+				cmd.tx_data = buf;
 		}
  out:
 		if (berr != 0) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201903022058.x22Kwp5u017774>