Some PCI host bridges have limitation that AER/PME can't work over MSI. Vendors route the AER/PME via the dedicated SPI interrupt which is only handled by the controller driver. Add the generic get_service_irqs() callback for bridge, to let portdrv can fetch the vendor specific AER/PME interrupter by it. Signed-off-by: Richard Zhu <hongxing.zhu@xxxxxxx> --- drivers/pci/pcie/portdrv.c | 7 +++++++ include/linux/pci.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c index e8318fd5f6ed5..035e6425ce034 100644 --- a/drivers/pci/pcie/portdrv.c +++ b/drivers/pci/pcie/portdrv.c @@ -176,11 +176,18 @@ static int pcie_port_enable_irq_vec(struct pci_dev *dev, int *irqs, int mask) */ static int pcie_init_service_irqs(struct pci_dev *dev, int *irqs, int mask) { + struct pci_host_bridge *host_bridge = pci_find_host_bridge(dev->bus); int ret, i; for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) irqs[i] = -1; + if (host_bridge->get_service_irqs) { + ret = host_bridge->get_service_irqs(host_bridge, irqs, mask); + if (ret > 0) + return 0; + } + /* * If we support PME but can't use MSI/MSI-X for it, we have to * fall back to INTx or other interrupts, e.g., a system shared diff --git a/include/linux/pci.h b/include/linux/pci.h index 05e68f35f3923..e681f2e6adc17 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -597,6 +597,7 @@ struct pci_host_bridge { u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */ int (*map_irq)(const struct pci_dev *, u8, u8); void (*release_fn)(struct pci_host_bridge *); + int (*get_service_irqs)(struct pci_host_bridge *bridge, int *irqs, int mask); int (*enable_device)(struct pci_host_bridge *bridge, struct pci_dev *dev); void (*disable_device)(struct pci_host_bridge *bridge, struct pci_dev *dev); void *release_data; -- 2.37.1