forked from mirrors/linux
		
	PCI: Setup ACPI fwnode early and at the same time with OF
Previously, the ACPI_COMPANION() of a pci_dev was usually set by
acpi_bind_one() in this path:
  pci_device_add
    pci_configure_device
    pci_init_capabilities
    device_add
      device_platform_notify
	acpi_platform_notify
	  acpi_device_notify  # KOBJ_ADD
	    acpi_bind_one
	      ACPI_COMPANION_SET
However, things like pci_configure_device() and pci_init_capabilities()
that run before device_add() need the ACPI_COMPANION, e.g.,
acpi_pci_bridge_d3() uses a _DSD method to learn about D3 support.  These
places had special-case code to manually look up the ACPI_COMPANION.
Set the ACPI_COMPANION earlier, in pci_setup_device(), so it will be
available while configuring the device.  This covers both paths to creating
pci_dev objects:
  pci_scan_single_device           # for normal non-SR-IOV devices
    pci_scan_device
      pci_setup_device
	pci_set_acpi_fwnode
    pci_device_add
  pci_iov_add_virtfn               # for SR-IOV virtual functions
    pci_setup_device
      pci_set_acpi_fwnode
Also move the OF fwnode setup to the same spot.
[bhelgaas: commit log]
Link: https://lore.kernel.org/r/20210817180500.1253-8-ameynarkhede03@gmail.com
Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									4273e64cc4
								
							
						
					
					
						commit
						375553a932
					
				
					 2 changed files with 16 additions and 25 deletions
				
			
		|  | @ -952,46 +952,36 @@ static bool acpi_pci_power_manageable(struct pci_dev *dev) | |||
| 
 | ||||
| static bool acpi_pci_bridge_d3(struct pci_dev *dev) | ||||
| { | ||||
| 	const struct fwnode_handle *fwnode; | ||||
| 	const union acpi_object *obj; | ||||
| 	struct acpi_device *adev; | ||||
| 	struct pci_dev *root; | ||||
| 	u8 val; | ||||
| 	struct pci_dev *rpdev; | ||||
| 
 | ||||
| 	if (!dev->is_hotplug_bridge) | ||||
| 		return false; | ||||
| 
 | ||||
| 	/* Assume D3 support if the bridge is power-manageable by ACPI. */ | ||||
| 	pci_set_acpi_fwnode(dev); | ||||
| 
 | ||||
| 	if (acpi_pci_power_manageable(dev)) | ||||
| 		return true; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Look for a special _DSD property for the root port and if it | ||||
| 	 * is set we know the hierarchy behind it supports D3 just fine. | ||||
| 	 * The ACPI firmware will provide the device-specific properties through | ||||
| 	 * _DSD configuration object. Look for the 'HotPlugSupportInD3' property | ||||
| 	 * for the root port and if it is set we know the hierarchy behind it | ||||
| 	 * supports D3 just fine. | ||||
| 	 */ | ||||
| 	root = pcie_find_root_port(dev); | ||||
| 	if (!root) | ||||
| 	rpdev = pcie_find_root_port(dev); | ||||
| 	if (!rpdev) | ||||
| 		return false; | ||||
| 
 | ||||
| 	adev = ACPI_COMPANION(&root->dev); | ||||
| 	if (root == dev) { | ||||
| 		/*
 | ||||
| 		 * It is possible that the ACPI companion is not yet bound | ||||
| 		 * for the root port so look it up manually here. | ||||
| 		 */ | ||||
| 		if (!adev && !pci_dev_is_added(root)) | ||||
| 			adev = acpi_pci_find_companion(&root->dev); | ||||
| 	} | ||||
| 
 | ||||
| 	adev = ACPI_COMPANION(&rpdev->dev); | ||||
| 	if (!adev) | ||||
| 		return false; | ||||
| 
 | ||||
| 	fwnode = acpi_fwnode_handle(adev); | ||||
| 	if (fwnode_property_read_u8(fwnode, "HotPlugSupportInD3", &val)) | ||||
| 	if (acpi_dev_get_property(adev, "HotPlugSupportInD3", | ||||
| 				   ACPI_TYPE_INTEGER, &obj) < 0) | ||||
| 		return false; | ||||
| 
 | ||||
| 	return val == 1; | ||||
| 	return obj->integer.value == 1; | ||||
| } | ||||
| 
 | ||||
| static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) | ||||
|  |  | |||
|  | @ -1810,6 +1810,9 @@ int pci_setup_device(struct pci_dev *dev) | |||
| 	dev->error_state = pci_channel_io_normal; | ||||
| 	set_pcie_port_type(dev); | ||||
| 
 | ||||
| 	pci_set_of_node(dev); | ||||
| 	pci_set_acpi_fwnode(dev); | ||||
| 
 | ||||
| 	pci_dev_assign_slot(dev); | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -1947,6 +1950,7 @@ int pci_setup_device(struct pci_dev *dev) | |||
| 	default:				    /* unknown header */ | ||||
| 		pci_err(dev, "unknown header type %02x, ignoring device\n", | ||||
| 			dev->hdr_type); | ||||
| 		pci_release_of_node(dev); | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	bad: | ||||
|  | @ -2375,10 +2379,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) | |||
| 	dev->vendor = l & 0xffff; | ||||
| 	dev->device = (l >> 16) & 0xffff; | ||||
| 
 | ||||
| 	pci_set_of_node(dev); | ||||
| 
 | ||||
| 	if (pci_setup_device(dev)) { | ||||
| 		pci_release_of_node(dev); | ||||
| 		pci_bus_put(dev->bus); | ||||
| 		kfree(dev); | ||||
| 		return NULL; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Shanker Donthineni
						Shanker Donthineni