Hi Wolfram, > > [<bf9921e7>] (tmio_mmc_dma_callback) from [<bf908e1b>] > (rzadma_tasklet+0x23/0x98) > > For SYS-DMAC, this is a callback called by the dmaengine core once the > DMA is completed. My guess is you call it directly from an interrupt > handler? It would be easier to talk over code here, I guess. > > > Is it now a requirement that I have to register my DMA channel > > interrupts as devm_request_threaded_irq? > > > > Will that fix my issue? > > I can't say yet if this alone will do. Likely not. Can you share the > code already? The interrupt handler is starting a tasklet, and then the tasklet calls the callback. I thought tasklets didn't run in an interrupt context????? As a code snippet, here is the irq hander and the tasket. Of course I can send the entire file if you want as well if you need to see more. static void dma_irq_handle_channel(struct rzadma_channel *rzadmac) { u32 chstat, chctrl; struct rzadma_engine *rzadma = rzadmac->rzadma; int channel = rzadmac->channel; chstat = rzadma_ch_readl(rzadmac, CHSTAT, 1); if (chstat & CHSTAT_ER) { dev_dbg(rzadma->dev, "CHSTAT_%d = %08X\n", channel, chstat); rzadma_ch_writel(rzadmac, CHCTRL_DEFAULT, CHCTRL, 1); goto schedule; } if (!(chstat & CHSTAT_END)) return; chctrl = rzadma_ch_readl(rzadmac, CHCTRL, 1); dev_dbg(rzadma->dev,"2. chctrl_%d=%08X\n", channel, chctrl); rzadma_ch_writel(rzadmac, chctrl | CHCTRL_CLREND | CHCTRL_CLRRQ, CHCTRL, 1); schedule: /* Tasklet irq */ tasklet_schedule(&rzadmac->dma_tasklet); } static void rzadma_tasklet(unsigned long data) { struct rzadma_channel *rzadmac = (void *)data; struct rzadma_engine *rzadma = rzadmac->rzadma; struct rzadma_desc *desc; unsigned long flags; /* Protection of critical section */ spin_lock_irqsave(&rzadma->lock, flags); if (list_empty(&rzadmac->ld_active)) { /* Someone might have called terminate all */ goto out; } desc = list_first_entry(&rzadmac->ld_active, struct rzadma_desc, node); if (desc->desc.callback) desc->desc.callback(desc->desc.callback_param); dma_cookie_complete(&desc->desc); if (list_empty(&rzadmac->ld_active)) { goto out; }else{ list_move_tail(rzadmac->ld_active.next, &rzadmac->ld_free); } if (!list_empty(&rzadmac->ld_queue)) { desc = list_first_entry(&rzadmac->ld_queue, struct rzadma_desc, node); if (rzadma_xfer_desc(desc) < 0){ dev_err(rzadma->dev, "%s: channel: %d couldn't xfer desc\n", __func__, rzadmac->channel); }else{ list_move_tail(rzadmac->ld_queue.next, &rzadmac->ld_active); } } out: spin_unlock_irqrestore(&rzadma->lock, flags); } > Isn't it SYS-DMAC compatible (sigh)? My first goal is to just get this DMA platform driver we made a couple years ago working with DT (ie, you can't go passing in slave IDs anymore via platform data structures). Technically, it is working now (after I revert your patch), but I probably have more things that have to change before I can think about submitting it upstream for review. Thank you! Chris