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