From patchwork Thu Feb 12 12:13:08 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Abbott X-Patchwork-Id: 5818931 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id DD9DC9F37F for ; Thu, 12 Feb 2015 12:13:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 21A2E2021B for ; Thu, 12 Feb 2015 12:13:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BA9EF20225 for ; Thu, 12 Feb 2015 12:13:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755428AbbBLMNh (ORCPT ); Thu, 12 Feb 2015 07:13:37 -0500 Received: from smtp117.iad3a.emailsrvr.com ([173.203.187.117]:35537 "EHLO smtp117.iad3a.emailsrvr.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755381AbbBLMNg (ORCPT ); Thu, 12 Feb 2015 07:13:36 -0500 Received: from smtp7.relay.iad3a.emailsrvr.com (localhost.localdomain [127.0.0.1]) by smtp7.relay.iad3a.emailsrvr.com (SMTP Server) with ESMTP id 7DEBE18036C; Thu, 12 Feb 2015 07:13:35 -0500 (EST) Received: by smtp7.relay.iad3a.emailsrvr.com (Authenticated sender: abbotti-AT-mev.co.uk) with ESMTPSA id C1DE6180360; Thu, 12 Feb 2015 07:13:34 -0500 (EST) X-Sender-Id: abbotti@mev.co.uk Received: from localhost.localdomain (host86-149-99-235.range86-149.btcentralplus.com [86.149.99.235]) (using TLSv1.2 with cipher AES128-SHA256) by 0.0.0.0:465 (trex/5.4.2); Thu, 12 Feb 2015 12:13:35 GMT 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-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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;