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@nxp.com>
---
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