summaryrefslogtreecommitdiff
path: root/drivers/tty
diff options
context:
space:
mode:
authorMichael Walle <michael@walle.cc>2020-03-25 10:06:57 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-03-26 15:34:05 +0100
commitd0e7600b914c9fd4935fe6dabf0cd5d71cb94347 (patch)
tree480b2a47d73395835b6d446ddb3b8d8f3781c120 /drivers/tty
parenta0c4adeeea84889890bb4c7a28dc58b7c764e4ad (diff)
tty: serial: fsl_lpuart: move dma_request_chan()
Move dma_request_chan() out of the atomic context. First this call should not be in the atomic context at all and second the dev_info_once() may cause a hang because because the console takes this spinlock, too. Fixes: 159381df1442f ("tty: serial: fsl_lpuart: fix DMA operation when using IOMMU") Reported-by: Leonard Crestez <leonard.crestez@nxp.com> Signed-off-by: Michael Walle <michael@walle.cc> Reviewed-by: Fugang Duan <fugang.duan@nxp.com> Tested-by: Leonard Crestez <leonard.crestez@nxp.com> Link: https://lore.kernel.org/r/20200325090658.25967-1-michael@walle.cc Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/fsl_lpuart.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 9c6a018b1390..131018979b77 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1510,20 +1510,33 @@ static void rx_dma_timer_init(struct lpuart_port *sport)
add_timer(&sport->lpuart_timer);
}
-static void lpuart_tx_dma_startup(struct lpuart_port *sport)
+static void lpuart_request_dma(struct lpuart_port *sport)
{
- u32 uartbaud;
- int ret;
-
sport->dma_tx_chan = dma_request_chan(sport->port.dev, "tx");
if (IS_ERR(sport->dma_tx_chan)) {
dev_info_once(sport->port.dev,
"DMA tx channel request failed, operating without tx DMA (%ld)\n",
PTR_ERR(sport->dma_tx_chan));
sport->dma_tx_chan = NULL;
- goto err;
}
+ sport->dma_rx_chan = dma_request_chan(sport->port.dev, "rx");
+ if (IS_ERR(sport->dma_rx_chan)) {
+ dev_info_once(sport->port.dev,
+ "DMA rx channel request failed, operating without rx DMA (%ld)\n",
+ PTR_ERR(sport->dma_rx_chan));
+ sport->dma_rx_chan = NULL;
+ }
+}
+
+static void lpuart_tx_dma_startup(struct lpuart_port *sport)
+{
+ u32 uartbaud;
+ int ret;
+
+ if (!sport->dma_tx_chan)
+ goto err;
+
ret = lpuart_dma_tx_request(&sport->port);
if (!ret)
goto err;
@@ -1549,14 +1562,8 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport)
{
int ret;
- sport->dma_rx_chan = dma_request_chan(sport->port.dev, "rx");
- if (IS_ERR(sport->dma_rx_chan)) {
- dev_info_once(sport->port.dev,
- "DMA rx channel request failed, operating without rx DMA (%ld)\n",
- PTR_ERR(sport->dma_rx_chan));
- sport->dma_rx_chan = NULL;
+ if (!sport->dma_rx_chan)
goto err;
- }
ret = lpuart_start_rx_dma(sport);
if (ret)
@@ -1592,6 +1599,8 @@ static int lpuart_startup(struct uart_port *port)
sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_RXSIZE_OFF) &
UARTPFIFO_FIFOSIZE_MASK);
+ lpuart_request_dma(sport);
+
spin_lock_irqsave(&sport->port.lock, flags);
lpuart_setup_watermark_enable(sport);
@@ -1649,11 +1658,12 @@ static int lpuart32_startup(struct uart_port *port)
sport->port.fifosize = sport->txfifo_size;
}
+ lpuart_request_dma(sport);
+
spin_lock_irqsave(&sport->port.lock, flags);
lpuart32_setup_watermark_enable(sport);
-
lpuart_rx_dma_startup(sport);
lpuart_tx_dma_startup(sport);