From patchwork Thu Aug 11 15:25:48 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ludovic Desroches X-Patchwork-Id: 1057312 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p7BEFhju020671 for ; Thu, 11 Aug 2011 14:16:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751343Ab1HKOQJ (ORCPT ); Thu, 11 Aug 2011 10:16:09 -0400 Received: from newsmtp5.atmel.com ([204.2.163.5]:7322 "EHLO sjogate2.atmel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751472Ab1HKOQH (ORCPT ); Thu, 11 Aug 2011 10:16:07 -0400 Received: from meyreuil.atmel.fr ([10.159.254.132]) by sjogate2.atmel.com (8.13.6/8.13.6) with ESMTP id p7BEChCc011705; Thu, 11 Aug 2011 07:12:44 -0700 (PDT) Received: from bendor.rfo.atmel.com ([10.159.245.201]) by meyreuil.atmel.fr (8.11.7p1+Sun/8.11.7) with ESMTP id p7BEFwe25295; Thu, 11 Aug 2011 16:15:58 +0200 (MEST) From: ludovic.desroches@atmel.com To: linux-arm-kernel@lists.infradead.org, linux-mmc@vger.kernel.org Cc: nicolas.ferre@atmel.com, plagnioj@jcrosoft.com, Ludovic Desroches Subject: [PATCH v2 8/8] mmc: atmel-mci: fix a potential issue about pending PDC interrupts Date: Thu, 11 Aug 2011 17:25:48 +0200 Message-Id: X-Mailer: git-send-email 1.7.5 In-Reply-To: <1313076348-3065-1-git-send-email-ludovic.desroches@atmel.com> References: <1311863398-31579-1-git-send-email-ludovic.desroches@atmel.com> <1313076348-3065-1-git-send-email-ludovic.desroches@atmel.com> In-Reply-To: <3408076e8bc2e7b3ad3bb4d3ae3859ab665a59aa.1313071125.git.ludovic.desroches@atmel.com> References: <3408076e8bc2e7b3ad3bb4d3ae3859ab665a59aa.1313071125.git.ludovic.desroches@atmel.com> Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Thu, 11 Aug 2011 14:16:10 +0000 (UTC) From: Ludovic Desroches 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 --- 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);