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

Reply via email to