summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/stm32-usart.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/stm32-usart.c')
-rw-r--r--drivers/tty/serial/stm32-usart.c87
1 files changed, 31 insertions, 56 deletions
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index dfdbcf092fac..409e91d6829a 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -596,8 +596,7 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port)
if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE))
break;
writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
+ uart_xmit_advance(port, 1);
}
/* rely on TXE irq (mask or unmask) for sending remaining data */
@@ -673,8 +672,8 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port)
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT);
- xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
- port->icount.tx += count;
+ uart_xmit_advance(port, count);
+
return;
fallback_err:
@@ -798,25 +797,11 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
spin_unlock(&port->lock);
}
- if (stm32_usart_rx_dma_enabled(port))
- return IRQ_WAKE_THREAD;
- else
- return IRQ_HANDLED;
-}
-
-static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
-{
- struct uart_port *port = ptr;
- struct tty_port *tport = &port->state->port;
- struct stm32_port *stm32_port = to_stm32_port(port);
- unsigned int size;
- unsigned long flags;
-
/* Receiver timeout irq for DMA RX */
- if (!stm32_port->throttled) {
- spin_lock_irqsave(&port->lock, flags);
+ if (stm32_usart_rx_dma_enabled(port) && !stm32_port->throttled) {
+ spin_lock(&port->lock);
size = stm32_usart_receive_chars(port, false);
- uart_unlock_and_check_sysrq_irqrestore(port, flags);
+ uart_unlock_and_check_sysrq(port);
if (size)
tty_flip_buffer_push(tport);
}
@@ -1016,10 +1001,8 @@ static int stm32_usart_startup(struct uart_port *port)
u32 val;
int ret;
- ret = request_threaded_irq(port->irq, stm32_usart_interrupt,
- stm32_usart_threaded_interrupt,
- IRQF_ONESHOT | IRQF_NO_SUSPEND,
- name, port);
+ ret = request_irq(port->irq, stm32_usart_interrupt,
+ IRQF_NO_SUSPEND, name, port);
if (ret)
return ret;
@@ -1602,13 +1585,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
struct dma_slave_config config;
int ret;
- /*
- * Using DMA and threaded handler for the console could lead to
- * deadlocks.
- */
- if (uart_console(port))
- return -ENODEV;
-
stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L,
&stm32port->rx_dma_buf,
GFP_KERNEL);
@@ -1681,22 +1657,10 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
if (!stm32port->info)
return -EINVAL;
- ret = stm32_usart_init_port(stm32port, pdev);
- if (ret)
- return ret;
-
- if (stm32port->wakeup_src) {
- device_set_wakeup_capable(&pdev->dev, true);
- ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq);
- if (ret)
- goto err_deinit_port;
- }
-
stm32port->rx_ch = dma_request_chan(&pdev->dev, "rx");
- if (PTR_ERR(stm32port->rx_ch) == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
- goto err_wakeirq;
- }
+ if (PTR_ERR(stm32port->rx_ch) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
/* Fall back in interrupt mode for any non-deferral error */
if (IS_ERR(stm32port->rx_ch))
stm32port->rx_ch = NULL;
@@ -1710,6 +1674,17 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
if (IS_ERR(stm32port->tx_ch))
stm32port->tx_ch = NULL;
+ ret = stm32_usart_init_port(stm32port, pdev);
+ if (ret)
+ goto err_dma_tx;
+
+ if (stm32port->wakeup_src) {
+ device_set_wakeup_capable(&pdev->dev, true);
+ ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq);
+ if (ret)
+ goto err_deinit_port;
+ }
+
if (stm32port->rx_ch && stm32_usart_of_dma_rx_probe(stm32port, pdev)) {
/* Fall back in interrupt mode */
dma_release_channel(stm32port->rx_ch);
@@ -1746,19 +1721,11 @@ err_port:
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
- if (stm32port->tx_ch) {
+ if (stm32port->tx_ch)
stm32_usart_of_dma_tx_remove(stm32port, pdev);
- dma_release_channel(stm32port->tx_ch);
- }
-
if (stm32port->rx_ch)
stm32_usart_of_dma_rx_remove(stm32port, pdev);
-err_dma_rx:
- if (stm32port->rx_ch)
- dma_release_channel(stm32port->rx_ch);
-
-err_wakeirq:
if (stm32port->wakeup_src)
dev_pm_clear_wake_irq(&pdev->dev);
@@ -1768,6 +1735,14 @@ err_deinit_port:
stm32_usart_deinit_port(stm32port);
+err_dma_tx:
+ if (stm32port->tx_ch)
+ dma_release_channel(stm32port->tx_ch);
+
+err_dma_rx:
+ if (stm32port->rx_ch)
+ dma_release_channel(stm32port->rx_ch);
+
return ret;
}