Commit 7e8ba228 authored by Ludovic Desroches's avatar Ludovic Desroches Committed by Chris Ball

mmc: atmel-mci: fix a potential issue about pending PDC interrupts

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
have "lost" one sg buffer. It's the same for transmission.
Signed-off-by: default avatarLudovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: default avatarNicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 341fa4c3
...@@ -1729,17 +1729,9 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) ...@@ -1729,17 +1729,9 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
tasklet_schedule(&host->tasklet); 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) { if (pending & ATMCI_TXBUFE) {
atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE); atmci_writel(host, ATMCI_IDR, ATMCI_TXBUFE);
atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
/* /*
* We can receive this interruption before having configured * We can receive this interruption before having configured
* the second pdc buffer, so we need to reconfigure first and * 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) ...@@ -1747,24 +1739,24 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
*/ */
if (host->data_size) { if (host->data_size) {
atmci_pdc_set_both_buf(host, XFER_TRANSMIT); atmci_pdc_set_both_buf(host, XFER_TRANSMIT);
atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
atmci_writel(host, ATMCI_IER, ATMCI_TXBUFE); atmci_writel(host, ATMCI_IER, ATMCI_TXBUFE);
} else { } else {
atmci_pdc_complete(host); atmci_pdc_complete(host);
} }
} } else if (pending & ATMCI_ENDTX) {
atmci_writel(host, ATMCI_IDR, ATMCI_ENDTX);
if (pending & ATMCI_ENDRX) {
atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
if (host->data_size) { if (host->data_size) {
atmci_pdc_set_single_buf(host, atmci_pdc_set_single_buf(host,
XFER_RECEIVE, PDC_SECOND_BUF); XFER_TRANSMIT, PDC_SECOND_BUF);
atmci_writel(host, ATMCI_IER, ATMCI_ENDRX); atmci_writel(host, ATMCI_IER, ATMCI_ENDTX);
} }
} }
if (pending & ATMCI_RXBUFF) { if (pending & ATMCI_RXBUFF) {
atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF); atmci_writel(host, ATMCI_IDR, ATMCI_RXBUFF);
atmci_writel(host, ATMCI_IDR, ATMCI_ENDRX);
/* /*
* We can receive this interruption before having configured * We can receive this interruption before having configured
* the second pdc buffer, so we need to reconfigure first and * 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) ...@@ -1772,12 +1764,22 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
*/ */
if (host->data_size) { if (host->data_size) {
atmci_pdc_set_both_buf(host, XFER_RECEIVE); atmci_pdc_set_both_buf(host, XFER_RECEIVE);
atmci_writel(host, ATMCI_IER, ATMCI_ENDRX);
atmci_writel(host, ATMCI_IER, ATMCI_RXBUFF); atmci_writel(host, ATMCI_IER, ATMCI_RXBUFF);
} else { } else {
atmci_pdc_complete(host); 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) { if (pending & ATMCI_NOTBUSY) {
atmci_writel(host, ATMCI_IDR, atmci_writel(host, ATMCI_IDR,
ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY); ATMCI_DATA_ERROR_FLAGS | ATMCI_NOTBUSY);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment