@@ -35,33 +35,59 @@
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME("pci_bind");
-static int acpi_pci_unbind(struct acpi_device *acpi_dev, struct pci_dev *dev)
+static int acpi_pci_unbind(struct acpi_device *acpi_dev, struct device *dev)
{
+ struct pci_dev *pdev = NULL;
+ struct pci_bus *bus = NULL;
+
+ if (dev_is_pci(dev)) {
+ pdev = to_pci_dev(dev);
+ if (pdev->subordinate)
+ bus = pdev->subordinate;
+ } else
+ bus = to_pci_host_bridge(dev)->bus;
+
if (acpi_dev) {
- device_set_run_wake(&dev->dev, false);
- pci_acpi_remove_pm_notifier(acpi_dev);
+ device_set_run_wake(dev, false);
+ if (pdev)
+ pci_acpi_remove_pm_notifier(acpi_dev);
+ else
+ pci_acpi_remove_bus_pm_notifier(acpi_dev);
}
- if (dev->subordinate)
- acpi_pci_irq_del_prt(dev->subordinate);
+ if (bus)
+ acpi_pci_irq_del_prt(bus);
return 0;
}
-static int acpi_pci_bind(struct acpi_device *acpi_dev, struct pci_dev *dev)
+static int acpi_pci_bind(struct acpi_device *acpi_dev, struct device *dev)
{
acpi_status status;
- struct pci_bus *bus;
+ struct pci_dev *pdev = NULL;
+ struct pci_bus *bus = NULL;
acpi_handle tmp_hdl;
acpi_handle handle;
+ if (dev_is_pci(dev)) {
+ pdev = to_pci_dev(dev);
+ if (pdev->subordinate)
+ bus = pdev->subordinate;
+ else
+ bus = pdev->bus;
+ } else
+ bus = to_pci_host_bridge(dev)->bus;
+
if (acpi_dev) {
- pci_acpi_add_pm_notifier(acpi_dev, dev);
+ if (pdev)
+ pci_acpi_add_pm_notifier(acpi_dev, pdev);
+ else
+ pci_acpi_add_bus_pm_notifier(acpi_dev, bus);
if (acpi_dev->wakeup.flags.run_wake)
- device_set_run_wake(&dev->dev, true);
+ device_set_run_wake(dev, true);
handle = acpi_dev->handle;
} else
- handle = DEVICE_ACPI_HANDLE(&dev->dev);
+ handle = DEVICE_ACPI_HANDLE(dev);
/*
* Evaluate and parse _PRT, if exists. This code allows parsing of
@@ -72,13 +98,8 @@ static int acpi_pci_bind(struct acpi_device *acpi_dev, struct pci_dev *dev)
* TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
*/
status = acpi_get_handle(handle, METHOD_NAME__PRT, &tmp_hdl);
- if (ACPI_SUCCESS(status)) {
- if (dev->subordinate)
- bus = dev->subordinate;
- else
- bus = dev->bus;
+ if (ACPI_SUCCESS(status))
acpi_pci_irq_add_prt(handle, bus);
- }
return 0;
}
@@ -86,10 +107,10 @@ static int acpi_pci_bind(struct acpi_device *acpi_dev, struct pci_dev *dev)
void acpi_pci_bind_notify(struct acpi_device *acpi_dev, struct device *dev,
bool bind)
{
- if (dev_is_pci(dev)) {
+ if (dev_is_pci(dev) || dev_is_pci_host_bridge(dev)) {
if (bind)
- acpi_pci_bind(acpi_dev, to_pci_dev(dev));
+ acpi_pci_bind(acpi_dev, dev);
else
- acpi_pci_unbind(acpi_dev, to_pci_dev(dev));
+ acpi_pci_unbind(acpi_dev, dev);
}
}
@@ -505,7 +505,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
int result;
struct acpi_pci_root *root;
struct acpi_pci_driver *driver;
- acpi_handle handle;
u32 flags;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
@@ -591,21 +590,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
goto out_del_root;
}
- /*
- * PCI Routing Table
- * -----------------
- * Evaluate and parse _PRT, if exists.
- */
- status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
- if (ACPI_SUCCESS(status))
- result = acpi_pci_irq_add_prt(device->handle, root->bus);
-
acpi_pci_root_osc_control_set(root);
- pci_acpi_add_bus_pm_notifier(device, root->bus);
- if (device->wakeup.flags.run_wake)
- device_set_run_wake(root->bus->bridge, true);
-
if (system_state != SYSTEM_BOOTING) {
pcibios_resource_survey_bus(root->bus);
pci_assign_unassigned_bus_resources(root->bus);
@@ -649,13 +635,6 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
driver->remove(root);
mutex_unlock(&acpi_pci_root_lock);
- device_set_run_wake(root->bus->bridge, false);
- pci_acpi_remove_bus_pm_notifier(device);
-
- status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
- if (ACPI_SUCCESS(status))
- acpi_pci_irq_del_prt(root->bus);
-
pci_remove_root_bus(root->bus);
mutex_lock(&acpi_pci_root_lock);
Now pci_dev is using: pci_bus_add_device ==> device_add ==> platform_notify aka acpi_platform_notify ==> acpi_bind_one ==> acpi_pci_bind_notify pci_host_bridge calling till to acpi_bind_one but not in acpi_pci_bind_notify because acpi_pci_bind_notify only handle pci_dev. Extend acpi_pci_bind_notify to handle pci_host_bridge. After that, We could remove same calling in acpi_pci_root_add and acpi_pci_root_remove. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Cc: Len Brown <lenb@kernel.org> Cc: linux-acpi@vger.kernel.org --- drivers/acpi/pci_bind.c | 59 +++++++++++++++++++++++++++++++--------------- drivers/acpi/pci_root.c | 21 ---------------- 2 files changed, 40 insertions(+), 40 deletions(-)