Re: imx: RS-485 DMA problem analysis

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

 



Hi Uwe,

On Mon, Sep 04, 2017 at 08:47:08AM +0200, Uwe Kleine-König wrote:
> Hello Clemens,
> 
> first of all thanks for your research and feed back to the list.
> 
> On Mon, Sep 04, 2017 at 02:24:45AM +0200, Clemens Gruber wrote:
> > I finished my analysis of the imx RS-485 DMA problem, we discussed on
> > the list before and which was fixed upstream with commit 514ab34dbad6
> > ("serial: imx: Prevent TX buffer PIO write when a DMA has been started")
> > from Ian.
> > 
> > Open questions were:
> > 1) Why did this only appear on SMP machines?
> > 2) Why did this only affect RS-485?
> > 
> > Thanks to ftrace, I can now answer both:
> > 
> > 1) When starting a new transmission, the following happens in
> > imx_start_tx:
> > After imx_port_rts_active to enable the external RS-485 transceiver,
> > the transmit-complete-interrupt is enabled (TCEN).
> > Then, imx_dma_tx is called and the DMA request is handed off.
> > Now, while sdma_prep_slave_sg and sdma_load_context are executing on one
> > CPU core, imx_int is called on another, because the previously enabled
> > interrupt asserted immediately (TXDC was active because both the TxFIFO
> > and the Shifter were empty) after enabling it. (50us on i.MX6Q SMP)
> > This leads to the transmit_buffer function (called from imx_int/imx_txint)
> > writing to UTXD which corrupts the ongoing DMA transmission and also leads to
> > xmit->tail getting double-incremented and jumping over xmit->head, so the whole
> > UART_XMIT_SIZE xmit buffer is sent out.
> > On non-SMP machines, the interrupt is handled later when
> > uart_circ_empty(xmit) is already true and transmit_buffer returns before
> > doing PIO. With a non-SMP kernel on an i.MX6Q, I measured 35ms until
> > imx_int/imx_txint and the function_graph trace showed
> > imx_txint()
> >   imx_stop_tx()
> > (Instead of a trace_printk I added to the PIO loop in transmit_buffer)
> 
> I see that imx_start_tx only enables irqs but doesn't send data. So I
> wonder if this could be done better by already writing to TXDATA (in the
> !dma case) or preparing the DMA transfer (otherwise). Up to now the
> driver waits for an irq which introduces a needless delay first
> including a context switch first.

If DMA is enabled, imx_start_tx already calls imx_dma_tx.
But we could begin sending data in the !DMA case (and the X-char both in
DMA and !DMA cases) from within imx_start_tx and set TCEN at the end.

I'd also like to separate the handling of TRDY and TXDC in imx_int.
The latter is only relevant for RS-485 and should result in an
imx_stop_tx if uart_circ_empty || uart_tx_stopped. No need to jump into
imx_txint/imx_transmit_buffer with its x_char and wakeup handling.

Cheers,
Clemens
--
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