Thread (23 messages) 23 messages, 3 authors, 2011-08-11

[PATCH v2 8/8] mmc: atmel-mci: fix a potential issue about pending PDC interrupts

From: ludovic.desroches at atmel.com <hidden>
Date: 2011-08-11 15:25:48
Also in: linux-mmc
Subsystem: microchip mmc/sd/sdio mci driver, multimedia card (mmc), secure digital (sd) and sdio subsystem, the rest · Maintainers: Aubin Constans, Ulf Hansson, Linus Torvalds

From: Ludovic Desroches <redacted>

This patch fixes a potential issue about PDC interrupts. For example we have
a ENDRX pending interrupt and a RXBUFF pending interrupt. We have received the
RXBUFF interrupt but the transfer is not finished (so we didn't have time to
give a new buffer to the PDC controller). Then we will compute ENDRX interrupt
and we will give a new buffer to the PDC controller, just after we will
compute the RXBUFF interrupt and give one or two new buffers to the PDC
controller but we are not sure that the first buffer given has been filled. So
in this situation we may "lost" one sg buffer. It's the same for transmission.

Signed-off-by: Ludovic Desroches <redacted>
---
 drivers/mmc/host/atmel-mci.c |   32 +++++++++++++++++---------------
 1 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 963e320..7108f64 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -1729,17 +1729,9 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
 			tasklet_schedule(&host->tasklet);
 		}
 
-		if (pending & ATMCI_ENDTX) {
-			atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
-			if (host->data_size) {
-				atmci_pdc_set_single_buf(host,
-						XFER_TRANSMIT, PDC_SECOND_BUF);
-				atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
-			}
-		}
-
 		if (pending & ATMCI_TXBUFE) {
 			atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE);
+			atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
 			/*
 			 * We can receive this interruption before having configured
 			 * the second pdc buffer, so we need to reconfigure first and
@@ -1747,24 +1739,24 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
 			 */
 			if (host->data_size) {
 				atmci_pdc_set_both_buf(host, XFER_TRANSMIT);
+				atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
 				atmci_writel(host, ATMCI_IER, ATMCI_TXBUFE);
 			} else {
 				atmci_pdc_complete(host);
 			}
-		}
-
-		if (pending & ATMCI_ENDRX) {
-			atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
+		} else if (pending & ATMCI_ENDTX) {
+			atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
 
 			if (host->data_size) {
 				atmci_pdc_set_single_buf(host,
-						XFER_RECEIVE, PDC_SECOND_BUF);
-				atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
+						XFER_TRANSMIT, PDC_SECOND_BUF);
+				atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
 			}
 		}
 
 		if (pending & ATMCI_RXBUFF) {
 			atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF);
+			atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
 			/*
 			 * We can receive this interruption before having configured
 			 * the second pdc buffer, so we need to reconfigure first and
@@ -1772,12 +1764,22 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
 			 */
 			if (host->data_size) {
 				atmci_pdc_set_both_buf(host, XFER_RECEIVE);
+				atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
 				atmci_writel(host, ATMCI_IER, ATMCI_RXBUFF);
 			} else {
 				atmci_pdc_complete(host);
 			}
+		} else if (pending & ATMCI_ENDRX) {
+			atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
+
+			if (host->data_size) {
+				atmci_pdc_set_single_buf(host,
+						XFER_RECEIVE, PDC_SECOND_BUF);
+				atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
+			}
 		}
 
+
 		if (pending & ATMCI_NOTBUSY) {
 			atmci_writel(host, ATMCI_IDR,
 					ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY);
-- 
1.7.0.4
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help