Skip to content

Commit 1ff7760

Browse files
bwh-ctbroonie
authored andcommitted
spi: spi-ti-qspi: Handle truncated frames properly
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> Cc: stable@vger.kernel.org
1 parent ea1b60f commit 1ff7760

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

drivers/spi/spi-ti-qspi.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -236,16 +236,16 @@ static inline int ti_qspi_poll_wc(struct ti_qspi *qspi)
236236
return -ETIMEDOUT;
237237
}
238238

239-
static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
239+
static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t,
240+
int count)
240241
{
241-
int wlen, count, xfer_len;
242+
int wlen, xfer_len;
242243
unsigned int cmd;
243244
const u8 *txbuf;
244245
u32 data;
245246

246247
txbuf = t->tx_buf;
247248
cmd = qspi->cmd | QSPI_WR_SNGL;
248-
count = t->len;
249249
wlen = t->bits_per_word >> 3; /* in bytes */
250250
xfer_len = wlen;
251251

@@ -305,9 +305,10 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
305305
return 0;
306306
}
307307

308-
static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
308+
static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
309+
int count)
309310
{
310-
int wlen, count;
311+
int wlen;
311312
unsigned int cmd;
312313
u8 *rxbuf;
313314

@@ -324,7 +325,6 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
324325
cmd |= QSPI_RD_SNGL;
325326
break;
326327
}
327-
count = t->len;
328328
wlen = t->bits_per_word >> 3; /* in bytes */
329329

330330
while (count) {
@@ -355,20 +355,21 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
355355
return 0;
356356
}
357357

358-
static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
358+
static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t,
359+
int count)
359360
{
360361
int ret;
361362

362363
if (t->tx_buf) {
363-
ret = qspi_write_msg(qspi, t);
364+
ret = qspi_write_msg(qspi, t, count);
364365
if (ret) {
365366
dev_dbg(qspi->dev, "Error while writing\n");
366367
return ret;
367368
}
368369
}
369370

370371
if (t->rx_buf) {
371-
ret = qspi_read_msg(qspi, t);
372+
ret = qspi_read_msg(qspi, t, count);
372373
if (ret) {
373374
dev_dbg(qspi->dev, "Error while reading\n");
374375
return ret;
@@ -451,7 +452,8 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
451452
struct spi_device *spi = m->spi;
452453
struct spi_transfer *t;
453454
int status = 0, ret;
454-
unsigned int frame_len_words;
455+
unsigned int frame_len_words, transfer_len_words;
456+
int wlen;
455457

456458
/* setup device control reg */
457459
qspi->dc = 0;
@@ -484,14 +486,20 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
484486
qspi->cmd = ((qspi->cmd & ~QSPI_WLEN_MASK) |
485487
QSPI_WLEN(t->bits_per_word));
486488

487-
ret = qspi_transfer_msg(qspi, t);
489+
wlen = t->bits_per_word >> 3;
490+
transfer_len_words = min(t->len / wlen, frame_len_words);
491+
492+
ret = qspi_transfer_msg(qspi, t, transfer_len_words * wlen);
488493
if (ret) {
489494
dev_dbg(qspi->dev, "transfer message failed\n");
490495
mutex_unlock(&qspi->list_lock);
491496
return -EINVAL;
492497
}
493498

494-
m->actual_length += t->len;
499+
m->actual_length += transfer_len_words * wlen;
500+
frame_len_words -= transfer_len_words;
501+
if (frame_len_words == 0)
502+
break;
495503
}
496504

497505
mutex_unlock(&qspi->list_lock);

0 commit comments

Comments
 (0)