From db86bb6ed4979ed8a987057f9098ea88f85e48be Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 8 May 2023 11:20:14 +0300 Subject: [PATCH] serial: 8250: omap: Shut down on remove for console uart 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 Link: https://lore.kernel.org/r/20230508082014.23083-5-tony@atomide.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index bf57e32..5c093df 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -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); -- 2.7.4