From patchwork Sat Jun 8 20:56:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Shiyan X-Patchwork-Id: 2693061 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork1.kernel.org (Postfix) with ESMTP id 8870D3FC23 for ; Sat, 8 Jun 2013 20:57:28 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UlQCQ-000644-SR; Sat, 08 Jun 2013 20:57:23 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UlQCO-0002q9-1C; Sat, 08 Jun 2013 20:57:20 +0000 Received: from smtp23.mail.ru ([94.100.176.176]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UlQCJ-0002pM-PW for linux-arm-kernel@lists.infradead.org; Sat, 08 Jun 2013 20:57:17 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail2; h=Message-Id:Date:Subject:Cc:To:From; bh=JlPMfFbNZrGANnIAGxOxKXhGcJj1zlO2xa1rmGZZSzI=; b=bYvaN8i++UqqQoXVYmugjcnX4/b0F6xsquG1l+bo0UDZqj/8NrAAtvKBRK+7VtcTqINrioQccC8N2cDZbNmAkW7SShxk8dR3ewAeTLieFBn3dKIJBGEDN6Uor7QtVJaON1GXZwPAIO+mTgkiQjgaL/onvnC6uK6XagT1UHpJf9M=; Received: from [188.134.40.128] (port=17425 helo=shc.zet) by smtp23.mail.ru with esmtpa (envelope-from ) id 1UlQBr-00075u-NX; Sun, 09 Jun 2013 00:56:47 +0400 From: Alexander Shiyan To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] ARM: dma: imx: Fix deadlock bug Date: Sun, 9 Jun 2013 00:56:28 +0400 Message-Id: <1370724988-16426-1-git-send-email-shc_work@mail.ru> X-Mailer: git-send-email 1.8.1.5 X-Spam: Not detected X-Mras: Ok X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130608_165716_458355_0D402150 X-CRM114-Status: GOOD ( 10.94 ) X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (shc_work[at]mail.ru) -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [94.100.176.176 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Russell King , Alexander Shiyan , Vinod Koul , Sascha Hauer , Dan Williams , Shawn Guo X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org ================================= [ INFO: inconsistent lock state ] 3.10.0-rc4-next-20130607-00006-gf5bbfe3-dirty #59 Not tainted --------------------------------- inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. swapper/1 [HC0[0]:SC1[1]:HE1:SE0] takes: (&(&imxdma->lock)->rlock){?.-...}, at: [] imxdma_tasklet+0x1c/0x138 {IN-HARDIRQ-W} state was registered at: [] __lock_acquire+0xa74/0x1a64 [] lock_acquire+0x64/0x78 [] _raw_spin_lock+0x34/0x44 [] dma_irq_handler+0x7c/0x250 [] handle_irq_event_percpu+0x50/0x1c8 [] handle_irq_event+0x3c/0x5c [] handle_level_irq+0x8c/0xe8 [] generic_handle_irq+0x20/0x30 [] handle_IRQ+0x30/0x84 [] avic_handle_irq+0x34/0x54 [] __irq_svc+0x44/0x74 [] ida_get_new_above+0x74/0x1c4 [] sysfs_new_dirent+0x60/0xf8 [] create_dir+0x28/0xc0 [] sysfs_create_dir+0x90/0xf4 [] kobject_add_internal+0x90/0x1d8 [] kobject_init_and_add+0x44/0x6c [] bus_add_driver+0x74/0x230 [] driver_register+0x78/0x14c [] do_one_initcall+0x50/0x158 [] kernel_init_freeable+0xe8/0x1ac [] kernel_init+0x8/0xe4 [] ret_from_fork+0x14/0x34 irq event stamp: 232290 hardirqs last enabled at (232290): [] tasklet_action+0x30/0xdc hardirqs last disabled at (232289): [] tasklet_action+0x18/0xdc softirqs last enabled at (232196): [] __do_softirq+0x174/0x1e0 softirqs last disabled at (232287): [] irq_exit+0xa0/0xdc other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&(&imxdma->lock)->rlock); lock(&(&imxdma->lock)->rlock); *** DEADLOCK *** 1 lock held by swapper/1: #0: (sysfs_ino_lock){+.+...}, at: [] sysfs_new_dirent+0x50/0xf8 stack backtrace: CPU: 0 PID: 1 Comm: swapper Not tainted 3.10.0-rc4-next-20130607-00006-gf5bbfe3-dirty #59 [] (unwind_backtrace+0x0/0xf0) from [] (show_stack+0x10/0x14) [] (show_stack+0x10/0x14) from [] (print_usage_bug.part.26+0x220/0x288) [] (print_usage_bug.part.26+0x220/0x288) from [] (mark_lock+0x288/0x668) [] (mark_lock+0x288/0x668) from [] (__lock_acquire+0x5ac/0x1a64) [] (__lock_acquire+0x5ac/0x1a64) from [] (lock_acquire+0x64/0x78) [] (lock_acquire+0x64/0x78) from [] (_raw_spin_lock+0x34/0x44) [] (_raw_spin_lock+0x34/0x44) from [] (imxdma_tasklet+0x1c/0x138) [] (imxdma_tasklet+0x1c/0x138) from [] (tasklet_action+0x78/0xdc) [] (tasklet_action+0x78/0xdc) from [] (__do_softirq+0xec/0x1e0) [] (__do_softirq+0xec/0x1e0) from [] (irq_exit+0xa0/0xdc) [] (irq_exit+0xa0/0xdc) from [] (handle_IRQ+0x34/0x84) [] (handle_IRQ+0x34/0x84) from [] (avic_handle_irq+0x34/0x54) [] (avic_handle_irq+0x34/0x54) from [] (__irq_svc+0x44/0x74) Signed-off-by: Alexander Shiyan --- drivers/dma/imx-dma.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index ff2aab9..65fe00a 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -318,12 +318,9 @@ static void imxdma_enable_hw(struct imxdma_desc *d) struct imxdma_channel *imxdmac = to_imxdma_chan(d->desc.chan); struct imxdma_engine *imxdma = imxdmac->imxdma; int channel = imxdmac->channel; - unsigned long flags; dev_dbg(imxdma->dev, "%s channel %d\n", __func__, channel); - local_irq_save(flags); - imx_dmav1_writel(imxdma, 1 << channel, DMA_DISR); imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_DIMR) & ~(1 << channel), DMA_DIMR); @@ -342,27 +339,23 @@ static void imxdma_enable_hw(struct imxdma_desc *d) } } - local_irq_restore(flags); } static void imxdma_disable_hw(struct imxdma_channel *imxdmac) { struct imxdma_engine *imxdma = imxdmac->imxdma; int channel = imxdmac->channel; - unsigned long flags; dev_dbg(imxdma->dev, "%s channel %d\n", __func__, channel); if (imxdma_hw_chain(imxdmac)) del_timer(&imxdmac->watchdog); - local_irq_save(flags); imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_DIMR) | (1 << channel), DMA_DIMR); imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_CCR(channel)) & ~CCR_CEN, DMA_CCR(channel)); imx_dmav1_writel(imxdma, 1 << channel, DMA_DISR); - local_irq_restore(flags); } static void imxdma_watchdog(unsigned long data) @@ -519,7 +512,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) { struct imxdma_channel *imxdmac = to_imxdma_chan(d->desc.chan); struct imxdma_engine *imxdma = imxdmac->imxdma; - unsigned long flags; int slot = -1; int i; @@ -527,7 +519,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) switch (d->type) { case IMXDMA_DESC_INTERLEAVED: /* Try to get a free 2D slot */ - spin_lock_irqsave(&imxdma->lock, flags); for (i = 0; i < IMX_DMA_2D_SLOTS; i++) { if ((imxdma->slots_2d[i].count > 0) && ((imxdma->slots_2d[i].xsr != d->x) || @@ -537,10 +528,8 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) slot = i; break; } - if (slot < 0) { - spin_unlock_irqrestore(&imxdma->lock, flags); + if (slot < 0) return -EBUSY; - } imxdma->slots_2d[slot].xsr = d->x; imxdma->slots_2d[slot].ysr = d->y; @@ -549,7 +538,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) imxdmac->slot_2d = slot; imxdmac->enabled_2d = true; - spin_unlock_irqrestore(&imxdma->lock, flags); if (slot == IMX_DMA_2D_SLOT_A) { d->config_mem &= ~CCR_MSEL_B; @@ -625,8 +613,9 @@ static void imxdma_tasklet(unsigned long data) struct imxdma_channel *imxdmac = (void *)data; struct imxdma_engine *imxdma = imxdmac->imxdma; struct imxdma_desc *desc; + unsigned long flags; - spin_lock(&imxdma->lock); + spin_lock_irqsave(&imxdma->lock, flags); if (list_empty(&imxdmac->ld_active)) { /* Someone might have called terminate all */ @@ -663,7 +652,7 @@ static void imxdma_tasklet(unsigned long data) __func__, imxdmac->channel); } out: - spin_unlock(&imxdma->lock); + spin_unlock_irqrestore(&imxdma->lock, flags); } static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, @@ -677,11 +666,12 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, switch (cmd) { case DMA_TERMINATE_ALL: - imxdma_disable_hw(imxdmac); - spin_lock_irqsave(&imxdma->lock, flags); + + imxdma_disable_hw(imxdmac); list_splice_tail_init(&imxdmac->ld_active, &imxdmac->ld_free); list_splice_tail_init(&imxdmac->ld_queue, &imxdmac->ld_free); + spin_unlock_irqrestore(&imxdma->lock, flags); return 0; case DMA_SLAVE_CONFIG: