diff options
author | Shanker Donthineni <sdonthineni@nvidia.com> | 2021-08-17 23:34:58 +0530 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2021-08-18 17:16:46 -0500 |
commit | 375553a93201a58a52f142eab19545a07aa1eaf5 (patch) | |
tree | 65b05651a18791e8a770264ada2f33b63f84c9cb /drivers/pci/pci-acpi.c | |
parent | 4273e64cc4ebb881e1954d768020f5440491dcd9 (diff) | |
download | lwn-375553a93201a58a52f142eab19545a07aa1eaf5.tar.gz lwn-375553a93201a58a52f142eab19545a07aa1eaf5.zip |
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>
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r-- | drivers/pci/pci-acpi.c | 34 |
1 files changed, 12 insertions, 22 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index af2341d98860..c27dbb2294e3 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -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) |