mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	PCI/portdrv: Remove pcie_port_bus_type link order dependency
The pcie_port_bus_type must be registered before drivers that depend on it can be registered. Those drivers include: pcied_init() # PCIe native hotplug driver aer_service_init() # AER driver dpc_service_init() # DPC driver pcie_pme_service_init() # PME driver Previously we registered pcie_port_bus_type from pcie_portdrv_init(), a device_initcall. The callers of pcie_port_service_register() (above) are also device_initcalls. This is fragile because the device_initcall ordering depends on link order, which is not explicit. Register pcie_port_bus_type from pci_driver_init() along with pci_bus_type. This removes the link order dependency between portdrv and the pciehp, AER, DPC, and PCIe PME drivers. Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
		
							parent
							
								
									79a011194b
								
							
						
					
					
						commit
						c6c889d932
					
				| @ -19,6 +19,7 @@ | ||||
| #include <linux/suspend.h> | ||||
| #include <linux/kexec.h> | ||||
| #include "pci.h" | ||||
| #include "pcie/portdrv.h" | ||||
| 
 | ||||
| struct pci_dynid { | ||||
| 	struct list_head node; | ||||
| @ -1552,8 +1553,49 @@ struct bus_type pci_bus_type = { | ||||
| }; | ||||
| EXPORT_SYMBOL(pci_bus_type); | ||||
| 
 | ||||
| #ifdef CONFIG_PCIEPORTBUS | ||||
| static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) | ||||
| { | ||||
| 	struct pcie_device *pciedev; | ||||
| 	struct pcie_port_service_driver *driver; | ||||
| 
 | ||||
| 	if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	pciedev = to_pcie_device(dev); | ||||
| 	driver = to_service_driver(drv); | ||||
| 
 | ||||
| 	if (driver->service != pciedev->service) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (driver->port_type != PCIE_ANY_PORT && | ||||
| 	    driver->port_type != pci_pcie_type(pciedev->port)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| struct bus_type pcie_port_bus_type = { | ||||
| 	.name		= "pci_express", | ||||
| 	.match		= pcie_port_bus_match, | ||||
| }; | ||||
| EXPORT_SYMBOL_GPL(pcie_port_bus_type); | ||||
| #endif | ||||
| 
 | ||||
| static int __init pci_driver_init(void) | ||||
| { | ||||
| 	return bus_register(&pci_bus_type); | ||||
| 	int ret; | ||||
| 
 | ||||
| 	ret = bus_register(&pci_bus_type); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| #ifdef CONFIG_PCIEPORTBUS | ||||
| 	ret = bus_register(&pcie_port_bus_type); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| #endif | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| postcore_initcall(pci_driver_init); | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
| # Build PCI Express ASPM if needed
 | ||||
| obj-$(CONFIG_PCIEASPM)		+= aspm.o | ||||
| 
 | ||||
| pcieportdrv-y			:= portdrv_core.o portdrv_pci.o portdrv_bus.o | ||||
| pcieportdrv-y			:= portdrv_core.o portdrv_pci.o | ||||
| pcieportdrv-$(CONFIG_ACPI)	+= portdrv_acpi.o | ||||
| 
 | ||||
| obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o | ||||
|  | ||||
| @ -1,55 +0,0 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| /*
 | ||||
|  * File:	portdrv_bus.c | ||||
|  * Purpose:	PCI Express Port Bus Driver's Bus Overloading Functions | ||||
|  * | ||||
|  * Copyright (C) 2004 Intel | ||||
|  * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/module.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/pm.h> | ||||
| 
 | ||||
| #include "portdrv.h" | ||||
| 
 | ||||
| static int pcie_port_bus_match(struct device *dev, struct device_driver *drv); | ||||
| 
 | ||||
| struct bus_type pcie_port_bus_type = { | ||||
| 	.name		= "pci_express", | ||||
| 	.match		= pcie_port_bus_match, | ||||
| }; | ||||
| EXPORT_SYMBOL_GPL(pcie_port_bus_type); | ||||
| 
 | ||||
| static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) | ||||
| { | ||||
| 	struct pcie_device *pciedev; | ||||
| 	struct pcie_port_service_driver *driver; | ||||
| 
 | ||||
| 	if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	pciedev = to_pcie_device(dev); | ||||
| 	driver = to_service_driver(drv); | ||||
| 
 | ||||
| 	if (driver->service != pciedev->service) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if ((driver->port_type != PCIE_ANY_PORT) && | ||||
| 	    (driver->port_type != pci_pcie_type(pciedev->port))) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| int pcie_port_bus_register(void) | ||||
| { | ||||
| 	return bus_register(&pcie_port_bus_type); | ||||
| } | ||||
| 
 | ||||
| void pcie_port_bus_unregister(void) | ||||
| { | ||||
| 	bus_unregister(&pcie_port_bus_type); | ||||
| } | ||||
| @ -258,22 +258,11 @@ static const struct dmi_system_id pcie_portdrv_dmi_table[] __initconst = { | ||||
| 
 | ||||
| static int __init pcie_portdrv_init(void) | ||||
| { | ||||
| 	int retval; | ||||
| 
 | ||||
| 	if (pcie_ports_disabled) | ||||
| 		return -EACCES; | ||||
| 
 | ||||
| 	dmi_check_system(pcie_portdrv_dmi_table); | ||||
| 
 | ||||
| 	retval = pcie_port_bus_register(); | ||||
| 	if (retval) { | ||||
| 		printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	retval = pci_register_driver(&pcie_portdriver); | ||||
| 	if (retval) | ||||
| 		pcie_port_bus_unregister(); | ||||
|  out: | ||||
| 	return retval; | ||||
| 	return pci_register_driver(&pcie_portdriver); | ||||
| } | ||||
| device_initcall(pcie_portdrv_init); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Bjorn Helgaas
						Bjorn Helgaas