[linux-yocto] [PATCH 16/28] i2c-axxia: Avoid timeout when interrupt delayed

Charlie Paul cpaul.windriver at gmail.com
Fri May 2 12:16:53 PDT 2014


From: Anders Berg <anders.berg at lsi.com>

Changed the order in which the interrupt conditions are checked in the
interrupt handler. Need to check for transfer-complete before timeout-error,
otherwise a delayed interrupt may report a false timeout error (since the
timeout may expire after the transfer was completed).

Signed-off-by: Anders Berg <anders.berg at lsi.com>
---
 drivers/i2c/busses/i2c-axxia.c |   50 ++++++++++++++++++----------------------
 1 file changed, 23 insertions(+), 27 deletions(-)

diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
index e58292b..43b433b 100644
--- a/drivers/i2c/busses/i2c-axxia.c
+++ b/drivers/i2c/busses/i2c-axxia.c
@@ -334,33 +334,6 @@ axxia_i2c_isr(int irq, void *_dev)
 	/* Clear interrupt */
 	writel(0x01, &idev->regs->interrupt_status);
 
-	if (unlikely(status & MST_STATUS_ERR)) {
-		idev->msg_err = status & MST_STATUS_ERR;
-		i2c_int_disable(idev, ~0);
-		dev_err(idev->dev, "error %s, rx=%u/%u tx=%u/%u\n",
-			status_str(idev->msg_err),
-			readl(&idev->regs->mst_rx_bytes_xfrd),
-			readl(&idev->regs->mst_rx_xfer),
-			readl(&idev->regs->mst_tx_bytes_xfrd),
-			readl(&idev->regs->mst_tx_xfer));
-		complete(&idev->msg_complete);
-		return IRQ_HANDLED;
-	}
-
-	/* Stop completed? */
-	if (status & MST_STATUS_SCC) {
-		i2c_int_disable(idev, ~0);
-		complete(&idev->msg_complete);
-	}
-
-	/* Transfer done? */
-	if (status & (MST_STATUS_SNS | MST_STATUS_SS)) {
-		if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
-			axxia_i2c_empty_rx_fifo(idev);
-		i2c_int_disable(idev, ~0);
-		complete(&idev->msg_complete);
-	}
-
 	/* RX FIFO needs service? */
 	if (i2c_m_rd(idev->msg) && (status & MST_STATUS_RFL))
 		axxia_i2c_empty_rx_fifo(idev);
@@ -373,6 +346,29 @@ axxia_i2c_isr(int irq, void *_dev)
 			i2c_int_disable(idev, MST_STATUS_TFL);
 	}
 
+	if (status & MST_STATUS_SCC) {
+		/* Stop completed? */
+		i2c_int_disable(idev, ~0);
+		complete(&idev->msg_complete);
+	} else if (status & (MST_STATUS_SNS | MST_STATUS_SS)) {
+		/* Transfer done? */
+		if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
+			axxia_i2c_empty_rx_fifo(idev);
+		i2c_int_disable(idev, ~0);
+		complete(&idev->msg_complete);
+	} else if (unlikely(status & MST_STATUS_ERR)) {
+		/* Transfer error? */
+		idev->msg_err = status & MST_STATUS_ERR;
+		i2c_int_disable(idev, ~0);
+		dev_err(idev->dev, "error %s, rx=%u/%u tx=%u/%u\n",
+			status_str(status),
+			readl(&idev->regs->mst_rx_bytes_xfrd),
+			readl(&idev->regs->mst_rx_xfer),
+			readl(&idev->regs->mst_tx_bytes_xfrd),
+			readl(&idev->regs->mst_tx_xfer));
+		complete(&idev->msg_complete);
+	}
+
 	return IRQ_HANDLED;
 }
 
-- 
1.7.9.5



More information about the linux-yocto mailing list