[<prev] [next>] [day] [month] [year] [list]
Message-Id: <200904050107.23410.david-b@pacbell.net>
Date: Sun, 5 Apr 2009 01:07:23 -0700
From: David Brownell <david-b@...bell.net>
To: Andrew Morton <akpm@...ux-foundation.org>
Cc: spi-devel-general@...ts.sourceforge.net,
lkml <linux-kernel@...r.kernel.org>,
Maxime Bizon <mbizon@...ebox.fr>
Subject: [patch 2.6.29-git] spi: spi_write_then_read() bugfixes
From: David Brownell <dbrownell@...rs.sourceforge.net>
The "simplify spi_write_then_read()" patch included two
regressions from the 2.6.27 behaviors:
- The data it wrote out during the (full duplex) read side
of the transfer was not zeroed.
- It fails completely on half duplex hardware, such as
Microwire and most "3-wire" SPI variants.
So, revert that patch. A revised version should be submitted
at some point, which can get the speedup on standard hardware
(full duplex) without breaking on less-capable half-duplex stuff.
Signed-off-by: David Brownell <dbrownell@...rs.sourceforge.net>
---
Fix should go into '28 and '29 stable kernels.
drivers/spi/spi.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -658,7 +658,7 @@ int spi_write_then_read(struct spi_devic
int status;
struct spi_message message;
- struct spi_transfer x;
+ struct spi_transfer x[2];
u8 *local_buf;
/* Use preallocated DMA-safe buffer. We can't avoid copying here,
@@ -669,9 +669,15 @@ int spi_write_then_read(struct spi_devic
return -EINVAL;
spi_message_init(&message);
- memset(&x, 0, sizeof x);
- x.len = n_tx + n_rx;
- spi_message_add_tail(&x, &message);
+ memset(x, 0, sizeof x);
+ if (n_tx) {
+ x[0].len = n_tx;
+ spi_message_add_tail(&x[0], &message);
+ }
+ if (n_rx) {
+ x[1].len = n_rx;
+ spi_message_add_tail(&x[1], &message);
+ }
/* ... unless someone else is using the pre-allocated buffer */
if (!mutex_trylock(&lock)) {
@@ -682,15 +688,15 @@ int spi_write_then_read(struct spi_devic
local_buf = buf;
memcpy(local_buf, txbuf, n_tx);
- x.tx_buf = local_buf;
- x.rx_buf = local_buf;
+ x[0].tx_buf = local_buf;
+ x[1].rx_buf = local_buf + n_tx;
/* do the i/o */
status = spi_sync(spi, &message);
if (status == 0)
- memcpy(rxbuf, x.rx_buf + n_tx, n_rx);
+ memcpy(rxbuf, x[1].rx_buf, n_rx);
- if (x.tx_buf == buf)
+ if (x[0].tx_buf == buf)
mutex_unlock(&lock);
else
kfree(local_buf);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists