diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-12-01 22:54:25 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2012-12-06 09:03:14 -0500 |
commit | b3a223ee2d1a4635b0643c547bc0096a37334ed1 (patch) | |
tree | 0b0e7891825af66e8ecfdc6e3f14bbf2b1941991 /drivers/spi/spi.c | |
parent | 266904c77911fdc0a064d97e2f06034b824c23ac (diff) |
spi: Remove SPI_BUFSIZ restriction on spi_write_then_read()
In order to avoid constantly allocating and deallocating there is a fixed
buffer which spi_write_then_read() uses for transfers, with an early error
check to ensure that the transfer fits within the buffer. This limits the
size of transfers to this size, currently max(32, SMP_CACHE_BYTES).
Since we can dynamically allocate and in fact already have a fallback
to do so when there is contention for the fixed buffer remove this
restriction and instead dynamically allocate a suitably sized buffer if
the transfer won't fit.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index f1217ae59f3d..22c71e238fdf 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -1545,12 +1545,18 @@ int spi_write_then_read(struct spi_device *spi, | |||
1545 | struct spi_transfer x[2]; | 1545 | struct spi_transfer x[2]; |
1546 | u8 *local_buf; | 1546 | u8 *local_buf; |
1547 | 1547 | ||
1548 | /* Use preallocated DMA-safe buffer. We can't avoid copying here, | 1548 | /* Use preallocated DMA-safe buffer if we can. We can't avoid |
1549 | * (as a pure convenience thing), but we can keep heap costs | 1549 | * copying here, (as a pure convenience thing), but we can |
1550 | * out of the hot path ... | 1550 | * keep heap costs out of the hot path unless someone else is |
1551 | * using the pre-allocated buffer or the transfer is too large. | ||
1551 | */ | 1552 | */ |
1552 | if ((n_tx + n_rx) > SPI_BUFSIZ) | 1553 | if ((n_tx + n_rx) > SPI_BUFSIZ || !mutex_trylock(&lock)) { |
1553 | return -EINVAL; | 1554 | local_buf = kmalloc(max(SPI_BUFSIZ, n_tx + n_rx), GFP_KERNEL); |
1555 | if (!local_buf) | ||
1556 | return -ENOMEM; | ||
1557 | } else { | ||
1558 | local_buf = buf; | ||
1559 | } | ||
1554 | 1560 | ||
1555 | spi_message_init(&message); | 1561 | spi_message_init(&message); |
1556 | memset(x, 0, sizeof x); | 1562 | memset(x, 0, sizeof x); |
@@ -1563,14 +1569,6 @@ int spi_write_then_read(struct spi_device *spi, | |||
1563 | spi_message_add_tail(&x[1], &message); | 1569 | spi_message_add_tail(&x[1], &message); |
1564 | } | 1570 | } |
1565 | 1571 | ||
1566 | /* ... unless someone else is using the pre-allocated buffer */ | ||
1567 | if (!mutex_trylock(&lock)) { | ||
1568 | local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); | ||
1569 | if (!local_buf) | ||
1570 | return -ENOMEM; | ||
1571 | } else | ||
1572 | local_buf = buf; | ||
1573 | |||
1574 | memcpy(local_buf, txbuf, n_tx); | 1572 | memcpy(local_buf, txbuf, n_tx); |
1575 | x[0].tx_buf = local_buf; | 1573 | x[0].tx_buf = local_buf; |
1576 | x[1].rx_buf = local_buf + n_tx; | 1574 | x[1].rx_buf = local_buf + n_tx; |