Commit 56dc5074 authored by Ilpo Järvinen's avatar Ilpo Järvinen Committed by Greg Kroah-Hartman

serial: 8250_dma: Rearm DMA Rx if more data is pending

When DMA Rx completes, the current behavior is to just exit the DMA
completion handler without future actions. If the transfer is still
on-going, UART will trigger an interrupt and that eventually rearms the
DMA Rx. The extra interrupt round-trip has an inherent latency cost
that increases the risk of FIFO overrun. In such situations, the
latency margin tends to already be less due to FIFO not being empty.

Add check into DMA Rx completion handler to detect if LSR has DR (Data
Ready) still set. DR indicates there will be more characters pending
and DMA Rx can be rearmed right away to handle them.

Cc: Gilles BULOZ <gilles.buloz@kontron.com>
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20221107102126.56481-1-ilpo.jarvinen@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c6d30576
......@@ -38,9 +38,8 @@ static void __dma_tx_complete(void *param)
spin_unlock_irqrestore(&p->port.lock, flags);
}
static void __dma_rx_complete(void *param)
static void __dma_rx_complete(struct uart_8250_port *p)
{
struct uart_8250_port *p = param;
struct uart_8250_dma *dma = p->dma;
struct tty_port *tty_port = &p->port.state->port;
struct dma_tx_state state;
......@@ -57,6 +56,20 @@ static void __dma_rx_complete(void *param)
tty_flip_buffer_push(tty_port);
}
static void dma_rx_complete(void *param)
{
struct uart_8250_port *p = param;
struct uart_8250_dma *dma = p->dma;
unsigned long flags;
__dma_rx_complete(p);
spin_lock_irqsave(&p->port.lock, flags);
if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR))
p->dma->rx_dma(p);
spin_unlock_irqrestore(&p->port.lock, flags);
}
int serial8250_tx_dma(struct uart_8250_port *p)
{
struct uart_8250_dma *dma = p->dma;
......@@ -130,7 +143,7 @@ int serial8250_rx_dma(struct uart_8250_port *p)
return -EBUSY;
dma->rx_running = 1;
desc->callback = __dma_rx_complete;
desc->callback = dma_rx_complete;
desc->callback_param = p;
dma->rx_cookie = dmaengine_submit(desc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment