RE: renesas sdhi driver and DMA

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux