On Wed, Sep 10, 2014 at 09:30:07PM +0200, Sebastian Andrzej Siewior wrote:
> Sometimes the OMAP UART does not signal the DMA engine to unload the FIFO.
> Usually this happens when we have >threshold bytes in the FIFO
> and start the DMA transfer. It seems that in those cases the UART won't
> trigger the transfer once the requested threshold is reached. In some
> rare cases the UART does not trigger the DMA transfer even if programmed
> while the FIFO was empty.
> In those cases the UART drops an RDI event and we have to empty the FIFO
> manually. If we ignore it because the DMA transfer is programmed then we
> will enter the function a few times until we receive the RX_TIMEOUT
> event. At that point the FIFO is usually full and we risk to overflow
> the FIFO.
> 
> Reviewed-by: Tony Lindgren <[email protected]>
> Tested-by: Tony Lindgren <[email protected]>
> Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
> ---
>  drivers/tty/serial/8250/8250_dma.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/drivers/tty/serial/8250/8250_dma.c 
> b/drivers/tty/serial/8250/8250_dma.c
> index fa1dc966f394..898a6781d0b3 100644
> --- a/drivers/tty/serial/8250/8250_dma.c
> +++ b/drivers/tty/serial/8250/8250_dma.c
> @@ -193,6 +193,24 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned 
> int iir)
>                       __dma_rx_do_complete(p, true);
>               }
>               return -ETIMEDOUT;
> +     case UART_IIR_RDI:
> +             if (p->bugs & UART_BUG_DMA_RX)
> +                     break;
> +             /*
> +              * The OMAP UART is a special BEAST. If we receive RDI we _have_
> +              * a DMA transfer programmed but it didn't worked. One reason is

didn't work

> +              * that we were too slow and there were too many bytes in the
> +              * FIFO, the UART counted wrong and never kicked the DMA engine
> +              * to do anything. That means once we receive RDI on OMAP than

then

> +              * the DMA won't do anything soon so we have to cancel the DMA
> +              * transfer and purge the FIFO manually.
> +              */
> +             if (dma->rx_running) {
> +                     dmaengine_pause(dma->rxchan);
> +                     __dma_rx_do_complete(p, true);
> +             }
> +             return -ETIMEDOUT;
> +
>       default:
>               break;
>       }
> -- 
> 2.1.0
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to