diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c index 88af0dacf35131..3c31524af9e4b5 100644 --- a/drivers/pci/pcie/portdrv.c +++ b/drivers/pci/pcie/portdrv.c @@ -685,6 +685,9 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { static int pcie_portdrv_probe(struct pci_dev *dev, const struct pci_device_id *id) { + if (dev->dev_flags & PCI_DEV_FLAGS_NO_PORT_SERVICES) + return -ENODEV; + int type = pci_pcie_type(dev); int status; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 48946cca4be72c..bbde482ff7cb7c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -6380,3 +6380,15 @@ static void pci_mask_replay_timer_timeout(struct pci_dev *pdev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_GLI, 0x9750, pci_mask_replay_timer_timeout); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_GLI, 0x9755, pci_mask_replay_timer_timeout); #endif + +/* + * SG2042's PCIe root ports do not correctly deliver MSI interrupts to + * downstream devices when native PCIe port services are enabled. All + * services including bwctrl must be disabled, equivalent to pcie_ports=compat. + */ +static void quirk_sg2042_no_port_services(struct pci_dev *dev) +{ + pci_info(dev, "SG2042: disabling native PCIe port services\n"); + dev->dev_flags |= PCI_DEV_FLAGS_NO_PORT_SERVICES; +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SOPHGO, 0x2042, quirk_sg2042_no_port_services); diff --git a/include/linux/pci.h b/include/linux/pci.h index 1c270f1d512301..e038fe14ef7830 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -253,6 +253,8 @@ enum pci_dev_flags { * integrated with the downstream devices and doesn't use real PCI. */ PCI_DEV_FLAGS_PCI_BRIDGE_NO_ALIAS = (__force pci_dev_flags_t) (1 << 14), + /* Do not use native PCIe port services (equivalent to pcie_ports=compat) */ + PCI_DEV_FLAGS_NO_PORT_SERVICES = (__force pci_dev_flags_t) (1 << 15), }; enum pci_irq_reroute_variant { diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 406abf629be2e4..9663be526dd0f6 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2630,6 +2630,8 @@ #define PCI_VENDOR_ID_CXL 0x1e98 +#define PCI_VENDOR_ID_SOPHGO 0x1f1c + #define PCI_VENDOR_ID_TEHUTI 0x1fc9 #define PCI_DEVICE_ID_TEHUTI_3009 0x3009 #define PCI_DEVICE_ID_TEHUTI_3010 0x3010