From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755582AbbBLMNi (ORCPT ); Thu, 12 Feb 2015 07:13:38 -0500 Received: from smtp113.iad3a.emailsrvr.com ([173.203.187.113]:50428 "EHLO smtp113.iad3a.emailsrvr.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755288AbbBLMNg (ORCPT ); Thu, 12 Feb 2015 07:13:36 -0500 X-Sender-Id: abbotti@mev.co.uk From: Ian Abbott To: linux-spi@vger.kernel.org Cc: Mark Brown , linux-kernel@vger.kernel.org, Ian Abbott Subject: [PATCH] spi: spidev: only use up TX/RX bounce buffer space when needed Date: Thu, 12 Feb 2015 12:13:08 +0000 Message-Id: <1423743188-1821-1-git-send-email-abbotti@mev.co.uk> X-Mailer: git-send-email 2.1.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Devices have separate, pre-allocated TX and RX bounce buffers of fixed size. Currently, each transfer uses up space in both buffers even if the user-supplied no TX data or no RX space. Change it to only use up space in the TX and RX bounce buffers as required. Since dummy transfers with no user-supplied TX data and no user-supplied RX space will no longer use up space in the bounce buffers, limit the overall SPI message length to INT_MAX instead of the buffer size. Signed-off-by: Ian Abbott --- drivers/spi/spidev.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index d1ccbfe..75de351 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -227,7 +227,7 @@ static int spidev_message(struct spidev_data *spidev, struct spi_transfer *k_xfers; struct spi_transfer *k_tmp; struct spi_ioc_transfer *u_tmp; - unsigned n, total; + unsigned n, total, tx_total, rx_total; u8 *tx_buf, *rx_buf; int status = -EFAULT; @@ -243,33 +243,45 @@ static int spidev_message(struct spidev_data *spidev, tx_buf = spidev->tx_buffer; rx_buf = spidev->rx_buffer; total = 0; + tx_total = 0; + rx_total = 0; for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; n; n--, k_tmp++, u_tmp++) { k_tmp->len = u_tmp->len; total += k_tmp->len; - if (total > bufsiz) { + if (total > INT_MAX) { status = -EMSGSIZE; goto done; } if (u_tmp->rx_buf) { + rx_total += k_tmp->len; + if (rx_total > bufsiz) { + status = -EMSGSIZE; + goto done; + } k_tmp->rx_buf = rx_buf; if (!access_ok(VERIFY_WRITE, (u8 __user *) (uintptr_t) u_tmp->rx_buf, u_tmp->len)) goto done; + rx_buf += k_tmp->len; } if (u_tmp->tx_buf) { + tx_total += k_tmp->len; + if (tx_total > bufsiz) { + status = -EMSGSIZE; + goto done; + } k_tmp->tx_buf = tx_buf; if (copy_from_user(tx_buf, (const u8 __user *) (uintptr_t) u_tmp->tx_buf, u_tmp->len)) goto done; + tx_buf += k_tmp->len; } - tx_buf += k_tmp->len; - rx_buf += k_tmp->len; k_tmp->cs_change = !!u_tmp->cs_change; k_tmp->tx_nbits = u_tmp->tx_nbits; @@ -307,8 +319,8 @@ static int spidev_message(struct spidev_data *spidev, status = -EFAULT; goto done; } + rx_buf += u_tmp->len; } - rx_buf += u_tmp->len; } status = total; -- 2.1.4