diff options
author | Nobuteru Hayashi <hayashi.nbb@ncos.nec.co.jp> | 2016-03-18 07:35:21 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-03-28 14:41:18 -0400 |
commit | 6319a68011b86fa61dc63e94dc4fb716628037f3 (patch) | |
tree | 2dbe35310b327e166e31cdc4f0e4752ce7889cbb | |
parent | aa70e567c4f0eeb849c6bcef3685bdf1fc3ca19d (diff) |
spi/fsl-espi: avoid infinite loops on fsl_espi_cpu_irq()
It brought nearly infinite loops, and was possible to be
occurred only if the SPI transaction total size are not
alighed with 4. Loops are here at while (tmp--),
tmp is unsigned, and set it with minus value.
The loops are executed as a result of unexpected RX interrupt
occurrence after that. This interrupt may be hardware eratta
and is not fixed.
Fix mspi->len from minus value to 0 and print warning message.
Signed-off-by: Nobuteru Hayashi <hayashi.nbb@ncos.nec.co.jp>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/spi/spi-fsl-espi.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 64d794b99803..8d85a3c343da 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c | |||
@@ -544,6 +544,7 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) | |||
544 | if (events & SPIE_NE) { | 544 | if (events & SPIE_NE) { |
545 | u32 rx_data, tmp; | 545 | u32 rx_data, tmp; |
546 | u8 rx_data_8; | 546 | u8 rx_data_8; |
547 | int rx_nr_bytes = 4; | ||
547 | int ret; | 548 | int ret; |
548 | 549 | ||
549 | /* Spin until RX is done */ | 550 | /* Spin until RX is done */ |
@@ -560,7 +561,14 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) | |||
560 | 561 | ||
561 | if (mspi->len >= 4) { | 562 | if (mspi->len >= 4) { |
562 | rx_data = mpc8xxx_spi_read_reg(®_base->receive); | 563 | rx_data = mpc8xxx_spi_read_reg(®_base->receive); |
564 | } else if (mspi->len <= 0) { | ||
565 | dev_err(mspi->dev, | ||
566 | "unexpected RX(SPIE_NE) interrupt occurred,\n" | ||
567 | "(local rxlen %d bytes, reg rxlen %d bytes)\n", | ||
568 | min(4, mspi->len), SPIE_RXCNT(events)); | ||
569 | rx_nr_bytes = 0; | ||
563 | } else { | 570 | } else { |
571 | rx_nr_bytes = mspi->len; | ||
564 | tmp = mspi->len; | 572 | tmp = mspi->len; |
565 | rx_data = 0; | 573 | rx_data = 0; |
566 | while (tmp--) { | 574 | while (tmp--) { |
@@ -571,7 +579,7 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) | |||
571 | rx_data <<= (4 - mspi->len) * 8; | 579 | rx_data <<= (4 - mspi->len) * 8; |
572 | } | 580 | } |
573 | 581 | ||
574 | mspi->len -= 4; | 582 | mspi->len -= rx_nr_bytes; |
575 | 583 | ||
576 | if (mspi->rx) | 584 | if (mspi->rx) |
577 | mspi->get_rx(rx_data, mspi); | 585 | mspi->get_rx(rx_data, mspi); |