diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2016-06-03 15:05:51 +0200 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-06-03 15:05:51 +0200 |
commit | 2eec3707a33fbf1c2e0a88ffc9fc0e465c2a59fd (patch) | |
tree | 9e47763ecd38f0ddd29f07e1ce199680304449fa /drivers/spi/spi-fsl-espi.c | |
parent | 59fa5860204ffc95128d60cba9f54f9740a42c7d (diff) | |
parent | 0de6b9979e2e10c79e5702d2d902cd7284d17689 (diff) | |
download | talos-op-linux-2eec3707a33fbf1c2e0a88ffc9fc0e465c2a59fd.tar.gz talos-op-linux-2eec3707a33fbf1c2e0a88ffc9fc0e465c2a59fd.zip |
Merge tag 'irqchip-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/urgent
Merge irqchip updates from Marc Zyngier:
- A number of embarassing buglets (GICv3, PIC32)
- A more substential errata workaround for Cavium's GICv3 ITS
(kept for post-rc1 due to its dependency on NUMA)
Diffstat (limited to 'drivers/spi/spi-fsl-espi.c')
-rw-r--r-- | drivers/spi/spi-fsl-espi.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 7cb0c1921495..8d85a3c343da 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -245,7 +245,12 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) if (ret) return ret; - wait_for_completion(&mpc8xxx_spi->done); + /* Won't hang up forever, SPI bus sometimes got lost interrupts... */ + ret = wait_for_completion_timeout(&mpc8xxx_spi->done, 2 * HZ); + if (ret == 0) + dev_err(mpc8xxx_spi->dev, + "Transaction hanging up (left %d bytes)\n", + mpc8xxx_spi->count); /* disable rx ints */ mpc8xxx_spi_write_reg(®_base->mask, 0); @@ -539,16 +544,31 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) if (events & SPIE_NE) { u32 rx_data, tmp; u8 rx_data_8; + int rx_nr_bytes = 4; + int ret; /* Spin until RX is done */ - while (SPIE_RXCNT(events) < min(4, mspi->len)) { - cpu_relax(); - events = mpc8xxx_spi_read_reg(®_base->event); + if (SPIE_RXCNT(events) < min(4, mspi->len)) { + ret = spin_event_timeout( + !(SPIE_RXCNT(events = + mpc8xxx_spi_read_reg(®_base->event)) < + min(4, mspi->len)), + 10000, 0); /* 10 msec */ + if (!ret) + dev_err(mspi->dev, + "tired waiting for SPIE_RXCNT\n"); } if (mspi->len >= 4) { rx_data = mpc8xxx_spi_read_reg(®_base->receive); + } else if (mspi->len <= 0) { + dev_err(mspi->dev, + "unexpected RX(SPIE_NE) interrupt occurred,\n" + "(local rxlen %d bytes, reg rxlen %d bytes)\n", + min(4, mspi->len), SPIE_RXCNT(events)); + rx_nr_bytes = 0; } else { + rx_nr_bytes = mspi->len; tmp = mspi->len; rx_data = 0; while (tmp--) { @@ -559,7 +579,7 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) rx_data <<= (4 - mspi->len) * 8; } - mspi->len -= 4; + mspi->len -= rx_nr_bytes; if (mspi->rx) mspi->get_rx(rx_data, mspi); |