Patch "spi: qup: Request DMA before enabling clocks" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    spi: qup: Request DMA before enabling clocks

to the 6.1-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:
     spi-qup-request-dma-before-enabling-clocks.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 74d75789c1ddf36e4dd0e5e4f7d9ee1e7fbe7401
Author: Stephan Gerhold <stephan@xxxxxxxxxxx>
Date:   Thu May 18 15:04:25 2023 +0200

    spi: qup: Request DMA before enabling clocks
    
    [ Upstream commit 0c331fd1dccfba657129380ee084b95c1cedfbef ]
    
    It is usually better to request all necessary resources (clocks,
    regulators, ...) before starting to make use of them. That way they do
    not change state in case one of the resources is not available yet and
    probe deferral (-EPROBE_DEFER) is necessary. This is particularly
    important for DMA channels and IOMMUs which are not enforced by
    fw_devlink yet (unless you use fw_devlink.strict=1).
    
    spi-qup does this in the wrong order, the clocks are enabled and
    disabled again when the DMA channels are not available yet.
    
    This causes issues in some cases: On most SoCs one of the SPI QUP
    clocks is shared with the UART controller. When using earlycon UART is
    actively used during boot but might not have probed yet, usually for
    the same reason (waiting for the DMA controller). In this case, the
    brief enable/disable cycle ends up gating the clock and further UART
    console output will halt the system completely.
    
    Avoid this by requesting the DMA channels before changing the clock
    state.
    
    Fixes: 612762e82ae6 ("spi: qup: Add DMA capabilities")
    Signed-off-by: Stephan Gerhold <stephan@xxxxxxxxxxx>
    Link: https://lore.kernel.org/r/20230518-spi-qup-clk-defer-v1-1-f49fc9ca4e02@xxxxxxxxxxx
    Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
index 205e54f157b4a..fb6b7738b4f55 100644
--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -1029,23 +1029,8 @@ static int spi_qup_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
-	ret = clk_prepare_enable(cclk);
-	if (ret) {
-		dev_err(dev, "cannot enable core clock\n");
-		return ret;
-	}
-
-	ret = clk_prepare_enable(iclk);
-	if (ret) {
-		clk_disable_unprepare(cclk);
-		dev_err(dev, "cannot enable iface clock\n");
-		return ret;
-	}
-
 	master = spi_alloc_master(dev, sizeof(struct spi_qup));
 	if (!master) {
-		clk_disable_unprepare(cclk);
-		clk_disable_unprepare(iclk);
 		dev_err(dev, "cannot allocate master\n");
 		return -ENOMEM;
 	}
@@ -1093,6 +1078,19 @@ static int spi_qup_probe(struct platform_device *pdev)
 	spin_lock_init(&controller->lock);
 	init_completion(&controller->done);
 
+	ret = clk_prepare_enable(cclk);
+	if (ret) {
+		dev_err(dev, "cannot enable core clock\n");
+		goto error_dma;
+	}
+
+	ret = clk_prepare_enable(iclk);
+	if (ret) {
+		clk_disable_unprepare(cclk);
+		dev_err(dev, "cannot enable iface clock\n");
+		goto error_dma;
+	}
+
 	iomode = readl_relaxed(base + QUP_IO_M_MODES);
 
 	size = QUP_IO_M_OUTPUT_BLOCK_SIZE(iomode);
@@ -1122,7 +1120,7 @@ static int spi_qup_probe(struct platform_device *pdev)
 	ret = spi_qup_set_state(controller, QUP_STATE_RESET);
 	if (ret) {
 		dev_err(dev, "cannot set RESET state\n");
-		goto error_dma;
+		goto error_clk;
 	}
 
 	writel_relaxed(0, base + QUP_OPERATIONAL);
@@ -1146,7 +1144,7 @@ static int spi_qup_probe(struct platform_device *pdev)
 	ret = devm_request_irq(dev, irq, spi_qup_qup_irq,
 			       IRQF_TRIGGER_HIGH, pdev->name, controller);
 	if (ret)
-		goto error_dma;
+		goto error_clk;
 
 	pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
 	pm_runtime_use_autosuspend(dev);
@@ -1161,11 +1159,12 @@ static int spi_qup_probe(struct platform_device *pdev)
 
 disable_pm:
 	pm_runtime_disable(&pdev->dev);
+error_clk:
+	clk_disable_unprepare(cclk);
+	clk_disable_unprepare(iclk);
 error_dma:
 	spi_qup_release_dma(master);
 error:
-	clk_disable_unprepare(cclk);
-	clk_disable_unprepare(iclk);
 	spi_master_put(master);
 	return ret;
 }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux