Skip to content

Commit

Permalink
spi: spidev: Align buffers for DMA
Browse files Browse the repository at this point in the history
Simply copying all xfers from userspace into one bounce buffer causes
alignment problems if the SPI controller uses DMA.

Ensure that all transfer data blocks within the rx and tx bounce buffers
are aligned for DMA (according to ARCH_KMALLOC_MINALIGN).

Alignment may increase the usage of the bounce buffers. In some cases,
the buffers may need to be increased using the "bufsiz" module
parameter.

Signed-off-by: Christian Eggers <ceggers@arri.de>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20200728100832.24788-1-ceggers@arri.de
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Christian Eggers authored and Mark Brown committed Jul 28, 2020
1 parent cfd97f9 commit aa9e862
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions drivers/spi/spidev.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ static int spidev_message(struct spidev_data *spidev,
for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
n;
n--, k_tmp++, u_tmp++) {
/* Ensure that also following allocations from rx_buf/tx_buf will meet
* DMA alignment requirements.
*/
unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_KMALLOC_MINALIGN);

k_tmp->len = u_tmp->len;

total += k_tmp->len;
Expand All @@ -239,17 +244,17 @@ static int spidev_message(struct spidev_data *spidev,

if (u_tmp->rx_buf) {
/* this transfer needs space in RX bounce buffer */
rx_total += k_tmp->len;
rx_total += len_aligned;
if (rx_total > bufsiz) {
status = -EMSGSIZE;
goto done;
}
k_tmp->rx_buf = rx_buf;
rx_buf += k_tmp->len;
rx_buf += len_aligned;
}
if (u_tmp->tx_buf) {
/* this transfer needs space in TX bounce buffer */
tx_total += k_tmp->len;
tx_total += len_aligned;
if (tx_total > bufsiz) {
status = -EMSGSIZE;
goto done;
Expand All @@ -259,7 +264,7 @@ static int spidev_message(struct spidev_data *spidev,
(uintptr_t) u_tmp->tx_buf,
u_tmp->len))
goto done;
tx_buf += k_tmp->len;
tx_buf += len_aligned;
}

k_tmp->cs_change = !!u_tmp->cs_change;
Expand Down Expand Up @@ -293,16 +298,16 @@ static int spidev_message(struct spidev_data *spidev,
goto done;

/* copy any rx data out of bounce buffer */
rx_buf = spidev->rx_buffer;
for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
n;
n--, k_tmp++, u_tmp++) {
if (u_tmp->rx_buf) {
if (copy_to_user((u8 __user *)
(uintptr_t) u_tmp->rx_buf, rx_buf,
(uintptr_t) u_tmp->rx_buf, k_tmp->rx_buf,
u_tmp->len)) {
status = -EFAULT;
goto done;
}
rx_buf += u_tmp->len;
}
}
status = total;
Expand Down

0 comments on commit aa9e862

Please sign in to comment.