* [PATCH v6 0/3] Add root port reset to support link recovery
@ 2026-06-03 6:25 hongxing.zhu
2026-06-03 6:25 ` [PATCH v6 1/3] dt-bindings: imx6q-pcie: Add optional intr/aer/pme interrupts for i.MX95 hongxing.zhu
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: hongxing.zhu @ 2026-06-03 6:25 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel
Based on the following patch-set[1] issued by Mani.
Add support for resetting the Root Port for i.MX PCIe to enable link recovery.
[1] [PATCH v8 0/5] PCI: Add support for resetting the Root Ports in a platform specific way
PCIe links can go down due to various unexpected circumstances. This patch series
adds root port reset support for link recovery on i.MX PCIe controllers when the
optional "intr" interrupt is present.
When a link down event is detected, the root port reset uninitializes and
reinitializes the PCIe controller, then restarts the PCIe link.
On i.MX95 platforms, link events and PME share the same interrupt line.
Link event interrupts cannot use only an IRQ thread handler because the PME
driver uses request_irq() to bind the PME interrupt directly with only the
IRQF_SHARED flag set.
To address this, we register one handler with IRQF_SHARED for link event
interrupts and manipulate the enable bits of link events to ensure the same
interrupt source is triggered only once at a time.
Additionally, this series adds 'intr', 'aer', and 'pme' interrupt entries to
the i.MX6Q PCIe binding to support PCIe event-based interrupts for general
controller events, Advanced Error Reporting, and Power Management Events
respectively.
Changes in v6:
- Use conditional constraints (if/then schema) to specify that these three
optional interrupts are only valid for the i.MX95 variant, while other
variants like imx6q should not have them.
- Change lnk_intr data type from u32 to int to properly handle negative
error codes returned by platform_get_irq_byname_optional().
- Replace platform_get_irq_byname() with platform_get_irq_byname_optional()
to suppress unnecessary error messages when the optional link event IRQ is
not present in the device tree.
- To avoid inadvertently clear the pending W1C status bit, clear the W1C
bit firstly, then do the regmap_clear_bits().
Changes in v5:
- Update the commit message of the first dt-binding patch for clarity.
- Add explicit comment explaining that writing 1 to IMX95_LINK_DOWN_INT_STS
clears the bit
Changes in v4:
- Set these new added three interrupts as optional interrupt.
Changes in v3:
- Don't add a new if:block; Drop the maxItems constraint of the interrupts
property for i.MX95 PCIe.
- Add constraints for the interrupts property for other variants.
- Regarding the ABI break: add descriptions explaining why these new
interrupts are mandatory and required by i.MX95 PCIe.
Changes in v2:
- Constrain the new added three interrupt entries to be valid only for the
i.MX95 variant using conditional schemas
[PATCH v6 1/3] dt-bindings: imx6q-pcie: Add optional intr/aer/pme
[PATCH v6 2/3] arm64: dts: imx95: Add dma, intr, aer and pme
[PATCH v6 3/3] PCI: imx6: Add root port reset to support link
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml | 29 +++++++++++++++++++++
arch/arm64/boot/dts/freescale/imx95.dtsi | 16 +++++++++---
drivers/pci/controller/dwc/pci-imx6.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+), 4 deletions(-)
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v6 1/3] dt-bindings: imx6q-pcie: Add optional intr/aer/pme interrupts for i.MX95
2026-06-03 6:25 [PATCH v6 0/3] Add root port reset to support link recovery hongxing.zhu
@ 2026-06-03 6:25 ` hongxing.zhu
2026-06-03 6:25 ` [PATCH v6 2/3] arm64: dts: imx95: Add dma, intr, aer and pme interrupts for PCIe hongxing.zhu
2026-06-03 6:25 ` [PATCH v6 3/3] PCI: imx6: Add root port reset to support link recovery hongxing.zhu
2 siblings, 0 replies; 6+ messages in thread
From: hongxing.zhu @ 2026-06-03 6:25 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel,
Richard Zhu, Frank Li
From: Richard Zhu <hongxing.zhu@nxp.com>
The i.MX95 PCIe controller introduces three additional dedicated hardware
interrupt lines for specific events:
- intr: general controller events
- aer: Advanced Error Reporting events
- pme: Power Management Events
These interrupts are optional on i.MX95. PCIe basic functionality
(enumeration, configuration, and data transfer) works correctly without
them, as the controller can operate using only the existing msi interrupt.
Earlier i.MX PCIe variants (imx6q, imx6sx, imx6qp, imx7d, imx8mm, imx8mp,
imx8mq, imx8q) do not have these three dedicated interrupt lines.
Update the binding to allow up to 5 interrupts for i.MX95, while
restricting earlier variants to a maximum of 2 interrupts using
conditional constraints (if/then schema). This ensures the schema
accurately reflects the hardware capabilities of each SoC variant.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
.../bindings/pci/fsl,imx6q-pcie.yaml | 29 +++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
index e8b8131f5f23..9b5d4e59dfff 100644
--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
@@ -58,12 +58,18 @@ properties:
items:
- description: builtin MSI controller.
- description: builtin DMA controller.
+ - description: PCIe event interrupt.
+ - description: builtin AER SPI standalone interrupt line.
+ - description: builtin PME SPI standalone interrupt line.
interrupt-names:
minItems: 1
items:
- const: msi
- const: dma
+ - const: intr
+ - const: aer
+ - const: pme
reset-gpio:
deprecated: true
@@ -248,6 +254,29 @@ allOf:
- const: pcie_aux
- const: ref
- const: extref # Optional
+ interrupts:
+ maxItems: 5
+ interrupt-names:
+ maxItems: 5
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - fsl,imx6q-pcie
+ - fsl,imx6sx-pcie
+ - fsl,imx6qp-pcie
+ - fsl,imx7d-pcie
+ - fsl,imx8mm-pcie
+ - fsl,imx8mp-pcie
+ - fsl,imx8mq-pcie
+ - fsl,imx8q-pcie
+ then:
+ properties:
+ interrupts:
+ maxItems: 2
+ interrupt-names:
+ maxItems: 2
unevaluatedProperties: false
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 2/3] arm64: dts: imx95: Add dma, intr, aer and pme interrupts for PCIe
2026-06-03 6:25 [PATCH v6 0/3] Add root port reset to support link recovery hongxing.zhu
2026-06-03 6:25 ` [PATCH v6 1/3] dt-bindings: imx6q-pcie: Add optional intr/aer/pme interrupts for i.MX95 hongxing.zhu
@ 2026-06-03 6:25 ` hongxing.zhu
2026-06-03 6:50 ` sashiko-bot
2026-06-03 6:25 ` [PATCH v6 3/3] PCI: imx6: Add root port reset to support link recovery hongxing.zhu
2 siblings, 1 reply; 6+ messages in thread
From: hongxing.zhu @ 2026-06-03 6:25 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel,
Richard Zhu
From: Richard Zhu <hongxing.zhu@nxp.com>
The current PCIe device tree configuration only defines the MSI
interrupt, which is sufficient for basic PCIe operation but limits
advanced functionality.
Add the following interrupt lines to pcie0 and pcie1 nodes:
- dma: DMA interrupt for PCIe DMA operations
- intr: General controller events and link state changes
- aer: Advanced Error Reporting interrupt
- pme: Power Management Event interrupt
This enables enhanced PCIe features and capabilities that were
previously unavailable due to missing interrupt definitions.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
arch/arm64/boot/dts/freescale/imx95.dtsi | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
index 3e35c956a4d7..1a9803f96790 100644
--- a/arch/arm64/boot/dts/freescale/imx95.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
@@ -1945,8 +1945,12 @@ pcie0: pcie@4c300000 {
bus-range = <0x00 0xff>;
num-lanes = <1>;
num-viewport = <8>;
- interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "msi";
+ interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "intr", "aer", "pme";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
@@ -2020,8 +2024,12 @@ pcie1: pcie@4c380000 {
bus-range = <0x00 0xff>;
num-lanes = <1>;
num-viewport = <8>;
- interrupts = <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "msi";
+ interrupts = <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "intr", "aer", "pme";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 3/3] PCI: imx6: Add root port reset to support link recovery
2026-06-03 6:25 [PATCH v6 0/3] Add root port reset to support link recovery hongxing.zhu
2026-06-03 6:25 ` [PATCH v6 1/3] dt-bindings: imx6q-pcie: Add optional intr/aer/pme interrupts for i.MX95 hongxing.zhu
2026-06-03 6:25 ` [PATCH v6 2/3] arm64: dts: imx95: Add dma, intr, aer and pme interrupts for PCIe hongxing.zhu
@ 2026-06-03 6:25 ` hongxing.zhu
2026-06-03 7:05 ` sashiko-bot
2 siblings, 1 reply; 6+ messages in thread
From: hongxing.zhu @ 2026-06-03 6:25 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel,
Richard Zhu
From: Richard Zhu <hongxing.zhu@nxp.com>
The PCIe link can go down due to various unexpected circumstances. Add
root port reset support to enable link recovery for the i.MX PCIe
controller when the optional "intr" interrupt is present.
When a link down event occurs, reset the root port by: uninitializing the
PCIe controller, re-initializing it, and restarting the link.
On i.MX95 platforms, link events and PME share the same interrupt line.
The link event interrupt cannot use a threaded-only IRQ handler because
the PME driver uses request_irq() with only the IRQF_SHARED flag set,
which requires a primary handler.
To handle this shared interrupt scenario, register a primary interrupt
handler with IRQF_SHARED for link events and manipulate the link event
enable bits to ensure the shared interrupt source triggers only one
handler at a time.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/pci/controller/dwc/pci-imx6.c | 123 ++++++++++++++++++++++++++
1 file changed, 123 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 773ab65b2afa..aa5c90be23df 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -79,6 +79,10 @@
#define IMX95_SID_MASK GENMASK(5, 0)
#define IMX95_MAX_LUT 32
+#define IMX95_LINK_INT_CTRL_STS 0x1040
+#define IMX95_LINK_DOWN_INT_STS BIT(11)
+#define IMX95_LINK_DOWN_INT_EN BIT(10)
+
#define IMX95_PCIE_RST_CTRL 0x3010
#define IMX95_PCIE_COLD_RST BIT(0)
@@ -126,6 +130,8 @@ enum imx_pcie_variants {
#define IMX_PCIE_MAX_INSTANCES 2
struct imx_pcie;
+static int imx_pcie_reset_root_port(struct pci_host_bridge *bridge,
+ struct pci_dev *pdev);
struct imx_pcie_drvdata {
enum imx_pcie_variants variant;
@@ -158,6 +164,7 @@ struct imx_pcie {
bool supports_clkreq;
bool enable_ext_refclk;
struct regmap *iomuxc_gpr;
+ int lnk_intr;
u16 msi_ctrl;
u32 controller_id;
struct reset_control *pciephy_reset;
@@ -1394,6 +1401,13 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
imx_setup_phy_mpll(imx_pcie);
+ /*
+ * Callback invoked by PCI core when link down is detected and
+ * recovery is needed.
+ */
+ if (pp->bridge)
+ pp->bridge->reset_root_port = imx_pcie_reset_root_port;
+
return 0;
err_phy_off:
@@ -1661,6 +1675,9 @@ static int imx_pcie_suspend_noirq(struct device *dev)
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
return 0;
+ if (imx_pcie->lnk_intr > 0)
+ regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
imx_pcie_msi_save_restore(imx_pcie, true);
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
imx_pcie_lut_save(imx_pcie);
@@ -1711,6 +1728,9 @@ static int imx_pcie_resume_noirq(struct device *dev)
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
imx_pcie_lut_restore(imx_pcie);
imx_pcie_msi_save_restore(imx_pcie, false);
+ if (imx_pcie->lnk_intr > 0)
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
return 0;
}
@@ -1720,6 +1740,85 @@ static const struct dev_pm_ops imx_pcie_pm_ops = {
imx_pcie_resume_noirq)
};
+static irqreturn_t imx_pcie_lnk_irq_isr(int irq, void *priv)
+{
+ struct imx_pcie *imx_pcie = priv;
+ struct dw_pcie *pci = imx_pcie->pci;
+ struct device *dev = pci->dev;
+ u32 val;
+
+ regmap_read(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS, &val);
+ if (val & IMX95_LINK_DOWN_INT_STS) {
+ dev_dbg(dev, "PCIe link down detected, initiating recovery\n");
+ /* Clear link down interrupt status by writing 1b'1 to it */
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_STS);
+ regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
+
+ return IRQ_WAKE_THREAD;
+ }
+
+ return IRQ_NONE;
+}
+
+static irqreturn_t imx_pcie_lnk_irq_thread(int irq, void *priv)
+{
+ struct imx_pcie *imx_pcie = priv;
+ struct dw_pcie *pci = imx_pcie->pci;
+ struct dw_pcie_rp *pp = &pci->pp;
+ struct pci_dev *port;
+
+ for_each_pci_bridge(port, pp->bridge->bus)
+ if (pci_pcie_type(port) == PCI_EXP_TYPE_ROOT_PORT)
+ pci_host_handle_link_down(port);
+
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
+
+ return IRQ_HANDLED;
+}
+
+static int imx_pcie_reset_root_port(struct pci_host_bridge *bridge,
+ struct pci_dev *pdev)
+{
+ struct pci_bus *bus = bridge->bus;
+ struct dw_pcie_rp *pp = bus->sysdata;
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct imx_pcie *imx_pcie = to_imx_pcie(pci);
+ int ret;
+
+ imx_pcie_msi_save_restore(imx_pcie, true);
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+ imx_pcie_lut_save(imx_pcie);
+ imx_pcie_stop_link(pci);
+ imx_pcie_host_exit(pp);
+
+ ret = imx_pcie_host_init(pp);
+ if (ret) {
+ dev_err(pci->dev, "Failed to re-init PCIe\n");
+ return ret;
+ }
+ ret = dw_pcie_setup_rc(pp);
+ if (ret)
+ goto err_host_deinit;
+
+ imx_pcie_start_link(pci);
+ dw_pcie_wait_for_link(pci);
+
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+ imx_pcie_lut_restore(imx_pcie);
+ imx_pcie_msi_save_restore(imx_pcie, false);
+
+ dev_dbg(pci->dev, "Root port reset completed\n");
+ return 0;
+
+err_host_deinit:
+ imx_pcie_host_exit(pp);
+
+ return ret;
+}
+
static int imx_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1919,9 +2018,33 @@ static int imx_pcie_probe(struct platform_device *pdev)
val |= PCI_MSI_FLAGS_ENABLE;
dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val);
}
+
+ /* Get link event irq if it is present */
+ imx_pcie->lnk_intr = platform_get_irq_byname_optional(pdev, "intr");
+ if (imx_pcie->lnk_intr > 0) {
+ ret = devm_request_threaded_irq(dev, imx_pcie->lnk_intr,
+ imx_pcie_lnk_irq_isr,
+ imx_pcie_lnk_irq_thread,
+ IRQF_SHARED,
+ "lnk", imx_pcie);
+ if (ret) {
+ dev_err_probe(dev, ret,
+ "unable to request LNK IRQ\n");
+ goto err_host_deinit;
+ }
+
+ regmap_set_bits(imx_pcie->iomuxc_gpr,
+ IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
+ }
}
return 0;
+
+err_host_deinit:
+ dw_pcie_host_deinit(&pci->pp);
+
+ return ret;
}
static void imx_pcie_shutdown(struct platform_device *pdev)
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v6 2/3] arm64: dts: imx95: Add dma, intr, aer and pme interrupts for PCIe
2026-06-03 6:25 ` [PATCH v6 2/3] arm64: dts: imx95: Add dma, intr, aer and pme interrupts for PCIe hongxing.zhu
@ 2026-06-03 6:50 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-06-03 6:50 UTC (permalink / raw)
To: hongxing.zhu; +Cc: robh, Frank.Li, imx, devicetree, conor+dt, linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Unrealized feature claim regarding PCIe 'intr', 'aer', and 'pme' interrupts.
--
commit 29e808a747deaa069b3eea1b8af9a71ce6b4b8c9
Author: Richard Zhu <hongxing.zhu@nxp.com>
arm64: dts: imx95: Add dma, intr, aer and pme interrupts for PCIe
This commit adds dma, intr, aer, and pme interrupts to the pcie0 and pcie1
device tree nodes for the i.MX95. The commit message states this enables
enhanced PCIe features that were previously unavailable.
> diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
> index 3e35c956a4d7a..1a9803f967901 100644
> --- a/arch/arm64/boot/dts/freescale/imx95.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
[ ... ]
> @@ -1945,8 +1945,12 @@ pcie0: pcie@4c300000 {
> bus-range = <0x00 0xff>;
> num-lanes = <1>;
> num-viewport = <8>;
> - interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
> - interrupt-names = "msi";
> + interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-names = "msi", "dma", "intr", "aer", "pme";
[Severity: Medium]
The commit message mentions that adding these interrupts enables enhanced PCIe
features and capabilities that were previously unavailable. Are these new
interrupts actually consumed by the kernel?
Looking at the Linux PCIe DesignWare core and the i.MX PCIe driver, it does
not appear that the intr, aer, or pme interrupts are requested or handled via
these names. Features like AER and PME are typically handled generically by
the PCIe Port Bus driver using standard in-band PCIe capabilities.
Could the commit message be updated to clarify if these are being added
primarily for hardware description completeness, rather than directly enabling
new features in the Linux drivers?
[ ... ]
> @@ -2020,8 +2024,12 @@ pcie1: pcie@4c380000 {
> bus-range = <0x00 0xff>;
> num-lanes = <1>;
> num-viewport = <8>;
> - interrupts = <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
> - interrupt-names = "msi";
> + interrupts = <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-names = "msi", "dma", "intr", "aer", "pme";
[Severity: Medium]
Similar to pcie0, these interrupts are defined here for pcie1 but do not
appear to be consumed by the kernel. Is the functionality claim in the commit
message accurate for these definitions?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260603062510.3767610-1-hongxing.zhu@oss.nxp.com?part=2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v6 3/3] PCI: imx6: Add root port reset to support link recovery
2026-06-03 6:25 ` [PATCH v6 3/3] PCI: imx6: Add root port reset to support link recovery hongxing.zhu
@ 2026-06-03 7:05 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-06-03 7:05 UTC (permalink / raw)
To: hongxing.zhu; +Cc: devicetree, imx, robh, conor+dt, Frank.Li, linux-pci
Thank you for your contribution! Sashiko AI review found 9 potential issue(s) to consider:
- [High] Read-modify-write operations on mixed RW/W1C register silently drop interrupts.
- [High] Shared interrupt handler checks status but fails to verify if the interrupt is enabled.
- [High] Ignored return value of `dw_pcie_wait_for_link()` hides downstream link recovery failures.
- [High] Lockless traversal of PCI bus devices in an asynchronous IRQ thread exposes the kernel to Use-After-Free and list corruption.
- [High] Link down interrupt is not disabled during system shutdown, causing an AXI bus fault and system hang.
- [High] Failed root port reset leaves the controller unclocked while still active, causing a crash on subsequent PM suspend.
- [High] Unprotected hardware indirect register access during root port reset.
- [Medium] Ignored negative error codes from `platform_get_irq_byname_optional()` break probe deferral.
- [Low] Build failure due to undefined functions and struct members.
--
commit 5bee25b25210b0bc28349bc8474d10204a25cd72
Author: Richard Zhu <hongxing.zhu@nxp.com>
PCI: imx6: Add root port reset to support link recovery
The PCIe link can go down due to various unexpected circumstances. Add
root port reset support to enable link recovery for the i.MX PCIe
controller when the optional "intr" interrupt is present.
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 773ab65b2afac..aa5c90be23df8 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
[ ... ]
> @@ -1394,6 +1401,13 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
>
> imx_setup_phy_mpll(imx_pcie);
>
> + /*
> + * Callback invoked by PCI core when link down is detected and
> + * recovery is needed.
> + */
> + if (pp->bridge)
> + pp->bridge->reset_root_port = imx_pcie_reset_root_port;
[Severity: Low]
Does the reset_root_port member actually exist in struct pci_host_bridge?
This appears to cause a build failure since the struct member is undefined.
[ ... ]
> @@ -1661,6 +1675,9 @@ static int imx_pcie_suspend_noirq(struct device *dev)
> if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
> return 0;
>
> + if (imx_pcie->lnk_intr > 0)
> + regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
> + IMX95_LINK_DOWN_INT_EN);
[Severity: High]
Since IMX95_LINK_INT_CTRL_STS mixes an RW enable bit and a write-1-to-clear
status bit, will using regmap_clear_bits perform a read-modify-write cycle
that inadvertently clears pending status bits if they are latched during the
read?
[ ... ]
> +static irqreturn_t imx_pcie_lnk_irq_isr(int irq, void *priv)
> +{
> + struct imx_pcie *imx_pcie = priv;
> + struct dw_pcie *pci = imx_pcie->pci;
> + struct device *dev = pci->dev;
> + u32 val;
> +
> + regmap_read(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS, &val);
> + if (val & IMX95_LINK_DOWN_INT_STS) {
[Severity: High]
Is it possible for this shared interrupt handler to be invoked while the
interrupt is disabled, see the latched status bit, and erroneously return
IRQ_WAKE_THREAD?
If a PME interrupt fires while the link down interrupt is intentionally
disabled, the ISR will still claim it. Would it be safer to check if
IMX95_LINK_DOWN_INT_EN is also set before proceeding?
> + dev_dbg(dev, "PCIe link down detected, initiating recovery\n");
> + /* Clear link down interrupt status by writing 1b'1 to it */
> + regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
> + IMX95_LINK_DOWN_INT_STS);
[Severity: High]
Similar to the regmap_clear_bits call above, could using regmap_set_bits here
perform a read-modify-write cycle that inadvertently clears other pending
write-1-to-clear bits in the same register?
> + regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
> + IMX95_LINK_DOWN_INT_EN);
> +
> + return IRQ_WAKE_THREAD;
> + }
> +
> + return IRQ_NONE;
> +}
> +
> +static irqreturn_t imx_pcie_lnk_irq_thread(int irq, void *priv)
> +{
> + struct imx_pcie *imx_pcie = priv;
> + struct dw_pcie *pci = imx_pcie->pci;
> + struct dw_pcie_rp *pp = &pci->pp;
> + struct pci_dev *port;
> +
> + for_each_pci_bridge(port, pp->bridge->bus)
[Severity: High]
Is it safe to iterate the bus list locklessly in this IRQ thread?
Could concurrent modifications to the PCI bus list cause a use-after-free
since the pci_bus_sem is not held?
> + if (pci_pcie_type(port) == PCI_EXP_TYPE_ROOT_PORT)
> + pci_host_handle_link_down(port);
[Severity: Low]
Does the pci_host_handle_link_down function exist in the tree? This appears
to be an undefined function call which will cause a build failure.
> +
> + regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
> + IMX95_LINK_DOWN_INT_EN);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int imx_pcie_reset_root_port(struct pci_host_bridge *bridge,
> + struct pci_dev *pdev)
> +{
> + struct pci_bus *bus = bridge->bus;
> + struct dw_pcie_rp *pp = bus->sysdata;
> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> + struct imx_pcie *imx_pcie = to_imx_pcie(pci);
> + int ret;
> +
> + imx_pcie_msi_save_restore(imx_pcie, true);
> + if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
> + imx_pcie_lut_save(imx_pcie);
[Severity: High]
The i.MX95 PCIe hardware uses an indirect access mechanism for LUTs. Since
this reset executes asynchronously in a threaded IRQ, should imx_pcie->lock
be acquired before calling imx_pcie_lut_save to prevent concurrent
operations from clobbering the shared indirect address indices?
> + imx_pcie_stop_link(pci);
> + imx_pcie_host_exit(pp);
> +
> + ret = imx_pcie_host_init(pp);
> + if (ret) {
> + dev_err(pci->dev, "Failed to re-init PCIe\n");
> + return ret;
> + }
> + ret = dw_pcie_setup_rc(pp);
> + if (ret)
> + goto err_host_deinit;
> +
> + imx_pcie_start_link(pci);
> + dw_pcie_wait_for_link(pci);
[Severity: High]
Should the return value of dw_pcie_wait_for_link be checked here?
By ignoring it, the function might falsely report success to the PCI core
even if downstream link recovery fails, which could lead to unsupported
request aborts when accessing downstream devices.
> +
> + if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
> + imx_pcie_lut_restore(imx_pcie);
> + imx_pcie_msi_save_restore(imx_pcie, false);
> +
> + dev_dbg(pci->dev, "Root port reset completed\n");
> + return 0;
> +
> +err_host_deinit:
> + imx_pcie_host_exit(pp);
[Severity: High]
If the re-initialization fails and imx_pcie_host_exit disables the clocks,
the device still remains bound. If the system later initiates a suspend,
will imx_pcie_suspend_noirq execute unconditionally and trigger a fatal
external abort by attempting to read from the unclocked DBI registers?
> +
> + return ret;
> +}
> +
[ ... ]
> @@ -1919,9 +2018,33 @@ static int imx_pcie_probe(struct platform_device *pdev)
> val |= PCI_MSI_FLAGS_ENABLE;
> dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val);
> }
> +
> + /* Get link event irq if it is present */
> + imx_pcie->lnk_intr = platform_get_irq_byname_optional(pdev, "intr");
> + if (imx_pcie->lnk_intr > 0) {
[Severity: Medium]
If the interrupt controller is not yet ready, the platform irq function
returns -EPROBE_DEFER. Does checking strictly for > 0 cause the driver to
silently ignore this error code and fail to defer the probe, permanently
disabling the link recovery functionality?
[ ... ]
> +err_host_deinit:
> + dw_pcie_host_deinit(&pci->pp);
> +
> + return ret;
> }
>
> static void imx_pcie_shutdown(struct platform_device *pdev)
[Severity: High]
The patch enables the link down interrupt during probe, but looking at
imx_pcie_shutdown(), it does not disable it before asserting core reset.
Does asserting the core reset drop the link and trigger the interrupt?
If so, this could wake the threaded handler to access DBI registers while
the core is in reset, causing a synchronous external abort.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260603062510.3767610-1-hongxing.zhu@oss.nxp.com?part=3
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-03 7:05 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-03 6:25 [PATCH v6 0/3] Add root port reset to support link recovery hongxing.zhu
2026-06-03 6:25 ` [PATCH v6 1/3] dt-bindings: imx6q-pcie: Add optional intr/aer/pme interrupts for i.MX95 hongxing.zhu
2026-06-03 6:25 ` [PATCH v6 2/3] arm64: dts: imx95: Add dma, intr, aer and pme interrupts for PCIe hongxing.zhu
2026-06-03 6:50 ` sashiko-bot
2026-06-03 6:25 ` [PATCH v6 3/3] PCI: imx6: Add root port reset to support link recovery hongxing.zhu
2026-06-03 7:05 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox