Skip to content

Commit aa9e862

Browse files
ceggers-arribroonie
authored andcommitted
spi: spidev: Align buffers for DMA
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 <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent cfd97f9 commit aa9e862

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

drivers/spi/spidev.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ static int spidev_message(struct spidev_data *spidev,
224224
for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
225225
n;
226226
n--, k_tmp++, u_tmp++) {
227+
/* Ensure that also following allocations from rx_buf/tx_buf will meet
228+
* DMA alignment requirements.
229+
*/
230+
unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_KMALLOC_MINALIGN);
231+
227232
k_tmp->len = u_tmp->len;
228233

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

240245
if (u_tmp->rx_buf) {
241246
/* this transfer needs space in RX bounce buffer */
242-
rx_total += k_tmp->len;
247+
rx_total += len_aligned;
243248
if (rx_total > bufsiz) {
244249
status = -EMSGSIZE;
245250
goto done;
246251
}
247252
k_tmp->rx_buf = rx_buf;
248-
rx_buf += k_tmp->len;
253+
rx_buf += len_aligned;
249254
}
250255
if (u_tmp->tx_buf) {
251256
/* this transfer needs space in TX bounce buffer */
252-
tx_total += k_tmp->len;
257+
tx_total += len_aligned;
253258
if (tx_total > bufsiz) {
254259
status = -EMSGSIZE;
255260
goto done;
@@ -259,7 +264,7 @@ static int spidev_message(struct spidev_data *spidev,
259264
(uintptr_t) u_tmp->tx_buf,
260265
u_tmp->len))
261266
goto done;
262-
tx_buf += k_tmp->len;
267+
tx_buf += len_aligned;
263268
}
264269

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

295300
/* copy any rx data out of bounce buffer */
296-
rx_buf = spidev->rx_buffer;
297-
for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
301+
for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
302+
n;
303+
n--, k_tmp++, u_tmp++) {
298304
if (u_tmp->rx_buf) {
299305
if (copy_to_user((u8 __user *)
300-
(uintptr_t) u_tmp->rx_buf, rx_buf,
306+
(uintptr_t) u_tmp->rx_buf, k_tmp->rx_buf,
301307
u_tmp->len)) {
302308
status = -EFAULT;
303309
goto done;
304310
}
305-
rx_buf += u_tmp->len;
306311
}
307312
}
308313
status = total;

0 commit comments

Comments
 (0)