This is a note to let you know that I've just added the patch titled serial: 8250_bcm7271: Fix arbitration handling to the 6.2-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: serial-8250_bcm7271-fix-arbitration-handling.patch and it can be found in the queue-6.2 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 975898381a400cb641add649ad016b2c9533bc44 Author: Doug Berger <opendmb@xxxxxxxxx> Date: Thu Mar 9 11:02:24 2023 -0800 serial: 8250_bcm7271: Fix arbitration handling [ Upstream commit 15ac1122fd6d4bf408a03e6f23c7ad4f60b22f9e ] The arbitration of the UART DMA is mishandled for a few exceptional cases when probing and releasing the driver. It is possible that the DMA register spaces are not defined in device tree for an instance of the driver, so attempts to access the registers in brcmuart_arbitration() would use NULL pointers. It is also possible for the probe function to return an error while still holding the UART DMA. This would prevent the UART DMA from being claimed by an instance that could use it. These errors are addressed by only releasing the UART DMA if it is held by this instance (i.e. priv->dma_enabled == 1) and directing early error paths in probe to this common release_dma handling. Fixes: 41a469482de2 ("serial: 8250: Add new 8250-core based Broadcom STB driver") Signed-off-by: Doug Berger <opendmb@xxxxxxxxx> Acked-by: Florian Fainelli <f.fainelli@xxxxxxxxx> Link: https://lore.kernel.org/r/20230309190224.687380-1-opendmb@xxxxxxxxx Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c index ed5a947476920..f801b1f5b46c0 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -1014,14 +1014,16 @@ static int brcmuart_probe(struct platform_device *pdev) /* See if a Baud clock has been specified */ baud_mux_clk = of_clk_get_by_name(np, "sw_baud"); if (IS_ERR(baud_mux_clk)) { - if (PTR_ERR(baud_mux_clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; + if (PTR_ERR(baud_mux_clk) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto release_dma; + } dev_dbg(dev, "BAUD MUX clock not specified\n"); } else { dev_dbg(dev, "BAUD MUX clock found\n"); ret = clk_prepare_enable(baud_mux_clk); if (ret) - return ret; + goto release_dma; priv->baud_mux_clk = baud_mux_clk; init_real_clk_rates(dev, priv); clk_rate = priv->default_mux_rate; @@ -1029,7 +1031,8 @@ static int brcmuart_probe(struct platform_device *pdev) if (clk_rate == 0) { dev_err(dev, "clock-frequency or clk not defined\n"); - return -EINVAL; + ret = -EINVAL; + goto release_dma; } dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not "); @@ -1116,7 +1119,9 @@ static int brcmuart_probe(struct platform_device *pdev) serial8250_unregister_port(priv->line); err: brcmuart_free_bufs(dev, priv); - brcmuart_arbitration(priv, 0); +release_dma: + if (priv->dma_enabled) + brcmuart_arbitration(priv, 0); return ret; } @@ -1128,7 +1133,8 @@ static int brcmuart_remove(struct platform_device *pdev) hrtimer_cancel(&priv->hrt); serial8250_unregister_port(priv->line); brcmuart_free_bufs(&pdev->dev, priv); - brcmuart_arbitration(priv, 0); + if (priv->dma_enabled) + brcmuart_arbitration(priv, 0); return 0; }