Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752207AbcKHNqt (ORCPT ); Tue, 8 Nov 2016 08:46:49 -0500 Received: from mout.kundenserver.de ([212.227.126.187]:61576 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750953AbcKHNqq (ORCPT ); Tue, 8 Nov 2016 08:46:46 -0500 From: Arnd Bergmann To: Mark Brown Cc: Arnd Bergmann , Chris Brandt , Hiep Cao Minh , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] spi: rspi: avoid uninitialized variable access Date: Tue, 8 Nov 2016 14:46:12 +0100 Message-Id: <20161108134624.1905209-1-arnd@arndb.de> X-Mailer: git-send-email 2.9.0 X-Provags-ID: V03:K0:pAwnbbpYQAkzgNMQW5pFrHqqyHbj/RZ2WL0v+u9X13hNneH585W EyYOFzmaBrZeCWIKT/TxVc6aNfpTqVeVs6Z/L3N0CaN06XgNzBlk0cKVABcfmf23Wy8U/+0 LmINBN52XiftX2ffAz/P7yAF76S61J/OqE+kNZg9b/Yo83ppK8uWFUek3+toQc7W4RTOSLP LKyfRJjaKuJ6dKvyED3PQ== X-UI-Out-Filterresults: notjunk:1;V01:K0:nDxV57PgLXw=:xlkRb6Sj2tba8nmvA8JWM1 bLsSwh59lLk4IPrqX0vo9h/5nYIAIBWepQUR1UrFOxLoGRxZ7xnX1qJQim+lLkMHgoZa2YRjm 1eJwa2hw3BC+sTZZcHFZIjzgADoBy4XZXk6MkBcC3oPqumwTgOTQ9PujiFlhNtuFfNs8qqT+E Wbrnj1fO15nCw3DhhE7otsR2RaFaASAmTzrFkMGYb7vcZQwOdC0f6cAKn0Tg+qwcocaY1qTFy O91ladcwafR2kLmfhj9op1qTn8Aco4m3o5tQwIHRMM9JxD3X8ye9E6bZ3TpFOtz51hcde68/t 2rcTDEi5NVd4HheeeVXF5++42F+ppRTwYQk4UtFVFioAL4WG7/To7XrOguMRxliCHpeg/FWQl zZaRWWyZKxYWQwhAdvKO6hk2JijPyNdcICtwezWwE4wZKeCjf1i3MCTPGntHR71oq7L3wDDOi m/vyu2TaNyYOeKSfn0Bg+UbYCz5UrPs5jB5LL2ikSKMBPkD3XgRqXLwT2ozU6xR8clKepVmU8 hec97wZYazQSw2ZTiefkEyiJ6c9LcTZvR8ocO9TSf3kqRMCCupaZ5URUC4VyZNNH8At5MWs8k eXuE7fNcVB6hOoMvND4gVOVDauJ1rGW7tJdqa8q2jusrflU+WFa/zwlsHNHE/fAqXWFoPi2ue FN3Q+eogD/U7ZN9neEg8I4a8GiRe35/I5lBEdPLTrcFy7070Fcdz8N6pVI0RjrOjzfqM= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4511 Lines: 156 The newly introduced rspi_pio_transfer_in_or_our() function must take either a valid 'rx' or 'tx' pointer, and has undefined behavior if both are NULL, as found by 'gcc -Wmaybe-unintialized': drivers/spi/spi-rspi.c: In function 'rspi_pio_transfer_in_or_our': drivers/spi/spi-rspi.c:558:5: error: 'len' may be used uninitialized in this function [-Werror=maybe-uninitialized] The analysis of the function is correct in principle, but the code is currently safe because both callers always pass exactly one of the two pointers. Looking closer at this function shows that having a combined method for rx and tx here actually increases the complexity and the size of the file. This simplifies it again by keeping the two separate, which then ends up avoiding that warning. Fixes: 3be09bec42a8 ("spi: rspi: supports 32bytes buffer for DUAL and QUAD") Signed-off-by: Arnd Bergmann --- drivers/spi/spi-rspi.c | 94 ++++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 3bab75ab1b25..9daf50031737 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -515,51 +515,6 @@ static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx, return 0; } -static int rspi_pio_transfer_in_or_our(struct rspi_data *rspi, const u8 *tx, - u8 *rx, unsigned int n) -{ - unsigned int i, len; - int ret; - - while (n > 0) { - if (tx) { - len = qspi_set_send_trigger(rspi, n); - if (len == QSPI_BUFFER_SIZE) { - ret = rspi_wait_for_tx_empty(rspi); - if (ret < 0) { - dev_err(&rspi->master->dev, "transmit timeout\n"); - return ret; - } - for (i = 0; i < len; i++) - rspi_write_data(rspi, *tx++); - } else { - ret = rspi_pio_transfer(rspi, tx, NULL, n); - if (ret < 0) - return ret; - } - } - if (rx) { - len = qspi_set_receive_trigger(rspi, n); - if (len == QSPI_BUFFER_SIZE) { - ret = rspi_wait_for_rx_full(rspi); - if (ret < 0) { - dev_err(&rspi->master->dev, "receive timeout\n"); - return ret; - } - for (i = 0; i < len; i++) - *rx++ = rspi_read_data(rspi); - } else { - ret = rspi_pio_transfer(rspi, NULL, rx, n); - if (ret < 0) - return ret; - *rx++ = ret; - } - } - n -= len; - } - return 0; -} - static void rspi_dma_complete(void *arg) { struct rspi_data *rspi = arg; @@ -831,6 +786,9 @@ static int qspi_transfer_out_in(struct rspi_data *rspi, static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) { + const u8 *tx = xfer->tx_buf; + unsigned int n = xfer->len; + unsigned int i, len; int ret; if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { @@ -839,9 +797,23 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) return ret; } - ret = rspi_pio_transfer_in_or_our(rspi, xfer->tx_buf, NULL, xfer->len); - if (ret < 0) - return ret; + while (n > 0) { + len = qspi_set_send_trigger(rspi, n); + if (len == QSPI_BUFFER_SIZE) { + ret = rspi_wait_for_tx_empty(rspi); + if (ret < 0) { + dev_err(&rspi->master->dev, "transmit timeout\n"); + return ret; + } + for (i = 0; i < len; i++) + rspi_write_data(rspi, *tx++); + } else { + ret = rspi_pio_transfer(rspi, tx, NULL, n); + if (ret < 0) + return ret; + } + n -= len; + } /* Wait for the last transmission */ rspi_wait_for_tx_empty(rspi); @@ -851,13 +823,37 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer) { + u8 *rx = xfer->rx_buf; + unsigned int n = xfer->len; + unsigned int i, len; + int ret; + if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg); if (ret != -EAGAIN) return ret; } - return rspi_pio_transfer_in_or_our(rspi, NULL, xfer->rx_buf, xfer->len); + while (n > 0) { + len = qspi_set_receive_trigger(rspi, n); + if (len == QSPI_BUFFER_SIZE) { + ret = rspi_wait_for_rx_full(rspi); + if (ret < 0) { + dev_err(&rspi->master->dev, "receive timeout\n"); + return ret; + } + for (i = 0; i < len; i++) + *rx++ = rspi_read_data(rspi); + } else { + ret = rspi_pio_transfer(rspi, NULL, rx, n); + if (ret < 0) + return ret; + *rx++ = ret; + } + n -= len; + } + + return 0; } static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, -- 2.9.0