FAILED: patch "[PATCH] spi: spi-zynqmp-gqspi: stop the controller on shutdown" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x e922bad8b2d5028c51a096d083fea41cd0987154
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026092228-clasp-turmoil-85b0@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e922bad8b2d5028c51a096d083fea41cd0987154 Mon Sep 17 00:00:00 2001
From: Itai Handler <[email protected]>
Date: Thu, 10 Sep 2026 20:48:32 +0300
Subject: [PATCH] spi: spi-zynqmp-gqspi: stop the controller on shutdown
The driver has no ->shutdown, and platform_drv_shutdown() has no fallback of its own. Unlike pci_device_shutdown(), which clears bus mastering when kexec_in_progress, nothing on the platform bus disarms a device that can still write to memory. The normal kexec path never calls ->suspend either, so the quiesce in zynqmp_qspi_suspend() is not reached.
A controller that is still executing a DMA read may therefore keep writing to memory across a kexec. QSPIDMA_DST_ADDR still points at memory owned by the kernel that called kexec, DST_SIZE is non-zero and the flash is still clocked, so data can keep landing in RAM while the new kernel is being relocated, and after it has started executing.
That destination is a physical address which means nothing to the new kernel, so the writes can corrupt whatever now occupies it: kernel text or data, page tables, or the initrd. Nothing reports an error and the resulting behaviour is undefined.
This can be observed by reading GQSPI_EN (offset 0x114) and QSPIDMA_DST_ADDR/SIZE/STS/CTRL (offsets 0x800 to 0x80c) early in the new kernel, before the driver probes: without this patch GQSPI_EN reads 1 and QSPIDMA_DST_ADDR still points into the previous kernel's memory.
Add a ->shutdown that stops the controller the way zynqmp_qspi_suspend() already does. spi_controller_suspend() stops the queue, waits for a message that is already executing and makes any later transfer fail with -ESHUTDOWN, so nothing can be cut short by the register write that follows. It may sleep, which is fine here: device_shutdown() runs in process context. Unlike ->suspend this cannot abort on error, because a controller left mastering the bus is worse than a truncated transfer, so a failure to drain is only logged.
GQSPI_EN_OFST is then cleared, as zynqmp_qspi_remove() and zynqmp_qspi_suspend() already do. Skip that write only when pm_runtime_get_if_in_use() returns 0, i.e. runtime suspended: the clocks are gated, so the registers are unreachable and the controller cannot be mastering the bus. A negative return is not the same thing - it is what the CONFIG_PM=n stub always returns, and there probe() has enabled pclk and refclk for good, so the controller is running and must be stopped.
drivers/spi/spi-zynqmp-gqspi.c +34 -0
@@ -1373,11 +1373,45 @@ static void zynqmp_qspi_remove(struct platform_device *pdev)clk_disable_unprepare (xqspi->pclk); } +static void zynqmp_qspi_shutdown (struct platform_device *pdev) +{ +struct zynqmp_qspi *xqspi =platform_get_drvdata (pdev); +int ret; + +/* +* Stop the queue and reject any later transfer first, so the write +* below cannot cut into a message that is still being executed. +* Unlike ->suspend this cannot abort on error: a controller left +* mastering the bus is worse than a truncated transfer. +*/ + ret =spi_controller_suspend (xqspi->ctlr); +if (ret) +dev_warn (&pdev->dev,"could not stop the queue: %d\n" , ret); + +/* +* Only a runtime suspended controller can be left alone: its clocks +* are gated, so it cannot be mastering the bus, and its registers +* must not be accessed either. Any other answer means it may be +* running and has to be stopped. In particular, on a kernel built +* without runtime PM this returns -EINVAL, and there the clocks +* enabled in probe() are never gated at all. +*/ + ret =pm_runtime_get_if_in_use (&pdev->dev); +if (!ret) +return ; + +zynqmp_gqspi_write (xqspi,GQSPI_EN_OFST ,0x0 ); + +if (ret >0 ) +pm_runtime_put_noidle (&pdev->dev); +} +MODULE_DEVICE_TABLE (of, zynqmp_qspi_of_match);static struct platform_driver zynqmp_qspi_driver = { .probe = zynqmp_qspi_probe, .remove = zynqmp_qspi_remove, + .shutdown = zynqmp_qspi_shutdown, .driver = { .name ="zynqmp-qspi" , .of_match_table = zynqmp_qspi_of_match,
PATCH 1/1 spi: spi-zynqmp-gqspi: stop the controller on shutdown
commit e922bad8b2d5028c51a096d083fea41cd0987154 upstream.
The driver has no ->shutdown, and platform_drv_shutdown() has no fallback of its own. Unlike pci_device_shutdown(), which clears bus mastering when kexec_in_progress, nothing on the platform bus disarms a device that can still write to memory. The normal kexec path never calls ->suspend either, so the quiesce in zynqmp_qspi_suspend() is not reached.
A controller that is still executing a DMA read may therefore keep writing to memory across a kexec. QSPIDMA_DST_ADDR still points at memory owned by the kernel that called kexec, DST_SIZE is non-zero and the flash is still clocked, so data can keep landing in RAM while the new kernel is being relocated, and after it has started executing.
That destination is a physical address which means nothing to the new kernel, so the writes can corrupt whatever now occupies it: kernel text or data, page tables, or the initrd. Nothing reports an error and the resulting behaviour is undefined.
This can be observed by reading GQSPI_EN (offset 0x114) and QSPIDMA_DST_ADDR/SIZE/STS/CTRL (offsets 0x800 to 0x80c) early in the new kernel, before the driver probes: without this patch GQSPI_EN reads 1 and QSPIDMA_DST_ADDR still points into the previous kernel's memory.
Add a ->shutdown that stops the controller the way zynqmp_qspi_suspend() already does. spi_controller_suspend() stops the queue, waits for a message that is already executing and makes any later transfer fail with -ESHUTDOWN, so nothing can be cut short by the register write that follows. It may sleep, which is fine here: device_shutdown() runs in process context. Unlike ->suspend this cannot abort on error, because a controller left mastering the bus is worse than a truncated transfer, so a failure to drain is only logged.
GQSPI_EN_OFST is then cleared, as zynqmp_qspi_remove() and zynqmp_qspi_suspend() already do. Skip that write only when pm_runtime_get_if_in_use() returns 0, i.e. runtime suspended: the clocks are gated, so the registers are unreachable and the controller cannot be mastering the bus. A negative return is not the same thing - it is what the CONFIG_PM=n stub always returns, and there probe() has enabled pclk and refclk for good, so the controller is running and must be stopped.
[ itai: context only - zynqmp_qspi_of_match[] still sits between
zynqmp_qspi_remove() and MODULE_DEVICE_TABLE() in this tree, hoisted to the top of the file upstream by commit 29f4d95b97bc ("spi:
spi-zynqmp-gqspi: Add tap delay support for GQSPI controller on Versal platform"), so zynqmp_qspi_shutdown() is placed above it ]
--- drivers/spi/spi-zynqmp-gqspi.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
drivers/spi/spi-zynqmp-gqspi.c +34 -0
@@ -1220,6 +1220,39 @@ static int zynqmp_qspi_remove(struct platform_device *pdev)return 0 ; } +static void zynqmp_qspi_shutdown (struct platform_device *pdev) +{ +struct zynqmp_qspi *xqspi =platform_get_drvdata (pdev); +int ret; + +/* +* Stop the queue and reject any later transfer first, so the write +* below cannot cut into a message that is still being executed. +* Unlike ->suspend this cannot abort on error: a controller left +* mastering the bus is worse than a truncated transfer. +*/ + ret =spi_controller_suspend (xqspi->ctlr); +if (ret) +dev_warn (&pdev->dev,"could not stop the queue: %d\n" , ret); + +/* +* Only a runtime suspended controller can be left alone: its clocks +* are gated, so it cannot be mastering the bus, and its registers +* must not be accessed either. Any other answer means it may be +* running and has to be stopped. In particular, on a kernel built +* without runtime PM this returns -EINVAL, and there the clocks +* enabled in probe() are never gated at all. +*/ + ret =pm_runtime_get_if_in_use (&pdev->dev); +if (!ret) +return ; + +zynqmp_gqspi_write (xqspi,GQSPI_EN_OFST ,0x0 ); + +if (ret >0 ) +pm_runtime_put_noidle (&pdev->dev); +} +static const struct of_device_id zynqmp_qspi_of_match[] = { { .compatible ="xlnx,zynqmp-qspi-1.0" , }, {/* End of table */ }
@@ -1230,6 +1263,7 @@ MODULE_DEVICE_TABLE(of, zynqmp_qspi_of_match);static struct platform_driver zynqmp_qspi_driver = { .probe = zynqmp_qspi_probe, .remove = zynqmp_qspi_remove, + .shutdown = zynqmp_qspi_shutdown, .driver = { .name ="zynqmp-qspi" , .of_match_table = zynqmp_qspi_of_match,
Signature · 1 line
2.34.1
Sasha Levin
maintainerRe: [PATCH 5.10.y] spi: spi-zynqmp-gqspi: stop the controller on shutdown
drivers/spi/spi-zynqmp-gqspi.c static int zynqmp_qspi_remove(struct platform_device *pdev) · line 1250
Quoted 5 lines
drivers/spi/spi-zynqmp-gqspi.c +5
-0+ ret =pm_runtime_get_if_in_use (&pdev->dev); +if (!ret) +return ; + +zynqmp_gqspi_write (xqspi,GQSPI_EN_OFST ,0x0 );
On 5.10 with CONFIG_PM=y this check always returns early, so GQSPI_EN is never cleared and the kexec DMA corruption is not fixed there.
5.10 picked up 58eaa7b2d07d ("spi: spi-zynqmp-gqspi: Fix runtime PM imbalance in zynqmp_qspi_probe") and then reverted it in 5.10.199 with 1ceaf0d3a883 ("Revert "spi: spi-zynqmp-gqspi: Fix runtime PM imbalance in zynqmp_qspi_probe""). Probe therefore ends with a pm_runtime_put_autosuspend() that has no matching get, leaving usage_count at -1. device_shutdown()'s pm_runtime_get_noresume() brings it back to 0, and pm_runtime_get_if_in_use() then returns 0 whether the controller is active or runtime suspended.
Could you send a 5.10 v2 that clears GQSPI_EN unconditionally, as 5.10's zynqmp_qspi_remove() and zynqmp_qspi_suspend() already do?
Signature · 2 lines
Thanks, Sasha
Re: [PATCH 5.10.y] spi: spi-zynqmp-gqspi: stop the controller on shutdown
Quoted 18 lines · Sasha Levin
drivers/spi/spi-zynqmp-gqspi.c static int zynqmp_qspi_remove(struct platform_device *pdev) · line 1250
Quoted 6 lines
drivers/spi/spi-zynqmp-gqspi.c +5
-0+ ret =pm_runtime_get_if_in_use (&pdev->dev); +if (!ret) +return ; + +zynqmp_gqspi_write (xqspi,GQSPI_EN_OFST ,0x0 );On 5.10 with
CONFIG_PM=ythis check always returns early, soGQSPI_ENis never cleared and the kexec DMA corruption is not fixed there.5.10 picked up
58eaa7b2d07d("spi: spi-zynqmp-gqspi: Fix runtime PM imbalance inzynqmp_qspi_probe") and then reverted it in 5.10.199 with1ceaf0d3a883("Revert "spi: spi-zynqmp-gqspi: Fix runtime PM imbalance inzynqmp_qspi_probe""). Probe therefore ends with apm_runtime_put_autosuspend()that has no matching get, leavingusage_countat -1. device_shutdown()'spm_runtime_get_noresume()brings it back to 0, andpm_runtime_get_if_in_use()then returns 0 whether the controller is active or runtime suspended.
Quoted 2 lines
Could you send a 5.10 v2 that clears
GQSPI_ENunconditionally, as 5.10'szynqmp_qspi_remove()andzynqmp_qspi_suspend()already do?
Thanks for looking into this.
I agree with your analysis of the 5.10 runtime-PM state: because of the probe-time runtime-PM imbalance, pm_runtime_get_if_in_use() cannot be used reliably in this path on 5.10.
However, I don't think we should change the backport to unconditionally write GQSPI_EN. The upstream patch intentionally avoids accessing the GQSPI registers when the controller is runtime-suspended, since its clocks are then disabled.
I'd also prefer not to introduce different runtime-PM/MMIO logic in the 5.10 backport just to work around the 5.10-specific usage_count issue.
I suggest dropping this backport for now and first fixing the runtime-PM logic in the 5.10 tree. Once that is fixed, we can revisit the GQSPI shutdown patch and backport it with the same runtime-PM logic as upstream.
This also avoids potentially accessing the GQSPI register block while the controller is runtime-suspended.
If that sounds reasonable, let's drop the 5.10 backport for now.
Thanks,
Itai
Sasha Levin
maintainerRe: [PATCH 5.10.y] spi: spi-zynqmp-gqspi: stop the controller on shutdown
Quoted 4 lines
I suggest dropping this backport for now and first fixing the runtime-PM logic in the 5.10 tree. Once that is fixed, we can revisit the GQSPI shutdown patch and backport it with the same runtime-PM logic as upstream.
Agreed. 5.10 stays without it for now.
Signature · 2 lines
Thanks, Sasha