mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	PCI: Limit visibility of match_driver flag to PCI core
Since commit58d9a38f6f("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 commitcbbc00be2c("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:
		
							parent
							
								
									3be5fa2366
								
							
						
					
					
						commit
						ce45dc4bb2
					
				
					 5 changed files with 15 additions and 5 deletions
				
			
		| 
						 | 
					@ -369,7 +369,9 @@ void pci_bus_add_device(struct pci_dev *dev)
 | 
				
			||||||
				pdev->name);
 | 
									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);
 | 
						retval = device_attach(&dev->dev);
 | 
				
			||||||
	if (retval < 0 && retval != -EPROBE_DEFER)
 | 
						if (retval < 0 && retval != -EPROBE_DEFER)
 | 
				
			||||||
		pci_warn(dev, "device attach failed (%d)\n", retval);
 | 
							pci_warn(dev, "device attach failed (%d)\n", retval);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1507,7 +1507,7 @@ static int pci_bus_match(struct device *dev, const struct device_driver *drv)
 | 
				
			||||||
	struct pci_driver *pci_drv;
 | 
						struct pci_driver *pci_drv;
 | 
				
			||||||
	const struct pci_device_id *found_id;
 | 
						const struct pci_device_id *found_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!pci_dev->match_driver)
 | 
						if (pci_dev_binding_disallowed(pci_dev))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pci_drv = (struct pci_driver *)to_pci_driver(drv);
 | 
						pci_drv = (struct pci_driver *)to_pci_driver(drv);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_RECOVERED 1
 | 
				
			||||||
#define PCI_DPC_RECOVERING 2
 | 
					#define PCI_DPC_RECOVERING 2
 | 
				
			||||||
#define PCI_DEV_REMOVED 3
 | 
					#define PCI_DEV_REMOVED 3
 | 
				
			||||||
 | 
					#define PCI_DEV_ALLOW_BINDING 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void pci_dev_assign_added(struct pci_dev *dev)
 | 
					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);
 | 
						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
 | 
					#ifdef CONFIG_PCIEAER
 | 
				
			||||||
#include <linux/aer.h>
 | 
					#include <linux/aer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2711,7 +2711,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 | 
				
			||||||
	pci_set_msi_domain(dev);
 | 
						pci_set_msi_domain(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Notifier could use PCI capabilities */
 | 
						/* Notifier could use PCI capabilities */
 | 
				
			||||||
	dev->match_driver = false;
 | 
					 | 
				
			||||||
	ret = device_add(&dev->dev);
 | 
						ret = device_add(&dev->dev);
 | 
				
			||||||
	WARN_ON(ret < 0);
 | 
						WARN_ON(ret < 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -423,8 +423,6 @@ struct pci_dev {
 | 
				
			||||||
	struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
 | 
						struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
 | 
				
			||||||
	struct resource driver_exclusive_resource;	 /* driver exclusive resource ranges */
 | 
						struct resource driver_exclusive_resource;	 /* driver exclusive resource ranges */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool		match_driver;		/* Skip attaching driver */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	unsigned int	transparent:1;		/* Subtractive decode bridge */
 | 
						unsigned int	transparent:1;		/* Subtractive decode bridge */
 | 
				
			||||||
	unsigned int	io_window:1;		/* Bridge has I/O window */
 | 
						unsigned int	io_window:1;		/* Bridge has I/O window */
 | 
				
			||||||
	unsigned int	pref_window:1;		/* Bridge has pref mem window */
 | 
						unsigned int	pref_window:1;		/* Bridge has pref mem window */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue