From 62a08c5a3173c4462239804b959c0d29dc74493b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 30 Oct 2012 14:31:32 -0600 Subject: PCI/ACPI: Assign unassigned resource for hot-added root bus After we get hot-added IOAPIC registered. pci_enable_bridges() will try to enable IOAPIC IRQ for PCI bridges. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index bce469c0b48a..27adbfdffb0c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -644,12 +644,19 @@ static int acpi_pci_root_start(struct acpi_device *device) struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; + if (system_state != SYSTEM_BOOTING) + pci_assign_unassigned_bus_resources(root->bus); + mutex_lock(&acpi_pci_root_lock); list_for_each_entry(driver, &acpi_pci_drivers, node) if (driver->add) driver->add(root); mutex_unlock(&acpi_pci_root_lock); + /* need to after hot-added ioapic is registered */ + if (system_state != SYSTEM_BOOTING) + pci_enable_bridges(root->bus); + pci_bus_add_devices(root->bus); return 0; -- cgit v1.2.1 From 9738a1fd214b8f617b31503307c79b6af72ee464 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 30 Oct 2012 14:31:43 -0600 Subject: PCI/ACPI: Make acpi_pci_root_remove() stop/remove pci root bus It will call pci_stop_and_remove_bus() to stop/remove pci root bus. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki CC: Len Brown CC: linux-acpi@vger.kernel.org --- drivers/acpi/pci_root.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 27adbfdffb0c..aed09537861a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -667,14 +667,20 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; + pci_stop_root_bus(root->bus); + mutex_lock(&acpi_pci_root_lock); list_for_each_entry(driver, &acpi_pci_drivers, node) if (driver->remove) driver->remove(root); + mutex_unlock(&acpi_pci_root_lock); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); + pci_remove_root_bus(root->bus); + + mutex_lock(&acpi_pci_root_lock); list_del(&root->node); mutex_unlock(&acpi_pci_root_lock); kfree(root); -- cgit v1.2.1 From 13b6a916409adbc47f3d13f9580be0bd413e446e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 30 Oct 2012 14:31:48 -0600 Subject: PCI/ACPI: Delete host bridge _PRT during hot remove path Corresponding to add path. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index aed09537861a..a27cbb572fe1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -664,6 +664,8 @@ static int acpi_pci_root_start(struct acpi_device *device) static int acpi_pci_root_remove(struct acpi_device *device, int type) { + acpi_status status; + acpi_handle handle; struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; @@ -678,6 +680,10 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) 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); -- cgit v1.2.1 From f426cef3bc58806284e0fee55d29262b10279f9c Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 30 Oct 2012 14:31:52 -0600 Subject: PCI/ACPI: Remove acpi_root_driver in reverse order Call the sub-driver .remove() methods in the reverse order of the .add() methods for symmetry. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_root.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index a27cbb572fe1..012f40d1d75d 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -672,7 +672,7 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) pci_stop_root_bus(root->bus); mutex_lock(&acpi_pci_root_lock); - list_for_each_entry(driver, &acpi_pci_drivers, node) + list_for_each_entry_reverse(driver, &acpi_pci_drivers, node) if (driver->remove) driver->remove(root); mutex_unlock(&acpi_pci_root_lock); -- cgit v1.2.1 From 79c4412298771b8996302806abc8a11e760da9b3 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 30 Oct 2012 15:24:06 +0900 Subject: ACPI: Pass segment/bus to _PRT add/del so they don't depend on pci_bus This effectively reverts 859a3f86ca8 ("ACPI: simplify acpi_pci_irq_add_prt() API") and d9efae3688a ("ACPI: simplify acpi_pci_irq_del_prt() API"). The reason is to disentangle these routines from the struct pci_bus. We want to be able to add the _PRT before the struct pci_bus exists, and delete the _PRT after we've removed the pci_bus. Signed-off-by: Bjorn Helgaas Signed-off-by: Taku Izumi --- drivers/acpi/pci_bind.c | 10 +++++----- drivers/acpi/pci_irq.c | 17 ++++++++--------- drivers/acpi/pci_root.c | 5 +++-- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 2ef04098cc1d..911144b22c89 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -49,7 +49,7 @@ static int acpi_pci_unbind(struct acpi_device *device) if (!dev->subordinate) goto out; - acpi_pci_irq_del_prt(dev->subordinate); + acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number); device->ops.bind = NULL; device->ops.unbind = NULL; @@ -63,7 +63,7 @@ static int acpi_pci_bind(struct acpi_device *device) { acpi_status status; acpi_handle handle; - struct pci_bus *bus; + unsigned char bus; struct pci_dev *dev; dev = acpi_get_pci_dev(device->handle); @@ -100,11 +100,11 @@ static int acpi_pci_bind(struct acpi_device *device) goto out; if (dev->subordinate) - bus = dev->subordinate; + bus = dev->subordinate->number; else - bus = dev->bus; + bus = dev->bus->number; - acpi_pci_irq_add_prt(device->handle, bus); + acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus); out: pci_dev_put(dev); diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 0eefa12e648c..8835cc38aa30 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, } } -static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, +static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, struct acpi_pci_routing_table *prt) { struct acpi_prt_entry *entry; @@ -198,8 +198,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert * it here. */ - entry->id.segment = pci_domain_nr(bus); - entry->id.bus = bus->number; + entry->id.segment = segment; + entry->id.bus = bus; entry->id.device = (prt->address >> 16) & 0xFFFF; entry->pin = prt->pin + 1; @@ -244,7 +244,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, return 0; } -int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) +int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) { acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -273,7 +273,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) entry = buffer.pointer; while (entry && (entry->length > 0)) { - acpi_pci_irq_add_entry(handle, bus, entry); + acpi_pci_irq_add_entry(handle, segment, bus, entry); entry = (struct acpi_pci_routing_table *) ((unsigned long)entry + entry->length); } @@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) return 0; } -void acpi_pci_irq_del_prt(struct pci_bus *bus) +void acpi_pci_irq_del_prt(int segment, int bus) { struct acpi_prt_entry *entry, *tmp; printk(KERN_DEBUG "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", - pci_domain_nr(bus), bus->number); + segment, bus); spin_lock(&acpi_prt_lock); list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { - if (pci_domain_nr(bus) == entry->id.segment - && bus->number == entry->id.bus) { + if (segment == entry->id.segment && bus == entry->id.bus) { list_del(&entry->list); kfree(entry); } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 012f40d1d75d..db31edaab9ce 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -554,7 +554,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) */ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_SUCCESS(status)) - result = acpi_pci_irq_add_prt(device->handle, root->bus); + result = acpi_pci_irq_add_prt(device->handle, root->segment, + root->secondary.start); /* * Scan and bind all _ADR-Based Devices @@ -682,7 +683,7 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_SUCCESS(status)) - acpi_pci_irq_del_prt(root->bus); + acpi_pci_irq_del_prt(root->segment, root->secondary.start); pci_remove_root_bus(root->bus); -- cgit v1.2.1 From d4761ba2d6adbe24c792ec6223a5884ae4e82430 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 30 Oct 2012 15:24:50 +0900 Subject: PCI/ACPI: Add _PRT interrupt routing info before enumerating devices We used to add the _PRT after enumerating devices behind a new host bridge. This moves the _PRT addition *before* the enumeration, since it no longer depends on the struct pci_bus existing. This is one step towards consolidating the .add/.start methods. Signed-off-by: Bjorn Helgaas Signed-off-by: Taku Izumi --- drivers/acpi/pci_root.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index db31edaab9ce..66f3ae74d130 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -501,6 +501,20 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); device->driver_data = root; + printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", + acpi_device_name(device), acpi_device_bid(device), + root->segment, &root->secondary); + + /* + * 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->segment, + root->secondary.start); + root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); /* @@ -518,10 +532,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) list_add_tail(&root->node, &acpi_pci_roots); mutex_unlock(&acpi_pci_root_lock); - printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", - acpi_device_name(device), acpi_device_bid(device), - root->segment, &root->secondary); - /* * Scan the Root Bridge * -------------------- @@ -547,16 +557,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) if (result) 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->segment, - root->secondary.start); - /* * Scan and bind all _ADR-Based Devices */ @@ -635,6 +635,8 @@ out_del_root: mutex_lock(&acpi_pci_root_lock); list_del(&root->node); mutex_unlock(&acpi_pci_root_lock); + + acpi_pci_irq_del_prt(root->segment, root->secondary.start); end: kfree(root); return result; -- cgit v1.2.1 From 642c92da36ae0bed3c31fdd408411ab95f4e326b Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Tue, 30 Oct 2012 15:26:18 +0900 Subject: PCI: Don't pass pci_dev to pci_ext_cfg_avail() pci_ext_cfg_avail() doesn't use the "struct pci_dev *" passed to it, and there's no requirement that a host bridge even be represented by a pci_dev. This drops the pci_ext_cfg_avail() parameter. [bhelgaas: changelog] Signed-off-by: Taku Izumi Signed-off-by: Bjorn Helgaas --- drivers/acpi/pci_root.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 66f3ae74d130..50f329d7ccff 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -564,7 +564,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) acpi_pci_bridge_scan(child); /* Indicate support for various _OSC capabilities. */ - if (pci_ext_cfg_avail(root->bus->self)) + if (pci_ext_cfg_avail()) flags |= OSC_EXT_PCI_CONFIG_SUPPORT; if (pcie_aspm_support_enabled()) flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | -- cgit v1.2.1 From 8c33f51df406e1a1f7fa4e9b244845b7ebd61fa6 Mon Sep 17 00:00:00 2001 From: Taku Izumi Date: Tue, 30 Oct 2012 15:27:13 +0900 Subject: PCI/ACPI: Request _OSC control before scanning PCI root bus This patch moves up the code block to request _OSC control in order to separate ACPI work and PCI work in acpi_pci_root_add(). Signed-off-by: Taku Izumi Signed-off-by: Bjorn Helgaas --- drivers/acpi/pci_root.c | 121 +++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 59 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 50f329d7ccff..ab781f00e32d 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -454,6 +454,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) acpi_handle handle; struct acpi_device *child; u32 flags, base_flags; + bool is_osc_granted = false; root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); if (!root) @@ -524,6 +525,60 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; acpi_pci_osc_support(root, flags); + /* Indicate support for various _OSC capabilities. */ + if (pci_ext_cfg_avail()) + flags |= OSC_EXT_PCI_CONFIG_SUPPORT; + if (pcie_aspm_support_enabled()) { + flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | + OSC_CLOCK_PWR_CAPABILITY_SUPPORT; + } + if (pci_msi_enabled()) + flags |= OSC_MSI_SUPPORT; + if (flags != base_flags) { + status = acpi_pci_osc_support(root, flags); + if (ACPI_FAILURE(status)) { + dev_info(&device->dev, "ACPI _OSC support " + "notification failed, disabling PCIe ASPM\n"); + pcie_no_aspm(); + flags = base_flags; + } + } + if (!pcie_ports_disabled + && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { + flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL + | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL + | OSC_PCI_EXPRESS_PME_CONTROL; + + if (pci_aer_available()) { + if (aer_acpi_firmware_first()) + dev_dbg(&device->dev, + "PCIe errors handled by BIOS.\n"); + else + flags |= OSC_PCI_EXPRESS_AER_CONTROL; + } + + dev_info(&device->dev, + "Requesting ACPI _OSC control (0x%02x)\n", flags); + + status = acpi_pci_osc_control_set(device->handle, &flags, + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + if (ACPI_SUCCESS(status)) { + is_osc_granted = true; + dev_info(&device->dev, + "ACPI _OSC control (0x%02x) granted\n", flags); + } else { + is_osc_granted = false; + dev_info(&device->dev, + "ACPI _OSC request failed (%s), " + "returned control mask: 0x%02x\n", + acpi_format_exception(status), flags); + } + } else { + dev_info(&device->dev, + "Unable to request _OSC control " + "(_OSC support mask: 0x%02x)\n", flags); + } + /* * TBD: Need PCI interface for enumeration/configuration of roots. */ @@ -563,66 +618,14 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) list_for_each_entry(child, &device->children, node) acpi_pci_bridge_scan(child); - /* Indicate support for various _OSC capabilities. */ - if (pci_ext_cfg_avail()) - flags |= OSC_EXT_PCI_CONFIG_SUPPORT; - if (pcie_aspm_support_enabled()) - flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | - OSC_CLOCK_PWR_CAPABILITY_SUPPORT; - if (pci_msi_enabled()) - flags |= OSC_MSI_SUPPORT; - if (flags != base_flags) { - status = acpi_pci_osc_support(root, flags); - if (ACPI_FAILURE(status)) { - dev_info(root->bus->bridge, "ACPI _OSC support " - "notification failed, disabling PCIe ASPM\n"); - pcie_no_aspm(); - flags = base_flags; - } - } - - if (!pcie_ports_disabled - && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { - flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL - | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL - | OSC_PCI_EXPRESS_PME_CONTROL; - - if (pci_aer_available()) { - if (aer_acpi_firmware_first()) - dev_dbg(root->bus->bridge, - "PCIe errors handled by BIOS.\n"); - else - flags |= OSC_PCI_EXPRESS_AER_CONTROL; - } - - dev_info(root->bus->bridge, - "Requesting ACPI _OSC control (0x%02x)\n", flags); - - status = acpi_pci_osc_control_set(device->handle, &flags, - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); - if (ACPI_SUCCESS(status)) { - dev_info(root->bus->bridge, - "ACPI _OSC control (0x%02x) granted\n", flags); - if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { - /* - * We have ASPM control, but the FADT indicates - * that it's unsupported. Clear it. - */ - pcie_clear_aspm(root->bus); - } - } else { - dev_info(root->bus->bridge, - "ACPI _OSC request failed (%s), " - "returned control mask: 0x%02x\n", - acpi_format_exception(status), flags); - pr_info("ACPI _OSC control for PCIe not granted, " - "disabling ASPM\n"); - pcie_no_aspm(); - } + /* ASPM setting */ + if (is_osc_granted) { + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) + pcie_clear_aspm(root->bus); } else { - dev_info(root->bus->bridge, - "Unable to request _OSC control " - "(_OSC support mask: 0x%02x)\n", flags); + pr_info("ACPI _OSC control for PCIe not granted, " + "disabling ASPM\n"); + pcie_no_aspm(); } pci_acpi_add_bus_pm_notifier(device, root->bus); -- cgit v1.2.1 From 71fbad6c9a28629b6af40b0ff48f36c6610a1394 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Wed, 7 Nov 2012 08:57:59 +0800 Subject: PCI/ACPI: Notify PCI devices when their power resource is turned on This patch reduces power consumption by allowing idle devices to go to a low power state after another device on the same power resource has been awakened. A power resource may be shared by multiple devices. When all devices sharing a power resource are put into D3_COLD state, the power resource will be turned off. When one of the devices is awakened, the power resource will be turned on and all devices sharing it will be powered on to D0uninitialized state. These devices should be resumed, so that they have the opportunity to go to low power state later. [bhelgaas: changelog] Signed-off-by: Huang Ying Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/acpi/pci_bind.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 2ef04098cc1d..f1ea71c80ab6 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -45,6 +45,7 @@ static int acpi_pci_unbind(struct acpi_device *device) device_set_run_wake(&dev->dev, false); pci_acpi_remove_pm_notifier(device); + acpi_power_resource_unregister_device(&dev->dev, device->handle); if (!dev->subordinate) goto out; @@ -71,6 +72,7 @@ static int acpi_pci_bind(struct acpi_device *device) return 0; pci_acpi_add_pm_notifier(device, dev); + acpi_power_resource_register_device(&dev->dev, device->handle); if (device->wakeup.flags.run_wake) device_set_run_wake(&dev->dev, true); -- cgit v1.2.1