PCI: Limit visibility of match_driver flag to PCI core

Since commit 58d9a38f6f ("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 cbbc00be2c ("iommu/amd: Prevent binding
other PCI drivers to IOMMU PCI devices")).

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Link: https://patch.msgid.link/d22a9e5b81d6bd8dd1837607d6156679b3b1199c.1745572340.git.lukas@wunner.de
This commit is contained in:
Lukas Wunner 2025-04-25 11:24:22 +02:00 committed by Krzysztof Wilczyński
parent 3be5fa2366
commit ce45dc4bb2
No known key found for this signature in database
GPG key ID: 7C64768D3DE334E7
5 changed files with 15 additions and 5 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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 <linux/aer.h>

View file

@ -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);

View file

@ -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 */