diff options
| author | Richard Zhu <hongxing.zhu@nxp.com> | 2026-03-31 16:52:52 +0800 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2026-04-03 16:51:27 -0500 |
| commit | 3a4e8302e72f83fd5cc8a916fc6f5c8fe5c8690e (patch) | |
| tree | 51772ee2a4c4fe3d55b58ee0ffdac7be4bbdba64 | |
| parent | 180ea823bb45eb71dd5ed0dc0b78633accd21096 (diff) | |
PCI: imx6: Keep Root Port MSI capability with iMSI-RX to work around hardware bug
On NXP i.MX7D, i.MX8MM, and i.MX8MQ chipsets, MSIs from the endpoints won't
be received by the iMSI-RX MSI controller if the Root Port MSI capability
is disabled.
Even though the Root Port MSIs won't be received by the iMSI-RX controller
due to design, these chipsets have some weird hardware bug that prevents
the endpoint MSIs from reaching when the Root Port MSI capability is
disabled.
Hence, introduce a new flag, 'dw_pcie_rp::keep_rp_msi_en', set it for the
above mentioned SoCs, and always keep the Root Port MSI capability when
this flag is set.
Note that by keeping Root Port MSI capability, Root Port MSIs such as AER,
PME and others won't be received by default. So users need to use
workarounds such as passing 'pcie_pme=nomsi' cmdline param.
Fixes: f5cd8a929c825 ("PCI: dwc: Remove MSI/MSIX capability for Root Port if iMSI-RX is used as MSI controller")
Suggested-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
[mani: commit log]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
[bhelgaas: fix typos]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260331085252.1243108-1-hongxing.zhu@nxp.com
| -rw-r--r-- | drivers/pci/controller/dwc/pci-imx6.c | 7 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-host.c | 2 | ||||
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware.h | 1 |
3 files changed, 9 insertions, 1 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 24c373020adc..a1da72dd85b0 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -117,6 +117,8 @@ enum imx_pcie_variants { #define IMX_PCIE_FLAG_HAS_LUT BIT(10) #define IMX_PCIE_FLAG_8GT_ECN_ERR051586 BIT(11) #define IMX_PCIE_FLAG_SKIP_L23_READY BIT(12) +/* Preserve MSI capability for platforms that require it */ +#define IMX_PCIE_FLAG_KEEP_MSI_CAP BIT(13) #define imx_check_flag(pci, val) (pci->drvdata->flags & val) @@ -1828,6 +1830,8 @@ static int imx_pcie_probe(struct platform_device *pdev) } else { if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_SKIP_L23_READY)) pci->pp.skip_l23_ready = true; + if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_KEEP_MSI_CAP)) + pci->pp.keep_rp_msi_en = true; pci->pp.use_atu_msg = true; ret = dw_pcie_host_init(&pci->pp); if (ret < 0) @@ -1907,6 +1911,7 @@ static const struct imx_pcie_drvdata drvdata[] = { [IMX7D] = { .variant = IMX7D, .flags = IMX_PCIE_FLAG_SUPPORTS_SUSPEND | + IMX_PCIE_FLAG_KEEP_MSI_CAP | IMX_PCIE_FLAG_HAS_APP_RESET | IMX_PCIE_FLAG_SKIP_L23_READY | IMX_PCIE_FLAG_HAS_PHY_RESET, @@ -1919,6 +1924,7 @@ static const struct imx_pcie_drvdata drvdata[] = { [IMX8MQ] = { .variant = IMX8MQ, .flags = IMX_PCIE_FLAG_HAS_APP_RESET | + IMX_PCIE_FLAG_KEEP_MSI_CAP | IMX_PCIE_FLAG_HAS_PHY_RESET | IMX_PCIE_FLAG_SUPPORTS_SUSPEND, .gpr = "fsl,imx8mq-iomuxc-gpr", @@ -1933,6 +1939,7 @@ static const struct imx_pcie_drvdata drvdata[] = { [IMX8MM] = { .variant = IMX8MM, .flags = IMX_PCIE_FLAG_SUPPORTS_SUSPEND | + IMX_PCIE_FLAG_KEEP_MSI_CAP | IMX_PCIE_FLAG_HAS_PHYDRV | IMX_PCIE_FLAG_HAS_APP_RESET, .gpr = "fsl,imx8mm-iomuxc-gpr", diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 6ae6189e9b8a..ded5462deae7 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -1171,7 +1171,7 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp) * the MSI and MSI-X capabilities of the Root Port to allow the drivers * to fall back to INTx instead. */ - if (pp->use_imsi_rx) { + if (pp->use_imsi_rx && !pp->keep_rp_msi_en) { dw_pcie_remove_capability(pci, PCI_CAP_ID_MSI); dw_pcie_remove_capability(pci, PCI_CAP_ID_MSIX); } diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index ae6389dd9caa..b12c5334552c 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -421,6 +421,7 @@ struct dw_pcie_host_ops { struct dw_pcie_rp { bool use_imsi_rx:1; + bool keep_rp_msi_en:1; bool cfg0_io_shared:1; u64 cfg0_base; void __iomem *va_cfg0_base; |
