From 74a70e80daa993445a8f0be817f8152a3b9d3b41 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 9 Apr 2025 22:43:10 +0200 Subject: [PATCH 1/5] PCI: Remove pci_fixup_cardbus() Since 1c7f4fe86f17 ("powerpc/pci: Remove pcibios_setup_bus_devices()") there's no architecture left setting pci_fixup_cardbus. Therefore remove support from PCI core. Signed-off-by: Heiner Kallweit Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/8de7da4c-2b16-4ee1-8c42-0d04f3c821c6@gmail.com --- drivers/pci/pci.c | 5 ----- drivers/pcmcia/cardbus.c | 1 - include/linux/pci.h | 3 --- 3 files changed, 9 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4d7c9f64ea24..c24d6f5a1012 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -6806,11 +6806,6 @@ int __weak pci_ext_cfg_avail(void) return 1; } -void __weak pci_fixup_cardbus(struct pci_bus *bus) -{ -} -EXPORT_SYMBOL(pci_fixup_cardbus); - static int __init pci_setup(char *str) { while (str) { diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 45c8252c8edc..5e5cf2c3e2c8 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -72,7 +72,6 @@ int __ref cb_alloc(struct pcmcia_socket *s) pci_lock_rescan_remove(); s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); - pci_fixup_cardbus(bus); max = bus->busn_res.start; for (pass = 0; pass < 2; pass++) diff --git a/include/linux/pci.h b/include/linux/pci.h index 0e8e3fd77e96..d26e6611bd00 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1139,9 +1139,6 @@ resource_size_t pcibios_align_resource(void *, const struct resource *, resource_size_t, resource_size_t); -/* Weak but can be overridden by arch */ -void pci_fixup_cardbus(struct pci_bus *); - /* Generic PCI functions used internally */ void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region, From 5fe8d08139280a552bb3e8471284362c65c5b032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Wed, 16 Apr 2025 13:02:39 +0300 Subject: [PATCH 2/5] PCI: Use PCI_STD_NUM_BARS instead of 6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pci_read_bases() is given literal 6 that means PCI_STD_NUM_BARS. Replace the literal with the define to annotate the code better. Signed-off-by: Ilpo Järvinen Signed-off-by: Bjorn Helgaas Reviewed-by: Niklas Cassel Link: https://patch.msgid.link/20250416100239.6958-1-ilpo.jarvinen@linux.intel.com --- drivers/pci/probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 364fa2a514f8..08971fca0819 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2058,7 +2058,7 @@ int pci_setup_device(struct pci_dev *dev) if (class == PCI_CLASS_BRIDGE_PCI) goto bad; pci_read_irq(dev); - pci_read_bases(dev, 6, PCI_ROM_ADDRESS); + pci_read_bases(dev, PCI_STD_NUM_BARS, PCI_ROM_ADDRESS); pci_subsystem_ids(dev, &dev->subsystem_vendor, &dev->subsystem_device); From d24eba726aadf8778f2907dd42281c6380b0ccaa Mon Sep 17 00:00:00 2001 From: Wilfred Mallawa Date: Mon, 14 Apr 2025 10:15:06 +1000 Subject: [PATCH 3/5] PCI: Print the actual delay time in pci_bridge_wait_for_secondary_bus() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print the delay amount that pcie_wait_for_link_delay() is invoked with instead of the hardcoded 1000ms value in the debug info print. Fixes: 7b3ba09febf4 ("PCI/PM: Shorten pci_bridge_wait_for_secondary_bus() wait time for slow links") Signed-off-by: Wilfred Mallawa Signed-off-by: Bjorn Helgaas Reviewed-by: Damien Le Moal Reviewed-by: Kuppuswamy Sathyanarayanan Reviewed-by: Mika Westerberg Reviewed-by: Ilpo Järvinen Link: https://patch.msgid.link/20250414001505.21243-2-wilfred.opensource@gmail.com --- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index c24d6f5a1012..53a070394739 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4954,7 +4954,7 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) delay); if (!pcie_wait_for_link_delay(dev, true, delay)) { /* Did not train, no need to wait any further */ - pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n"); + pci_info(dev, "Data Link Layer Link Active not set in %d msec\n", delay); return -ENOTTY; } From 3be5fa236649da6404f1bca1491bf02d4b0d5cce Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Fri, 25 Apr 2025 11:24:21 +0200 Subject: [PATCH 4/5] Revert "iommu/amd: Prevent binding other PCI drivers to IOMMU PCI devices" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 991de2e59090 ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") changed IRQ handling on PCI driver probing. It inadvertently broke resume from system sleep on AMD platforms: https://lore.kernel.org/r/20150926164651.GA3640@pd.tnic/ This was fixed by two independent commits: * 8affb487d4a4 ("x86/PCI: Don't alloc pcibios-irq when MSI is enabled") * cbbc00be2ce3 ("iommu/amd: Prevent binding other PCI drivers to IOMMU PCI devices") The breaking change and one of these two fixes were subsequently reverted: * fe25d078874f ("Revert "x86/PCI: Don't alloc pcibios-irq when MSI is enabled"") * 6c777e8799a9 ("Revert "PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()"") This rendered the second fix unnecessary, so revert it as well. It used the match_driver flag in struct pci_dev, which is internal to the PCI core and not supposed to be touched by arbitrary drivers. Signed-off-by: Lukas Wunner Signed-off-by: Bjorn Helgaas Signed-off-by: Krzysztof Wilczyński Acked-by: Joerg Roedel Link: https://patch.msgid.link/9a3ddff5cc49512044f963ba0904347bd404094d.1745572340.git.lukas@wunner.de --- drivers/iommu/amd/init.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index dd9e26b7b718..33b6e12c7d24 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -2030,9 +2030,6 @@ static int __init iommu_init_pci(struct amd_iommu *iommu) if (!iommu->dev) return -ENODEV; - /* Prevent binding other PCI device drivers to IOMMU devices */ - iommu->dev->match_driver = false; - /* ACPI _PRT won't have an IRQ for IOMMU */ iommu->dev->irq_managed = 1; From ce45dc4bb22e96b59a07e19b67e915d99dd5281b Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Fri, 25 Apr 2025 11:24:22 +0200 Subject: [PATCH 5/5] PCI: Limit visibility of match_driver flag to PCI core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 58d9a38f6fac ("PCI: Skip attaching driver in device_add()"), PCI enumeration is split into two steps: In the first step, all devices are published in sysfs with device_add(). In the second step, drivers are bound to the devices with device_attach(). To delay driver binding until the second step, a "bool match_driver" in struct pci_dev is used. Instead of a bool, use a bit in the "unsigned long priv_flags" to shrink struct pci_dev a little and prevent use of the bool outside the PCI core (as has happened with commit cbbc00be2ce3 ("iommu/amd: Prevent binding other PCI drivers to IOMMU PCI devices")). Signed-off-by: Lukas Wunner Signed-off-by: Bjorn Helgaas Signed-off-by: Krzysztof Wilczyński Link: https://patch.msgid.link/d22a9e5b81d6bd8dd1837607d6156679b3b1199c.1745572340.git.lukas@wunner.de --- drivers/pci/bus.c | 4 +++- drivers/pci/pci-driver.c | 2 +- drivers/pci/pci.h | 11 +++++++++++ drivers/pci/probe.c | 1 - include/linux/pci.h | 2 -- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index b6851101ac36..69048869ef1c 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -369,7 +369,9 @@ void pci_bus_add_device(struct pci_dev *dev) pdev->name); } - dev->match_driver = !dn || of_device_is_available(dn); + if (!dn || of_device_is_available(dn)) + pci_dev_allow_binding(dev); + retval = device_attach(&dev->dev); if (retval < 0 && retval != -EPROBE_DEFER) pci_warn(dev, "device attach failed (%d)\n", retval); diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index c8bd71a739f7..0c5bdb8c2c07 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -1507,7 +1507,7 @@ static int pci_bus_match(struct device *dev, const struct device_driver *drv) struct pci_driver *pci_drv; const struct pci_device_id *found_id; - if (!pci_dev->match_driver) + if (pci_dev_binding_disallowed(pci_dev)) return 0; pci_drv = (struct pci_driver *)to_pci_driver(drv); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index b81e99cd4b62..de5d4ef943b2 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -557,6 +557,7 @@ static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused) #define PCI_DPC_RECOVERED 1 #define PCI_DPC_RECOVERING 2 #define PCI_DEV_REMOVED 3 +#define PCI_DEV_ALLOW_BINDING 7 static inline void pci_dev_assign_added(struct pci_dev *dev) { @@ -580,6 +581,16 @@ static inline bool pci_dev_test_and_set_removed(struct pci_dev *dev) return test_and_set_bit(PCI_DEV_REMOVED, &dev->priv_flags); } +static inline void pci_dev_allow_binding(struct pci_dev *dev) +{ + set_bit(PCI_DEV_ALLOW_BINDING, &dev->priv_flags); +} + +static inline bool pci_dev_binding_disallowed(struct pci_dev *dev) +{ + return !test_bit(PCI_DEV_ALLOW_BINDING, &dev->priv_flags); +} + #ifdef CONFIG_PCIEAER #include diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 08971fca0819..4b8693ec9e4c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2711,7 +2711,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) pci_set_msi_domain(dev); /* Notifier could use PCI capabilities */ - dev->match_driver = false; ret = device_add(&dev->dev); WARN_ON(ret < 0); diff --git a/include/linux/pci.h b/include/linux/pci.h index d26e6611bd00..053d9dd494d4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -423,8 +423,6 @@ struct pci_dev { struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */ struct resource driver_exclusive_resource; /* driver exclusive resource ranges */ - bool match_driver; /* Skip attaching driver */ - unsigned int transparent:1; /* Subtractive decode bridge */ unsigned int io_window:1; /* Bridge has I/O window */ unsigned int pref_window:1; /* Bridge has pref mem window */