From d71505b6672c438af37771e92c24c1d73e943f8c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Sep 2013 10:32:50 -0400 Subject: edma: Update author email address Matt's @ti.com address bounces. Update the MODULE_AUTHOR information in edma.c to his Linaro address. Signed-off-by: Josh Boyer Acked-by: Matt Porter Signed-off-by: Vinod Koul --- drivers/dma/edma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index ff50ff4c6a57..098a8da450f0 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -749,6 +749,6 @@ static void __exit edma_exit(void) } module_exit(edma_exit); -MODULE_AUTHOR("Matt Porter "); +MODULE_AUTHOR("Matt Porter "); MODULE_DESCRIPTION("TI EDMA DMA engine driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From c2b9e974e6bfef52a250ea57684a6f70e4c8275a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 4 Sep 2013 09:32:03 -0400 Subject: dma/Kconfig: Make TI_EDMA select TI_PRIV_EDMA The TI_EDMA driver unconditionally calls functions provided by the TI_PRIV_EDMA code, but it doesn't force that to be built-in. If that isn't otherwise enabled somewhere, you can get build errors like: linux-3.12.0-0.rc0.git1.1.fc21.armv7hl/drivers/dma/edma.c:593: undefined reference to `edma_free_slot' drivers/built-in.o: In function `edma_terminate_all': linux-3.12.0-0.rc0.git1.1.fc21.armv7hl/drivers/dma/edma.c:169: undefined reference to `edma_stop' drivers/built-in.o: In function `edma_execute': linux-3.12.0-0.rc0.git1.1.fc21.armv7hl/drivers/dma/edma.c:122: undefined reference to `edma_write_slot' linux-3.12.0-0.rc0.git1.1.fc21.armv7hl/drivers/dma/edma.c:149: undefined reference to `edma_link' linux-3.12.0-0.rc0.git1.1.fc21.armv7hl/drivers/dma/edma.c:152: undefined reference to `edma_start' Make TI_EDMA select TI_PRIV_EDMA to avoid this. Signed-off-by: Josh Boyer Acked-by: Matt Porter Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 526ec77c7ba0..f238cfd33847 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -198,6 +198,7 @@ config TI_EDMA depends on ARCH_DAVINCI || ARCH_OMAP select DMA_ENGINE select DMA_VIRTUAL_CHANNELS + select TI_PRIV_EDMA default n help Enable support for the TI EDMA controller. This DMA -- cgit v1.2.3 From edc530fe7ee5a562680615d2e7cd205879c751a7 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 17 Sep 2013 15:56:06 +0200 Subject: dmaengine: imx-dma: fix slow path issue in prep_dma_cyclic When perparing cyclic_dma buffers by the sound layer, it will dump the following lockdep trace. The leading snd_pcm_action_single get called with read_lock_irq called. To fix this, we change the kcalloc call from GFP_KERNEL to GFP_ATOMIC. WARNING: at kernel/lockdep.c:2740 lockdep_trace_alloc+0xcc/0x114() DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags)) Modules linked in: CPU: 0 PID: 832 Comm: aplay Not tainted 3.11.0-20130823+ #903 Backtrace: [] (dump_backtrace+0x0/0x10c) from [] (show_stack+0x18/0x1c) r6:c004c090 r5:00000009 r4:c2e0bd18 r3:00404000 [] (show_stack+0x0/0x1c) from [] (dump_stack+0x20/0x28) [] (dump_stack+0x0/0x28) from [] (warn_slowpath_common+0x54/0x70) [] (warn_slowpath_common+0x0/0x70) from [] (warn_slowpath_fmt+0x38/0x40) r8:00004000 r7:a3b90000 r6:000080d0 r5:60000093 r4:c2e0a000 r3:00000009 [] (warn_slowpath_fmt+0x0/0x40) from [] (lockdep_trace_alloc+0xcc/0x114) r3:c03955d8 r2:c03907db [] (lockdep_trace_alloc+0x0/0x114) from [] (__kmalloc+0x34/0x118) r6:000080d0 r5:c3800120 r4:000080d0 r3:c040a0f8 [] (__kmalloc+0x0/0x118) from [] (imxdma_prep_dma_cyclic+0x64/0x168) r7:a3b90000 r6:00000004 r5:c39d8420 r4:c3847150 [] (imxdma_prep_dma_cyclic+0x0/0x168) from [] (snd_dmaengine_pcm_trigger+0xa8/0x160) [] (snd_dmaengine_pcm_trigger+0x0/0x160) from [] (soc_pcm_trigger+0x90/0xb4) r8:c058c7b0 r7:c3b8140c r6:c39da560 r5:00000001 r4:c3b81000 [] (soc_pcm_trigger+0x0/0xb4) from [] (snd_pcm_do_start+0x2c/0x38) r7:00000000 r6:00000003 r5:c058c7b0 r4:c3b81000 [] (snd_pcm_do_start+0x0/0x38) from [] (snd_pcm_action_single+0x40/0x6c) [] (snd_pcm_action_single+0x0/0x6c) from [] (snd_pcm_action_lock_irq+0x7c/0x9c) r7:00000003 r6:c3b810f0 r5:c3b810f0 r4:c3b81000 [] (snd_pcm_action_lock_irq+0x0/0x9c) from [] (snd_pcm_common_ioctl1+0x7f8/0xfd0) r8:c3b7f888 r7:005407b8 r6:c2c991c0 r5:c3b81000 r4:c3b81000 r3:00004142 [] (snd_pcm_common_ioctl1+0x0/0xfd0) from [] (snd_pcm_playback_ioctl1+0x464/0x488) [] (snd_pcm_playback_ioctl1+0x0/0x488) from [] (snd_pcm_playback_ioctl+0x34/0x40) r8:c3b7f888 r7:00004142 r6:00000004 r5:c2c991c0 r4:005407b8 [] (snd_pcm_playback_ioctl+0x0/0x40) from [] (vfs_ioctl+0x30/0x44) [] (vfs_ioctl+0x0/0x44) from [] (do_vfs_ioctl+0x55c/0x5c0) [] (do_vfs_ioctl+0x0/0x5c0) from [] (SyS_ioctl+0x40/0x68) [] (SyS_ioctl+0x0/0x68) from [] (ret_fast_syscall+0x0/0x44) r8:c0009544 r7:00000036 r6:bedeaa58 r5:00000000 r4:000000c0 Signed-off-by: Michael Grzeschik Signed-off-by: Vinod Koul --- drivers/dma/imx-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 78f8ca5fccee..442af6189cbc 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -883,7 +883,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( kfree(imxdmac->sg_list); imxdmac->sg_list = kcalloc(periods + 1, - sizeof(struct scatterlist), GFP_KERNEL); + sizeof(struct scatterlist), GFP_ATOMIC); if (!imxdmac->sg_list) return NULL; -- cgit v1.2.3 From 5a276fa6bdf82fd442046969603968c83626ce0b Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 17 Sep 2013 15:56:07 +0200 Subject: dmaengine: imx-dma: fix lockdep issue between irqhandler and tasklet The tasklet and irqhandler are using spin_lock while other routines are using spin_lock_irqsave/restore. This leads to lockdep issues as described bellow. This patch is changing the code to use spinlock_irq_save/restore in both code pathes. As imxdma_xfer_desc always gets called with spin_lock_irqsave lock held, this patch also removes the spare call inside the routine to avoid double locking. [ 403.358162] ================================= [ 403.362549] [ INFO: inconsistent lock state ] [ 403.366945] 3.10.0-20130823+ #904 Not tainted [ 403.371331] --------------------------------- [ 403.375721] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. [ 403.381769] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: [ 403.386762] (&(&imxdma->lock)->rlock){?.-...}, at: [] imxdma_tasklet+0x20/0x134 [ 403.395201] {IN-HARDIRQ-W} state was registered at: [ 403.400108] [] mark_lock+0x2a0/0x6b4 [ 403.404798] [] __lock_acquire+0x650/0x1a64 [ 403.410004] [] lock_acquire+0x94/0xa8 [ 403.414773] [] _raw_spin_lock+0x54/0x8c [ 403.419720] [] dma_irq_handler+0x78/0x254 [ 403.424845] [] handle_irq_event_percpu+0x38/0x1b4 [ 403.430670] [] handle_irq_event+0x44/0x64 [ 403.435789] [] handle_level_irq+0xd8/0xf0 [ 403.440903] [] generic_handle_irq+0x28/0x38 [ 403.446194] [] handle_IRQ+0x68/0x8c [ 403.450789] [] avic_handle_irq+0x3c/0x48 [ 403.455811] [] __irq_svc+0x44/0x74 [ 403.460314] [] cpu_startup_entry+0x88/0xf4 [ 403.465525] [] rest_init+0xb8/0xe0 [ 403.470045] [] start_kernel+0x28c/0x2d4 [ 403.474986] [] 0xa0008040 [ 403.478709] irq event stamp: 50854 [ 403.482140] hardirqs last enabled at (50854): [] tasklet_action+0x38/0xdc [ 403.489954] hardirqs last disabled at (50853): [] tasklet_action+0x20/0xdc [ 403.497761] softirqs last enabled at (50850): [] _local_bh_enable+0x14/0x18 [ 403.505741] softirqs last disabled at (50851): [] irq_exit+0x88/0xdc [ 403.513026] [ 403.513026] other info that might help us debug this: [ 403.519593] Possible unsafe locking scenario: [ 403.519593] [ 403.525548] CPU0 [ 403.528020] ---- [ 403.530491] lock(&(&imxdma->lock)->rlock); [ 403.534828] [ 403.537474] lock(&(&imxdma->lock)->rlock); [ 403.541983] [ 403.541983] *** DEADLOCK *** [ 403.541983] [ 403.547951] no locks held by swapper/0. [ 403.551813] [ 403.551813] stack backtrace: [ 403.556222] CPU: 0 PID: 0 Comm: swapper Not tainted 3.10.0-20130823+ #904 [ 403.563039] Backtrace: [ 403.565581] [] (dump_backtrace+0x0/0x10c) from [] (show_stack+0x18/0x1c) [ 403.574054] r6:00000000 r5:c05c51d8 r4:c040bd58 r3:00200000 [ 403.579872] [] (show_stack+0x0/0x1c) from [] (dump_stack+0x20/0x28) [ 403.587955] [] (dump_stack+0x0/0x28) from [] (print_usage_bug.part.28+0x224/0x28c) [ 403.597340] [] (print_usage_bug.part.28+0x0/0x28c) from [] (mark_lock+0x440/0x6b4) [ 403.606682] r8:c004a41c r7:00000000 r6:c040bd58 r5:c040c040 r4:00000002 [ 403.613566] [] (mark_lock+0x0/0x6b4) from [] (__lock_acquire+0x6cc/0x1a64) [ 403.622244] [] (__lock_acquire+0x0/0x1a64) from [] (lock_acquire+0x94/0xa8) [ 403.631010] [] (lock_acquire+0x0/0xa8) from [] (_raw_spin_lock+0x54/0x8c) [ 403.639614] [] (_raw_spin_lock+0x0/0x8c) from [] (imxdma_tasklet+0x20/0x134) [ 403.648434] r6:c3847010 r5:c040e890 r4:c38470d4 [ 403.653194] [] (imxdma_tasklet+0x0/0x134) from [] (tasklet_action+0x8c/0xdc) [ 403.662013] r8:c0599160 r7:00000000 r6:00000000 r5:c040e890 r4:c3847114 r3:c019d75c [ 403.670042] [] (tasklet_action+0x0/0xdc) from [] (__do_softirq+0xe4/0x1f0) [ 403.678687] r7:00000101 r6:c0402000 r5:c059919c r4:00000001 [ 403.684498] [] (__do_softirq+0x0/0x1f0) from [] (irq_exit+0x88/0xdc) [ 403.692652] [] (irq_exit+0x0/0xdc) from [] (handle_IRQ+0x6c/0x8c) [ 403.700514] r4:00000030 r3:00000110 [ 403.704192] [] (handle_IRQ+0x0/0x8c) from [] (avic_handle_irq+0x3c/0x48) [ 403.712664] r5:c0403f28 r4:c0593ebc [ 403.716343] [] (avic_handle_irq+0x0/0x48) from [] (__irq_svc+0x44/0x74) [ 403.724733] Exception stack(0xc0403f28 to 0xc0403f70) [ 403.729841] 3f20: 00000001 00000004 00000000 20000013 c0402000 c04104a8 [ 403.738078] 3f40: 00000002 c0b69620 a0004000 41069264 a03fb5f4 c0403f7c c0403f40 c0403f70 [ 403.746301] 3f60: c004b92c c0009e74 20000013 ffffffff [ 403.751383] r6:ffffffff r5:20000013 r4:c0009e74 r3:c004b92c [ 403.757210] [] (arch_cpu_idle+0x0/0x4c) from [] (cpu_startup_entry+0x88/0xf4) [ 403.766161] [] (cpu_startup_entry+0x0/0xf4) from [] (rest_init+0xb8/0xe0) [ 403.774753] [] (rest_init+0x0/0xe0) from [] (start_kernel+0x28c/0x2d4) [ 403.783051] r6:c03fc484 r5:ffffffff r4:c040a0e0 [ 403.787797] [] (start_kernel+0x0/0x2d4) from [] (0xa0008040) Signed-off-by: Michael Grzeschik Signed-off-by: Vinod Koul --- drivers/dma/imx-dma.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 442af6189cbc..247aa7cae37c 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -437,17 +437,18 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac) struct imxdma_engine *imxdma = imxdmac->imxdma; int chno = imxdmac->channel; struct imxdma_desc *desc; + unsigned long flags; - spin_lock(&imxdma->lock); + spin_lock_irqsave(&imxdma->lock, flags); if (list_empty(&imxdmac->ld_active)) { - spin_unlock(&imxdma->lock); + spin_unlock_irqrestore(&imxdma->lock, flags); goto out; } desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node); - spin_unlock(&imxdma->lock); + spin_unlock_irqrestore(&imxdma->lock, flags); if (desc->sg) { u32 tmp; @@ -519,7 +520,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 +527,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 +536,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 +546,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 +621,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 +660,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, -- cgit v1.2.3 From fcaaba6c7136fe47e5a13352f99a64b019b6d2c5 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 17 Sep 2013 15:56:08 +0200 Subject: dmaengine: imx-dma: fix callback path in tasklet We need to free the ld_active list head before jumping into the callback routine. Otherwise the callback could run into issue_pending and change our ld_active list head we just going to free. This will run the channel list into an currupted and undefined state. Signed-off-by: Michael Grzeschik Signed-off-by: Vinod Koul --- drivers/dma/imx-dma.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 247aa7cae37c..55852c026791 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -627,13 +627,11 @@ static void imxdma_tasklet(unsigned long data) if (list_empty(&imxdmac->ld_active)) { /* Someone might have called terminate all */ - goto out; + spin_unlock_irqrestore(&imxdma->lock, flags); + return; } desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node); - if (desc->desc.callback) - desc->desc.callback(desc->desc.callback_param); - /* If we are dealing with a cyclic descriptor, keep it on ld_active * and dont mark the descriptor as complete. * Only in non-cyclic cases it would be marked as complete @@ -661,6 +659,10 @@ static void imxdma_tasklet(unsigned long data) } out: spin_unlock_irqrestore(&imxdma->lock, flags); + + if (desc->desc.callback) + desc->desc.callback(desc->desc.callback_param); + } static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, -- cgit v1.2.3