Re: [RFC] Switching 8250_omap to use 8250_dma RX and TX flow

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

 



On 09/15/16 16:22, Sebastian Andrzej Siewior wrote:
> On 2016-09-14 17:27:37 [+0530], Vignesh R wrote:
>> 1. 8250_dma DMA sets up DMA RX transfer size to be PAGE_SIZE or 4K
>> bytes. 8250_omap RX DMA trigger size is currently 48 bytes. Which means
>> whenever there are 48 bytes in UART FIFO, DMA is triggered and data is
>> taken out by DMA, this happens until 4K bytes are fetched and then DMA
>> completion callback is invoked which pushes that data to tty layer. If
>> number of bytes in FIFO <48 bytes then RX timeout is raised and data
>> driver pushes the data to tty layer. But if the data received is
>> multiple of 48 bytes but <4KB then, neither there is RX timeout(as data
>> is taken out by DMA) nor DMA completion callback(as 4K bytes have not
>> yet been received). This means the data is stuck in DMA destination
>> forever.
>> Now, I believe this is a generic problem for all 8250 UARTs
>> using core 8250_dma. I am not sure how to workaround this. Any ideas??
> 
> counting is important here. As far as I remember if you receive one byte
> _before_ you programmed the DMA engine then the core will wait for 48
> *additional* bytes. That means one byte in the FIFO, DMA engine
> programmed, 47 bytes follow (so 48 in total) will result in an timeout
> interrupt. I am sure this was the case with EDMA not sure about SDMA but
> I *think* it is the same case.
> This is why the OMAP's DMA code programs the DMA transfer upfront.

Not really. The reason we tend to set up the DMA first (speaking of audio, bu
applies to other peripherals imho):
at the start of TX the FIFO is empty, if we release the TX in the peripheral
it is going to underrun as there is no data in the FIFO. SO we start first the
DMA, enable the DMA requests in the IP and then release the TX. This way the
FIFO will contain valid data.
On the RX side the issue is if we do not have FIFO. If we enable the RX but
the DMA has not been started we will have overflow in the peripherals as the
next incoming data will overwrite the previous one - no one is reading the
data out yet. So we start the DMA first, which will wait for the request to
read the data out.

But if you have FIFO on the RX, then the DMA can be started after the UART
started the reception, as long as it is not delayed too long that we will have
overrrun in the FIFO. So if we have 1 byte in FIFO when we start the DMA, then
the DMA will read that out, then the next, then the next, until it received
48bytes, if that is what it has been configured. But AFAIK we use bursts from
UART, so we configure that the FIFO should have 40(?) bytes and only then the
DMA request should be asserted. DMA will read the 40(?) bytes out, so again it
does not matter if we had 1 byte in the FIFO when the DMA started.

> Intel's UART on the hand programs the transfer later for 4KiB and the
> transfer completes with at "some point". I am not sure if this is OMAP
> that does it different compared to Intel or if everyone else behaves
> that way except for Intel.
> 
>> 2. TX DMA stalls if UART_MCR register is written to(as part of
>> set_termios call) when DMA is in progress. Currently, this is worked
>> around by delaying termios change. This results in deviation from TX DMA
>> flow. IMO, changing termios when transfer is in progress is not a
>> real usecase and not recommended. So, either driver can error out in
>> this condition or avoid touching UART_MCR register(which is mainly used
>> to switch to Loopback mode and enable access to DMA trigger
>> configuration register).
> 
> this workaround was introduced after busybox userland trigger this bug
> (I think busybox's vi was the test case).
> If you error out you probably break *this* userland because the settings
> busybox asked for were not applied. And if I am not wrong, set_termios
> does not return an error code.
> 
>> So I propose to submit patches to allow 8250_omap to use 8250_dma for
>> UART DMA support and remove UART DMA support for AM335x and AM437x that
>> do not have SDMA.
> 
> Nobody stepped up to get this pause-RX transfer merged. You need this
> because if you can receive less than 48 bytes and you need to purge the
> FIFO manually. And for this you need to pause the transfer _unless_ you
> find a way to deal with this situation in a different way.
> So before thinking about enabling SDMA you need to get this fixed first.
> 
> And then why would you want to get rid of EDMA support? As far as I
> remember it is working and you can enable RX path. I left it off because
> it was easier to disable it for both than to check if we are using EDMA
> or SDMA.
> But you have still open issues. One thing is that you receive two
> interrupts per complete transfer: one from UART and one from DMA. The
> UART interrupt should be suppressed / taken care. (I remember someone
> pointed out that the Intel manual pointed out that we use an invalid
> interrupt mask / MCR register settings but don't remember the details. I
> *think* that problem is also present on the Intel HW.)
> Right now, on high baud rates it is possible that UART interrupt will be
> disabled because it returned often enough with IRQ_NONE while the DMA
> engine handled all RX packets.
> Your second problem is that the starting / programming of a transfer
> (RX) is deferred into softirq context which may be too late. That means
> you can receive a TIMEOUT interrupt _before_ you the softirq programmed
> the dma_engine and the following dma_pause() will returned an error.
> 
> I *strongly* suggest you identify and fix the open issue before you
> throw out EDMA support. I am sure that there are people that are using
> it on am335x.
> 
> Sebastian
> 


-- 
Péter
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux