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 --- drivers/spi/spidev.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 59e07675ef86..455e99c4958e 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -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; @@ -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; @@ -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; @@ -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;
On Tue, 28 Jul 2020 12:08:32 +0200, Christian Eggers wrote:
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.
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
Thanks!
[1/1] spi: spidev: Align buffers for DMA commit: aa9e862d7d5bcecd4dca9f39e8b684b93dd84ee7
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
linux-stable-mirror@lists.linaro.org