* [PATCH v3 0/2] PCI: qcom: Implement shutdown() to avoid SMMU/NoC errors on reboot
@ 2026-08-24 5:34 Krishna Chaitanya Chundru
2026-08-24 5:34 ` [PATCH v3 1/2] PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check Krishna Chaitanya Chundru
2026-08-24 5:35 ` [PATCH v3 2/2] PCI: qcom: Implement shutdown() callback Krishna Chaitanya Chundru
0 siblings, 2 replies; 6+ messages in thread
From: Krishna Chaitanya Chundru @ 2026-08-24 5:34 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas
Cc: linux-pci, linux-kernel, linux-arm-msm, Krishna Chaitanya Chundru,
Manivannan Sadhasivam
During system shutdown/reboot, power/clocks to the PCIe controller get
removed regardless of link state. If the link is still up when that
happens, it can trigger SMMU or NoC errors.
This series adds a shutdown() callback to the Qualcomm PCIe host driver
that forces the link into L2/D3cold before shutdown proceeds, reusing
the existing suspend_noirq() path.
Patch 1 makes dw_pcie_suspend_noirq() skip the D3cold capability check
during shutdown/reboot, since that check can fail and leave the link up
if any endpoint hasn't suspended yet.
Patch 2 adds qcom_pcie_shutdown() and wires it up as .shutdown.
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
---
Changes in v3:
- Added null point check and use pm_runtime_put_sync (Sashiko).
- Link to v2: https://patch.msgid.link/20260822-shutdown-v2-0-520a68f1b4a5@oss.qualcomm.com
Changes in v2:
1) don't remove the endpoint pci dev's only keep link in D3cold.
Link to v1: https://lore.kernel.org/all/20250401-shutdown-v1-1-f699859403ae@oss.qualcomm.com/
---
Krishna Chaitanya Chundru (1):
PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check
Manivannan Sadhasivam (1):
PCI: qcom: Implement shutdown() callback
drivers/pci/controller/dwc/pcie-designware-host.c | 18 ++++++++++++++++--
drivers/pci/controller/dwc/pcie-qcom.c | 12 ++++++++++++
2 files changed, 28 insertions(+), 2 deletions(-)
---
base-commit: c1366b72ad4e87be60b57b74635a3a0bc58d2b0b
change-id: 20260822-shutdown-fe8139dff2b7
Best regards,
--
Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v3 1/2] PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check
2026-08-24 5:34 [PATCH v3 0/2] PCI: qcom: Implement shutdown() to avoid SMMU/NoC errors on reboot Krishna Chaitanya Chundru
@ 2026-08-24 5:34 ` Krishna Chaitanya Chundru
2026-08-24 5:52 ` sashiko-bot
2026-08-24 6:42 ` Konrad Dybcio
2026-08-24 5:35 ` [PATCH v3 2/2] PCI: qcom: Implement shutdown() callback Krishna Chaitanya Chundru
1 sibling, 2 replies; 6+ messages in thread
From: Krishna Chaitanya Chundru @ 2026-08-24 5:34 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas
Cc: linux-pci, linux-kernel, linux-arm-msm, Krishna Chaitanya Chundru
dw_pcie_suspend_noirq() normally calls pci_host_common_d3cold_possible()
to check whether every downstream endpoint can be put into D3cold before
bothering to move the link to L2. If no endpoint supports it, the
function returns early and leaves the link up.
Querying D3cold support during shutdown is actively harmful, not just
slow: pci_host_common_d3cold_possible() requires every active endpoint
to already be in PCI_D3hot, and returns false otherwise. If any endpoint
is still in D0 -- which is common, since endpoint drivers aren't
guaranteed to have suspended by the time the host's shutdown path runs
the check fails and dw_pcie_suspend_noirq() returns early without ever
moving the link to L2, leaving it up right up to the point where the
system cuts power/clocks to the controller.
Detect the shutdown/reboot case via system_state and skip straight to
forcing the link into L2, the same sequence used for the D3cold-capable
case.
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
---
drivers/pci/controller/dwc/pcie-designware-host.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 06722259d2e3..98cd9dd2c7d7 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -13,6 +13,7 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/irqchip/irq-msi-lib.h>
#include <linux/irqdomain.h>
+#include <linux/kernel.h>
#include <linux/msi.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
@@ -1222,16 +1223,29 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
int dw_pcie_suspend_noirq(struct dw_pcie *pci)
{
- bool pme_capable = false;
+ bool shutdown = system_state == SYSTEM_HALT ||
+ system_state == SYSTEM_POWER_OFF ||
+ system_state == SYSTEM_RESTART;
+ bool d3cold, pme_capable = false;
int ret = 0;
u32 val;
if (!dw_pcie_link_up(pci))
goto stop_link;
- if (!pci_host_common_d3cold_possible(pci->pp.bridge, &pme_capable))
+ /*
+ * During reboot/halt/poweroff the link is going away regardless, so
+ * force L2 entry without checking whether endpoints have transitioned
+ * to D3hot -- there's no point walking the bus to find out.
+ */
+ if (shutdown)
+ goto d3cold;
+
+ d3cold = pci_host_common_d3cold_possible(pci->pp.bridge, &pme_capable);
+ if (!d3cold)
return 0;
+d3cold:
if (pci->pp.ops->pme_turn_off) {
pci->pp.ops->pme_turn_off(&pci->pp);
} else {
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v3 1/2] PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check
2026-08-24 5:34 ` [PATCH v3 1/2] PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check Krishna Chaitanya Chundru
@ 2026-08-24 5:52 ` sashiko-bot
2026-08-24 6:42 ` Konrad Dybcio
1 sibling, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-08-24 5:52 UTC (permalink / raw)
To: Krishna Chaitanya Chundru; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Forcing PME_Turn_Off and cutting VAUX during shutdown unconditionally violates the PCIe Base Specification and breaks S5 Wake-on-LAN.
--
--- Patch [1]: [PATCH v3 1/2] PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check ---
commit a2c00716f7d3b58c02f9dc631c72c6f185e30be1
Author: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check
This commit modifies dw_pcie_suspend_noirq() to bypass the D3cold
capability check during shutdown or reboot. It unconditionally forces
the link into L2 state to avoid delays or failures when endpoints are
still in D0.
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index 06722259d2e37..98cd9dd2c7d79 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
[ ... ]
> @@ -1222,16 +1223,29 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
>
> int dw_pcie_suspend_noirq(struct dw_pcie *pci)
> {
> - bool pme_capable = false;
> + bool shutdown = system_state == SYSTEM_HALT ||
> + system_state == SYSTEM_POWER_OFF ||
> + system_state == SYSTEM_RESTART;
> + bool d3cold, pme_capable = false;
> int ret = 0;
> u32 val;
>
> if (!dw_pcie_link_up(pci))
> goto stop_link;
>
> - if (!pci_host_common_d3cold_possible(pci->pp.bridge, &pme_capable))
> + /*
> + * During reboot/halt/poweroff the link is going away regardless, so
> + * force L2 entry without checking whether endpoints have transitioned
> + * to D3hot -- there's no point walking the bus to find out.
> + */
> + if (shutdown)
> + goto d3cold;
[Severity: High]
Does skipping the D3hot verification and jumping straight to d3cold cause
the controller to broadcast a PME_Turn_Off message to endpoints that might
still be in D0?
Section 5.3.3.2.1 of the PCIe Base Specification mandates that all downstream
devices must be in D3hot or D3cold before software sends this message.
Also, since jumping to d3cold skips the call to
pci_host_common_d3cold_possible(), pme_capable remains false. Will this
cause the driver to incorrectly set skip_pwrctrl_off to false later in the
function:
stop_link:
...
pci->pp.skip_pwrctrl_off = pme_capable;
and unconditionally cut Vaux power to the bus, breaking S5 wake-on-LAN for
devices that were prepared for S5 wakeup?
> +
> + d3cold = pci_host_common_d3cold_possible(pci->pp.bridge, &pme_capable);
> + if (!d3cold)
> return 0;
>
> +d3cold:
> if (pci->pp.ops->pme_turn_off) {
> pci->pp.ops->pme_turn_off(&pci->pp);
> } else {
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260824-shutdown-v3-0-81c14bb7a1af@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH v3 1/2] PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check
2026-08-24 5:34 ` [PATCH v3 1/2] PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check Krishna Chaitanya Chundru
2026-08-24 5:52 ` sashiko-bot
@ 2026-08-24 6:42 ` Konrad Dybcio
1 sibling, 0 replies; 6+ messages in thread
From: Konrad Dybcio @ 2026-08-24 6:42 UTC (permalink / raw)
To: Krishna Chaitanya Chundru, Jingoo Han, Manivannan Sadhasivam,
Lorenzo Pieralisi, Krzysztof Wilczyński, Rob Herring,
Bjorn Helgaas
Cc: linux-pci, linux-kernel, linux-arm-msm
On 8/24/26 7:34 AM, Krishna Chaitanya Chundru wrote:
> dw_pcie_suspend_noirq() normally calls pci_host_common_d3cold_possible()
> to check whether every downstream endpoint can be put into D3cold before
> bothering to move the link to L2. If no endpoint supports it, the
> function returns early and leaves the link up.
[...]
> int dw_pcie_suspend_noirq(struct dw_pcie *pci)
> {
> - bool pme_capable = false;
> + bool shutdown = system_state == SYSTEM_HALT ||
> + system_state == SYSTEM_POWER_OFF ||
> + system_state == SYSTEM_RESTART;
> + bool d3cold, pme_capable = false;
> int ret = 0;
> u32 val;
>
> if (!dw_pcie_link_up(pci))
> goto stop_link;
>
> - if (!pci_host_common_d3cold_possible(pci->pp.bridge, &pme_capable))
> + /*
> + * During reboot/halt/poweroff the link is going away regardless, so
> + * force L2 entry without checking whether endpoints have transitioned
> + * to D3hot -- there's no point walking the bus to find out.
> + */
> + if (shutdown)
> + goto d3cold;
> +
> + d3cold = pci_host_common_d3cold_possible(pci->pp.bridge, &pme_capable);
> + if (!d3cold)
> return 0;
>
> +d3cold:
I don't really see why we need a goto here, and I especially don't like
that the label is named the same as a nearby local variable.
Can the check above be simply changed to "if (!d3cold && !shutdown)"?
Konrad
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 2/2] PCI: qcom: Implement shutdown() callback
2026-08-24 5:34 [PATCH v3 0/2] PCI: qcom: Implement shutdown() to avoid SMMU/NoC errors on reboot Krishna Chaitanya Chundru
2026-08-24 5:34 ` [PATCH v3 1/2] PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check Krishna Chaitanya Chundru
@ 2026-08-24 5:35 ` Krishna Chaitanya Chundru
2026-08-24 5:45 ` sashiko-bot
1 sibling, 1 reply; 6+ messages in thread
From: Krishna Chaitanya Chundru @ 2026-08-24 5:35 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas
Cc: linux-pci, linux-kernel, linux-arm-msm, Krishna Chaitanya Chundru,
Manivannan Sadhasivam
From: Manivannan Sadhasivam <mani@kernel.org>
PCIe host controllers should bring the link down cleanly before system
shutdown/reboot proceeds to remove power/clocks from the controller.
Without this, the link may still be up and endpoints still have
transactions in flight when power/clocks are cut, which can trip SMMU
translation faults or NoC protocol errors.
Reuse dw_pcie_suspend_noirq() in the shutdown path to force the link
into L2, putting it into D3cold.
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
---
drivers/pci/controller/dwc/pcie-qcom.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index d8eb52857f69..a4284c64de27 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -2156,6 +2156,17 @@ static int qcom_pcie_probe(struct platform_device *pdev)
return ret;
}
+static void qcom_pcie_shutdown(struct platform_device *pdev)
+{
+ struct qcom_pcie *pcie = platform_get_drvdata(pdev);
+
+ if (pcie)
+ dw_pcie_suspend_noirq(pcie->pci);
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+}
+
static int qcom_pcie_suspend_noirq(struct device *dev)
{
struct qcom_pcie *pcie;
@@ -2337,5 +2348,6 @@ static struct platform_driver qcom_pcie_driver = {
.pm = &qcom_pcie_pm_ops,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
+ .shutdown = qcom_pcie_shutdown,
};
builtin_platform_driver(qcom_pcie_driver);
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v3 2/2] PCI: qcom: Implement shutdown() callback
2026-08-24 5:35 ` [PATCH v3 2/2] PCI: qcom: Implement shutdown() callback Krishna Chaitanya Chundru
@ 2026-08-24 5:45 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-08-24 5:45 UTC (permalink / raw)
To: Krishna Chaitanya Chundru; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Reusing a `_noirq` suspend callback in the shutdown path without disabling interrupts creates a race condition that can cause a fatal synchronous external abort.
--
--- Patch [2]: [PATCH v3 2/2] PCI: qcom: Implement shutdown() callback ---
commit fddc2f7864ce1c4c291d73453690c4721638afe0
Author: Manivannan Sadhasivam <mani@kernel.org>
PCI: qcom: Implement shutdown() callback
This commit introduces a shutdown callback for the Qualcomm PCIe
controller. It reuses dw_pcie_suspend_noirq() to cleanly bring down
the PCIe link before system power and clocks are cut during shutdown
or reboot.
> diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
> index d8eb52857f69c..a4284c64de276 100644
> --- a/drivers/pci/controller/dwc/pcie-qcom.c
> +++ b/drivers/pci/controller/dwc/pcie-qcom.c
[ ... ]
> @@ -2156,6 +2156,17 @@ static int qcom_pcie_probe(struct platform_device *pdev)
> return ret;
> }
>
> +static void qcom_pcie_shutdown(struct platform_device *pdev)
> +{
> + struct qcom_pcie *pcie = platform_get_drvdata(pdev);
> +
> + if (pcie)
> + dw_pcie_suspend_noirq(pcie->pci);
[Severity: High]
Does reusing dw_pcie_suspend_noirq() here without disabling device interrupts
create a race condition that can cause a fatal synchronous external abort?
The device_shutdown() phase runs with interrupts enabled. The suspend_noirq
hardware teardown sequence eventually disables the PCIe clocks and PHY.
If a PCIe MSI or spurious interrupt fires after the clocks are disabled but
before the system finishes rebooting, the chained IRQ handler might attempt
to read powered-off hardware registers, resulting in a fatal bus fault.
> +
> + pm_runtime_put_sync(&pdev->dev);
> + pm_runtime_disable(&pdev->dev);
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260824-shutdown-v3-0-81c14bb7a1af@oss.qualcomm.com?part=2
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-24 6:42 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24 5:34 [PATCH v3 0/2] PCI: qcom: Implement shutdown() to avoid SMMU/NoC errors on reboot Krishna Chaitanya Chundru
2026-08-24 5:34 ` [PATCH v3 1/2] PCI: dwc: Force L2 link entry on shutdown/reboot without D3cold check Krishna Chaitanya Chundru
2026-08-24 5:52 ` sashiko-bot
2026-08-24 6:42 ` Konrad Dybcio
2026-08-24 5:35 ` [PATCH v3 2/2] PCI: qcom: Implement shutdown() callback Krishna Chaitanya Chundru
2026-08-24 5:45 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox