serial: 8250: omap: Shut down on remove for console uart
authorTony Lindgren <tony@atomide.com>
Mon, 8 May 2023 08:20:14 +0000 (11:20 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 13 May 2023 10:33:56 +0000 (19:33 +0900)
When unbinding the console uart, we want to power down the uart hardware
on remove. For the console uart, the normal shutdown path will never get
called as the cons_filp stays open. Let's rearrange the dma related
functions a bit so we can call driver shutdown also on console uart rebind.

Currently we set up->dma on probe, but that causes issues calling
omap_8250_shutdown() on remove. The dma startup will not get called on
the next rebind as we still have up->dma set from probe.

Note that serial8250_release_dma() already checks for dma so we can
remove the check for it in 8205_omap driver.

With these changes we also avoid hogging dma virtual channels for the
unused uarts that may be limited on some devices.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Link: https://lore.kernel.org/r/20230508082014.23083-5-tony@atomide.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/8250/8250_omap.c

index bf57e32..5c093df 100644 (file)
@@ -679,6 +679,7 @@ static int omap_8250_startup(struct uart_port *port)
 {
        struct uart_8250_port *up = up_to_u8250p(port);
        struct omap8250_priv *priv = port->private_data;
+       struct uart_8250_dma *dma = &priv->omap8250_dma;
        int ret;
 
        if (priv->wakeirq) {
@@ -697,16 +698,16 @@ static int omap_8250_startup(struct uart_port *port)
        up->msr_saved_flags = 0;
 
        /* Disable DMA for console UART */
-       if (uart_console(port))
-               up->dma = NULL;
-
-       if (up->dma) {
+       if (dma->fn && !uart_console(port)) {
+               up->dma = &priv->omap8250_dma;
                ret = serial8250_request_dma(up);
                if (ret) {
                        dev_warn_ratelimited(port->dev,
                                             "failed to request DMA\n");
                        up->dma = NULL;
                }
+       } else {
+               up->dma = NULL;
        }
 
        up->ier = UART_IER_RLSI | UART_IER_RDI;
@@ -752,8 +753,8 @@ static void omap_8250_shutdown(struct uart_port *port)
        disable_irq_nosync(up->port.irq);
        dev_pm_clear_wake_irq(port->dev);
 
-       if (up->dma)
-               serial8250_release_dma(up);
+       serial8250_release_dma(up);
+       up->dma = NULL;
 
        /*
         * Disable break condition and FIFOs
@@ -1499,24 +1500,24 @@ static int omap8250_probe(struct platform_device *pdev)
        ret = of_property_count_strings(np, "dma-names");
        if (ret == 2) {
                struct omap8250_dma_params *dma_params = NULL;
+               struct uart_8250_dma *dma = &priv->omap8250_dma;
 
-               up.dma = &priv->omap8250_dma;
-               up.dma->fn = the_no_dma_filter_fn;
-               up.dma->tx_dma = omap_8250_tx_dma;
-               up.dma->rx_dma = omap_8250_rx_dma;
+               dma->fn = the_no_dma_filter_fn;
+               dma->tx_dma = omap_8250_tx_dma;
+               dma->rx_dma = omap_8250_rx_dma;
                if (pdata)
                        dma_params = pdata->dma_params;
 
                if (dma_params) {
-                       up.dma->rx_size = dma_params->rx_size;
-                       up.dma->rxconf.src_maxburst = dma_params->rx_trigger;
-                       up.dma->txconf.dst_maxburst = dma_params->tx_trigger;
+                       dma->rx_size = dma_params->rx_size;
+                       dma->rxconf.src_maxburst = dma_params->rx_trigger;
+                       dma->txconf.dst_maxburst = dma_params->tx_trigger;
                        priv->rx_trigger = dma_params->rx_trigger;
                        priv->tx_trigger = dma_params->tx_trigger;
                } else {
-                       up.dma->rx_size = RX_TRIGGER;
-                       up.dma->rxconf.src_maxburst = RX_TRIGGER;
-                       up.dma->txconf.dst_maxburst = TX_TRIGGER;
+                       dma->rx_size = RX_TRIGGER;
+                       dma->rxconf.src_maxburst = RX_TRIGGER;
+                       dma->txconf.dst_maxburst = TX_TRIGGER;
                }
        }
 #endif
@@ -1550,12 +1551,15 @@ err:
 static int omap8250_remove(struct platform_device *pdev)
 {
        struct omap8250_priv *priv = platform_get_drvdata(pdev);
+       struct uart_8250_port *up;
        int err;
 
        err = pm_runtime_resume_and_get(&pdev->dev);
        if (err)
                return err;
 
+       up = serial8250_get_port(priv->line);
+       omap_8250_shutdown(&up->port);
        serial8250_unregister_port(priv->line);
        priv->line = -ENODEV;
        pm_runtime_dont_use_autosuspend(&pdev->dev);