[PATCH] ARM: add PrimeCell generic DMA to PL011

Russell King - ARM Linux linux at arm.linux.org.uk
Wed Dec 22 15:52:13 EST 2010


On Wed, Dec 22, 2010 at 08:34:39PM +0000, Russell King - ARM Linux wrote:
> On Wed, Dec 22, 2010 at 06:20:41PM +0000, Russell King - ARM Linux wrote:
> > On Wed, Dec 22, 2010 at 06:09:22PM +0100, Linus Walleij wrote:
> > > 2010/12/22 Russell King - ARM Linux <linux at arm.linux.org.uk>:
> > > > On Wed, Oct 06, 2010 at 11:32:06AM +0200, Linus Walleij wrote:
> > > >>       /*
> > > >> -      * Finally, enable interrupts
> > > >> +      * Finally, enable interrupts, only timeouts when using DMA
> > > >> +      * if initial RX DMA job failed, start in interrupt mode
> > > >> +      * as well.
> > > >>        */
> > > >>       spin_lock_irq(&uap->port.lock);
> > > >> -     uap->im = UART011_RXIM | UART011_RTIM;
> > > >> +     if (uap->enable_dma && uap->rx_dma_running)
> > > >> +             uap->im = UART011_RTIM;
> > > >> +     else
> > > >> +             uap->im = UART011_RXIM | UART011_RTIM;
> > > >>       writew(uap->im, uap->port.membase + UART011_IMSC);
> > > >
> > > > There's a big hole here, using DMA on the receive path.
> > > >
> > > > | 3.4.4 UARTRTINTR
> > > > | The receive timeout interrupt is asserted when the receive FIFO is not
> > > > | empty, and no further data is received over a 32-bit period. The receive
> > > > | timeout interrupt is cleared either when the FIFO becomes empty through
> > > > | reading all the data (or by reading the holding register), or when a 1
> > > > | is written to the corresponding bit of the UARTICR register.
> > > >
> > > > There must be unread data in the FIFO for us to get a RT interrupt.  The
> > > > problem is that if we have DMA enabled, then the received characters are
> > > > read from the FIFO as soon as they appear, and so the FIFO becomes empty,
> > > > which negates the conditions required for the RT interrupt to be
> > > > generated.
> > > 
> > > The DMA on the RX channel will not read single bytes at all,
> > > instead it waits until it can retrieve a burst, which is set to half
> > > a FIFO: src_maxburst = uap->fifosize >> 1,
> > 
> > I refer you to section 2.7, which describes the DMA interface.
> > 
> > UARTRXDMASREQ
> > Single character DMA transfer request, asserted by the UART. For
> > receive, one character consists of up to 12 bits. This signal is asserted
> > when the receive FIFO contains at least one character.
> > 
> > UARTRXDMABREQ
> > Burst DMA transfer request, asserted by the UART. This signal is
> > asserted when the receive FIFO contains more characters than the
> > programmed watermark level. You can program the watermark level for
> > each FIFO through the UARTIFLS register.
> > 
> > If your DMA controller is using UARTRXDMASREQ, then you'll end up DMAing
> > single bytes as long as the FIFO contains any bytes - thereby causing
> > it to be emptied completely.  As 3.4.4 says, if the FIFO is empty, you
> > don't get the timeout.
> > 
> > The PB926 doesn't specify whether it connects the burst or single-
> > character DMA request signal to the DMA controller - from the behaviour
> > I observe, I suspect it's the single character request which is.
> 
> And here's what /proc/interrupts reports:
> 
>  12:         38         VIC  uart-pl011
> 
> Now, I send exactly one 'o' to the port:
> 
>  12:         38         VIC  uart-pl011
> 
> no interrupt received.  If I extend PL08x's debugfs output to include
> a register dump (src, dest, lli, ctrl, conf):
> 
> 0               uart0rx
>                 [101f1000 019c4007 0111c011 1a0123f9 0000d01d]
> 
> now if I send three characters:
> 
> 0               uart0rx
>                 [101f1000 019c400a 0111c011 1a0123f6 0000d01d]
> 
> Note that the address has increased by three, and the count has
> decremented by three.  This confirms that the DMA is reading the data as
> the UART FIFO fills - rather than DMA waiting for the FIFO to partially
> fill before starting a request.
> 
> This emptying of the RX UART FIFO of all received data prevents the RX
> timeout condition being satisfied, which in turn prevents any reasonable
> use of the UART port.
> 
> I think the answer here is to allow the platform to supply just the TX
> DMA channel, so when a UART is wired up to use the single-character
> request, RX DMA support can be omitted.

One final point on this: it _will_ work if you send a corrupted
character or break first - that sets an error interrupt flag, which
remains latched because the ICR is never written to clear them.
Could that also have something to do with why your setup works?

I'll continue hacking the RX DMA support around, but for the time
being, I've committed my revised TX DMA support in several patches
to my tree.  That won't work on its own because the mainline
amba-pl08x.c is rather functional on PB/926 - and of course it has
the deadlock issue.



More information about the linux-arm-kernel mailing list