mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 19:26:25 +00:00
spi: spi_write_then_read() bugfixes
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@users.sourceforge.net> Cc: <stable@kernel.org> [2.6.28.x, 2.6.29.x] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
0769c29814
commit
bdff549ebe
1 changed files with 14 additions and 8 deletions
|
@ -658,7 +658,7 @@ int spi_write_then_read(struct spi_device *spi,
|
|||
|
||||
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_device *spi,
|
|||
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_device *spi,
|
|||
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);
|
||||
|
|
Loading…
Reference in a new issue