aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <ben.hutchings@codethink.co.uk>2016-04-12 07:58:14 -0400
committerMark Brown <broonie@kernel.org>2016-04-13 03:12:41 -0400
commit1ff7760ff66b98ef244bf0e5e2bd5310651205ad (patch)
treefd7a3c5af84df055ec34c5de017819d20f6b0b38
parentea1b60fb085839a9544cb3a0069992991beabb7f (diff)
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
-rw-r--r--drivers/spi/spi-ti-qspi.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index 0ee4139dec48..443f664534e1 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -236,16 +236,16 @@ static inline int ti_qspi_poll_wc(struct ti_qspi *qspi)
236 return -ETIMEDOUT; 236 return -ETIMEDOUT;
237} 237}
238 238
239static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t) 239static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t,
240 int count)
240{ 241{
241 int wlen, count, xfer_len; 242 int wlen, xfer_len;
242 unsigned int cmd; 243 unsigned int cmd;
243 const u8 *txbuf; 244 const u8 *txbuf;
244 u32 data; 245 u32 data;
245 246
246 txbuf = t->tx_buf; 247 txbuf = t->tx_buf;
247 cmd = qspi->cmd | QSPI_WR_SNGL; 248 cmd = qspi->cmd | QSPI_WR_SNGL;
248 count = t->len;
249 wlen = t->bits_per_word >> 3; /* in bytes */ 249 wlen = t->bits_per_word >> 3; /* in bytes */
250 xfer_len = wlen; 250 xfer_len = wlen;
251 251
@@ -305,9 +305,10 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
305 return 0; 305 return 0;
306} 306}
307 307
308static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t) 308static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
309 int count)
309{ 310{
310 int wlen, count; 311 int wlen;
311 unsigned int cmd; 312 unsigned int cmd;
312 u8 *rxbuf; 313 u8 *rxbuf;
313 314
@@ -324,7 +325,6 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
324 cmd |= QSPI_RD_SNGL; 325 cmd |= QSPI_RD_SNGL;
325 break; 326 break;
326 } 327 }
327 count = t->len;
328 wlen = t->bits_per_word >> 3; /* in bytes */ 328 wlen = t->bits_per_word >> 3; /* in bytes */
329 329
330 while (count) { 330 while (count) {
@@ -355,12 +355,13 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t)
355 return 0; 355 return 0;
356} 356}
357 357
358static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t) 358static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t,
359 int count)
359{ 360{
360 int ret; 361 int ret;
361 362
362 if (t->tx_buf) { 363 if (t->tx_buf) {
363 ret = qspi_write_msg(qspi, t); 364 ret = qspi_write_msg(qspi, t, count);
364 if (ret) { 365 if (ret) {
365 dev_dbg(qspi->dev, "Error while writing\n"); 366 dev_dbg(qspi->dev, "Error while writing\n");
366 return ret; 367 return ret;
@@ -368,7 +369,7 @@ static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
368 } 369 }
369 370
370 if (t->rx_buf) { 371 if (t->rx_buf) {
371 ret = qspi_read_msg(qspi, t); 372 ret = qspi_read_msg(qspi, t, count);
372 if (ret) { 373 if (ret) {
373 dev_dbg(qspi->dev, "Error while reading\n"); 374 dev_dbg(qspi->dev, "Error while reading\n");
374 return ret; 375 return ret;
@@ -451,7 +452,8 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
451 struct spi_device *spi = m->spi; 452 struct spi_device *spi = m->spi;
452 struct spi_transfer *t; 453 struct spi_transfer *t;
453 int status = 0, ret; 454 int status = 0, ret;
454 unsigned int frame_len_words; 455 unsigned int frame_len_words, transfer_len_words;
456 int wlen;
455 457
456 /* setup device control reg */ 458 /* setup device control reg */
457 qspi->dc = 0; 459 qspi->dc = 0;
@@ -484,14 +486,20 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
484 qspi->cmd = ((qspi->cmd & ~QSPI_WLEN_MASK) | 486 qspi->cmd = ((qspi->cmd & ~QSPI_WLEN_MASK) |
485 QSPI_WLEN(t->bits_per_word)); 487 QSPI_WLEN(t->bits_per_word));
486 488
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);
488 if (ret) { 493 if (ret) {
489 dev_dbg(qspi->dev, "transfer message failed\n"); 494 dev_dbg(qspi->dev, "transfer message failed\n");
490 mutex_unlock(&qspi->list_lock); 495 mutex_unlock(&qspi->list_lock);
491 return -EINVAL; 496 return -EINVAL;
492 } 497 }
493 498
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;
495 } 503 }
496 504
497 mutex_unlock(&qspi->list_lock); 505 mutex_unlock(&qspi->list_lock);