]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
spi: fsl-espi: extend and improve transfer error handling
authorHeiner Kallweit <hkallweit1@gmail.com>
Thu, 27 Oct 2016 19:28:02 +0000 (21:28 +0200)
committerMark Brown <broonie@kernel.org>
Fri, 28 Oct 2016 18:39:46 +0000 (19:39 +0100)
Extend and improve transfer error handling
- in case of timeout report also number of remaining rx bytes
- in case of timeout return ETIMEDOUT instead of EMSGSIZE
- add sanity checks after all bytes have been sent / read:
 - check that HW has flag SPIE_DON set
 - check that RX / TX FIFO are empty

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-fsl-espi.c

index d5506852e63cf85324d22a0383231da77d145306..a9593f9691ecf2980717e0dd48fa3c28196a1774 100644 (file)
@@ -289,13 +289,13 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
        ret = wait_for_completion_timeout(&mpc8xxx_spi->done, 2 * HZ);
        if (ret == 0)
                dev_err(mpc8xxx_spi->dev,
-                       "Transaction hanging up (left %u bytes)\n",
-                       mpc8xxx_spi->tx_len);
+                       "Transaction hanging up (left %u tx bytes, %u rx bytes)\n",
+                       mpc8xxx_spi->tx_len, mpc8xxx_spi->rx_len);
 
        /* disable rx ints */
        fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, 0);
 
-       return mpc8xxx_spi->tx_len > 0 ? -EMSGSIZE : 0;
+       return ret == 0 ? -ETIMEDOUT : 0;
 }
 
 static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
@@ -469,8 +469,20 @@ static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
        if (mspi->tx_len)
                fsl_espi_fill_tx_fifo(mspi, events);
 
-       if (!mspi->tx_len && !mspi->rx_len)
-               complete(&mspi->done);
+       if (mspi->tx_len || mspi->rx_len)
+               return;
+
+       /* we're done, but check for errors before returning */
+       events = fsl_espi_read_reg(mspi, ESPI_SPIE);
+
+       if (!(events & SPIE_DON))
+               dev_err(mspi->dev,
+                       "Transfer done but SPIE_DON isn't set!\n");
+
+       if (SPIE_RXCNT(events) || SPIE_TXCNT(events) != FSL_ESPI_FIFO_SIZE)
+               dev_err(mspi->dev, "Transfer done but rx/tx fifo's aren't empty!\n");
+
+       complete(&mspi->done);
 }
 
 static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)