lkml.org 
[lkml]   [2016]   [May]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 53/73] spi: spi-ti-qspi: Handle truncated frames properly
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Ben Hutchings <ben.hutchings@codethink.co.uk>

    commit 1ff7760ff66b98ef244bf0e5e2bd5310651205ad upstream.

    We clamp frame_len_words to a maximum of 4096, but do not actually
    limit the number of words written or read through the DATA registers
    or the length added to spi_message::actual_length. This results in
    silent data corruption for commands longer than this maximum.

    Recalculate the length of each transfer, taking frame_len_words into
    account. Use this length in qspi_{read,write}_msg(), and to increment
    spi_message::actual_length.

    Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
    Signed-off-by: Mark Brown <broonie@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/spi/spi-ti-qspi.c | 32 ++++++++++++++++++++------------
    1 file changed, 20 insertions(+), 12 deletions(-)

    --- a/drivers/spi/spi-ti-qspi.c
    +++ b/drivers/spi/spi-ti-qspi.c
    @@ -225,16 +225,16 @@ static inline int ti_qspi_poll_wc(struct
    return -ETIMEDOUT;
    }

    -static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
    +static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t,
    + int count)
    {
    - int wlen, count, xfer_len;
    + int wlen, xfer_len;
    unsigned int cmd;
    const u8 *txbuf;
    u32 data;

    txbuf = t->tx_buf;
    cmd = qspi->cmd | QSPI_WR_SNGL;
    - count = t->len;
    wlen = t->bits_per_word >> 3; /* in bytes */
    xfer_len = wlen;

    @@ -294,9 +294,10 @@ static int qspi_write_msg(struct ti_qspi
    return 0;
    }

    -static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
    +static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
    + int count)
    {
    - int wlen, count;
    + int wlen;
    unsigned int cmd;
    u8 *rxbuf;

    @@ -313,7 +314,6 @@ static int qspi_read_msg(struct ti_qspi
    cmd |= QSPI_RD_SNGL;
    break;
    }
    - count = t->len;
    wlen = t->bits_per_word >> 3; /* in bytes */

    while (count) {
    @@ -344,12 +344,13 @@ static int qspi_read_msg(struct ti_qspi
    return 0;
    }

    -static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
    +static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t,
    + int count)
    {
    int ret;

    if (t->tx_buf) {
    - ret = qspi_write_msg(qspi, t);
    + ret = qspi_write_msg(qspi, t, count);
    if (ret) {
    dev_dbg(qspi->dev, "Error while writing\n");
    return ret;
    @@ -357,7 +358,7 @@ static int qspi_transfer_msg(struct ti_q
    }

    if (t->rx_buf) {
    - ret = qspi_read_msg(qspi, t);
    + ret = qspi_read_msg(qspi, t, count);
    if (ret) {
    dev_dbg(qspi->dev, "Error while reading\n");
    return ret;
    @@ -374,7 +375,8 @@ static int ti_qspi_start_transfer_one(st
    struct spi_device *spi = m->spi;
    struct spi_transfer *t;
    int status = 0, ret;
    - unsigned int frame_len_words;
    + unsigned int frame_len_words, transfer_len_words;
    + int wlen;

    /* setup device control reg */
    qspi->dc = 0;
    @@ -404,14 +406,20 @@ static int ti_qspi_start_transfer_one(st
    qspi->cmd = ((qspi->cmd & ~QSPI_WLEN_MASK) |
    QSPI_WLEN(t->bits_per_word));

    - ret = qspi_transfer_msg(qspi, t);
    + wlen = t->bits_per_word >> 3;
    + transfer_len_words = min(t->len / wlen, frame_len_words);
    +
    + ret = qspi_transfer_msg(qspi, t, transfer_len_words * wlen);
    if (ret) {
    dev_dbg(qspi->dev, "transfer message failed\n");
    mutex_unlock(&qspi->list_lock);
    return -EINVAL;
    }

    - m->actual_length += t->len;
    + m->actual_length += transfer_len_words * wlen;
    + frame_len_words -= transfer_len_words;
    + if (frame_len_words == 0)
    + break;
    }

    mutex_unlock(&qspi->list_lock);

    \
     
     \ /
      Last update: 2016-05-17 03:41    [W:4.953 / U:0.240 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site