Some PCI host bridges have limitation that AER/PME can't work over MSI. Vendors route the AER/PME via the dedicated SPI interrupter which is only handled by the controller driver. Because that aer and pme had been defined in the snps,dw-pcie.yaml document. Fetch the vendor specific AER/PME interrupters if they are defined in the fdt file by generic bridge->get_service_irqs hook. Signed-off-by: Richard Zhu <hongxing.zhu@xxxxxxx> --- .../pci/controller/dwc/pcie-designware-host.c | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 906277f9ffaf7..9393dc99df81f 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -13,11 +13,13 @@ #include <linux/irqdomain.h> #include <linux/msi.h> #include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/of_pci.h> #include <linux/pci_regs.h> #include <linux/platform_device.h> #include "../../pci.h" +#include "../../pcie/portdrv.h" #include "pcie-designware.h" static struct pci_ops dw_pcie_ops; @@ -461,6 +463,35 @@ static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp) return 0; } +static int dw_pcie_get_service_irqs(struct pci_host_bridge *bridge, + int *irqs, int mask) +{ + struct device *dev = bridge->dev.parent; + struct device_node *np = dev->of_node; + int ret, count = 0; + + if (!np) + return 0; + + if (mask & PCIE_PORT_SERVICE_AER) { + ret = of_irq_get_byname(np, "aer"); + if (ret > 0) { + irqs[PCIE_PORT_SERVICE_AER_SHIFT] = ret; + count++; + } + } + + if (mask & PCIE_PORT_SERVICE_PME) { + ret = of_irq_get_byname(np, "pme"); + if (ret > 0) { + irqs[PCIE_PORT_SERVICE_PME_SHIFT] = ret; + count++; + } + } + + return count; +} + int dw_pcie_host_init(struct dw_pcie_rp *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -476,6 +507,7 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) return -ENOMEM; pp->bridge = bridge; + pp->bridge->get_service_irqs = dw_pcie_get_service_irqs; ret = dw_pcie_host_get_resources(pp); if (ret) -- 2.37.1