From patchwork Thu Sep 18 16:12:25 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 4932641 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 6120A9F32F for ; Thu, 18 Sep 2014 16:14:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CBA0E20108 for ; Thu, 18 Sep 2014 16:14:49 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 46A07201F5 for ; Thu, 18 Sep 2014 16:14:44 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XUeKA-0006xI-GO; Thu, 18 Sep 2014 16:12:50 +0000 Received: from galois.linutronix.de ([2001:470:1f0b:db:abcd:42:0:1]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XUeK7-0006q0-Mt for linux-arm-kernel@lists.infradead.org; Thu, 18 Sep 2014 16:12:48 +0000 Received: from bigeasy by Galois.linutronix.de with local (Exim 4.80) (envelope-from ) id 1XUeJl-0002vj-VY; Thu, 18 Sep 2014 18:12:25 +0200 Date: Thu, 18 Sep 2014 18:12:25 +0200 From: Sebastian Andrzej Siewior To: Peter Ujfalusi Subject: Re: [RFC] ARM: edma: unconditionally ack the error interrupt Message-ID: <20140918161225.GA10232@linutronix.de> References: <1410377960-26921-1-git-send-email-bigeasy@linutronix.de> <541AA900.4080506@ti.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <541AA900.4080506@ti.com> X-Key-Id: 97C4700B X-Key-Fingerprint: 09E2 D1F3 9A3A FF13 C3D3 961C 0688 1C1E 97C4 700B User-Agent: Mutt/1.5.21 (2010-09-15) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140918_091247_902630_2799C5A7 X-CRM114-Status: GOOD ( 16.46 ) X-Spam-Score: -0.7 (/) Cc: linux-omap@vger.kernel.org, Sekhar Nori , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP * Peter Ujfalusi | 2014-09-18 12:42:24 [+0300]: >My hunch on what could be causing this that we might have unhandled dma event >and another comes. This will flag the EDMA_EMR register. Any change in this >register will assert error interrupt which can only be cleared by writing to >EDMA_EMRC register. >The EDMA_EMRC register bits also cleared on edma_start(), edma_stop() and >edma_clean_channel() apart from the error interrupt handler. >So it is possible that we have missed event on one of the channels but a stop >might clear the event so in the interrupt hander we do not see this. >I think it would be good to understand what is going on the backround... >Can you print out the EDMA_EMCR just before we clear it in the places I have >mentioned? We might get better understanding on which stage we clear it and >probably we can understand how to fix this properly so we are not going to >have missed events on channels. Okay. For the protocol I applied this patch: --- and the result is something like this: -0 [000] dnh. 303.356403: edma_start: j0 mask8000000 EDMA_EMCR: 0 -0 [000] d.h. 303.396721: edma_stop: j0 mask8000000 EDMA_EMCR: 0 -0 [000] dnh. 303.557103: edma_start: j0 mask8000000 EDMA_EMCR: 0 -0 [000] dnh. 303.557129: edma_stop: j0 mask4000000 EDMA_EMCR: 0 -0 [000] dnH. 303.557142: dma_ccerr_handler: Unhandled less-2612 [000] d... 303.557237: edma_start: j0 mask4000000 EDMA_EMCR: 0 less-2612 [000] d.h. 303.562491: edma_stop: j0 mask4000000 EDMA_EMCR: 0 less-2612 [000] d... 303.564475: edma_start: j0 mask4000000 EDMA_EMCR: 0 The full trace is at [0]. I haven't found a single entry where EDMA_EMCR was != 0 at those spots. *If* there is a edma_stop() before the interrupt then the interrupt remains unhandled. If there is a edma_start() with mask 8000000 then we have dma_ccerr_handler() with a mask of 4000000. Fun fact: If I remove the write access to EDMA_EMCR register (the write access after the read out) then I haven't seen [1] a single error interrupt beeing "unhandled" out of 9. The former has three out of eight. [0] https://breakpoint.cc/edma_trace.txt.xz [1] https://breakpoint.cc/edma_trace_nowrite.txt.xz Sebastian diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c index 160460ae3a49..16598625a4d1 100644 --- a/arch/arm/common/edma.c +++ b/arch/arm/common/edma.c @@ -422,20 +422,24 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data) int i; int ctlr; unsigned int cnt = 0; + u32 emr0; ctlr = irq2ctlr(irq); if (ctlr < 0) return IRQ_NONE; dev_dbg(data, "dma_ccerr_handler\n"); + emr0 = edma_read_array(ctlr, EDMA_EMR, 0); - if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) && + if ((emr0 == 0) && (edma_read_array(ctlr, EDMA_EMR, 1) == 0) && (edma_read(ctlr, EDMA_QEMR) == 0) && (edma_read(ctlr, EDMA_CCERR) == 0)) { edma_write(ctlr, EDMA_EEVAL, 1); + trace_printk("Unhandled\n"); return IRQ_NONE; } + trace_printk("emr0: %x\n", emr0); while (1) { int j = -1; @@ -1310,6 +1314,9 @@ int edma_start(unsigned channel) pr_debug("EDMA: ER%d %08x\n", j, edma_shadow0_read_array(ctlr, SH_ER, j)); /* Clear any pending event or error */ + trace_printk("j%d mask%x EDMA_EMCR: %x\n", + j, mask, + edma_read_array(ctlr, EDMA_EMCR, j)); edma_write_array(ctlr, EDMA_ECR, j, mask); edma_write_array(ctlr, EDMA_EMCR, j, mask); /* Clear any SER */ @@ -1347,6 +1354,9 @@ void edma_stop(unsigned channel) edma_shadow0_write_array(ctlr, SH_EECR, j, mask); edma_shadow0_write_array(ctlr, SH_ECR, j, mask); edma_shadow0_write_array(ctlr, SH_SECR, j, mask); + trace_printk("j%d mask%x EDMA_EMCR: %x\n", + j, mask, + edma_read_array(ctlr, EDMA_EMCR, j)); edma_write_array(ctlr, EDMA_EMCR, j, mask); pr_debug("EDMA: EER%d %08x\n", j, @@ -1387,6 +1397,9 @@ void edma_clean_channel(unsigned channel) edma_read_array(ctlr, EDMA_EMR, j)); edma_shadow0_write_array(ctlr, SH_ECR, j, mask); /* Clear the corresponding EMR bits */ + trace_printk("j%d mask%x EDMA_EMCR: %x\n", + j, mask, + edma_read_array(ctlr, EDMA_EMCR, j)); edma_write_array(ctlr, EDMA_EMCR, j, mask); /* Clear any SER */ edma_shadow0_write_array(ctlr, SH_SECR, j, mask);