#include <linux/pci-acpi.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
#include "pci.h"
-static DEFINE_MUTEX(pci_acpi_pm_notify_mtx);
-
/**
* pci_acpi_wake_bus - Wake-up notification handler for root buses.
* @handle: ACPI handle of a device the notification is for.
pci_pme_wakeup_bus(pci_dev->subordinate);
}
-/**
- * add_pm_notifier - Register PM notifier for given ACPI device.
- * @dev: ACPI device to add the notifier for.
- * @context: PCI device or bus to check for PME status if an event is signaled.
- *
- * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of
- * PM wake-up events. For example, wake-up events may be generated for bridges
- * if one of the devices below the bridge is signaling PME, even if the bridge
- * itself doesn't have a wake-up GPE associated with it.
- */
-static acpi_status add_pm_notifier(struct acpi_device *dev,
- acpi_notify_handler handler,
- void *context)
-{
- acpi_status status = AE_ALREADY_EXISTS;
-
- mutex_lock(&pci_acpi_pm_notify_mtx);
-
- if (dev->wakeup.flags.notifier_present)
- goto out;
-
- status = acpi_install_notify_handler(dev->handle,
- ACPI_SYSTEM_NOTIFY,
- handler, context);
- if (ACPI_FAILURE(status))
- goto out;
-
- dev->wakeup.flags.notifier_present = true;
-
- out:
- mutex_unlock(&pci_acpi_pm_notify_mtx);
- return status;
-}
-
-/**
- * remove_pm_notifier - Unregister PM notifier from given ACPI device.
- * @dev: ACPI device to remove the notifier from.
- */
-static acpi_status remove_pm_notifier(struct acpi_device *dev,
- acpi_notify_handler handler)
-{
- acpi_status status = AE_BAD_PARAMETER;
-
- mutex_lock(&pci_acpi_pm_notify_mtx);
-
- if (!dev->wakeup.flags.notifier_present)
- goto out;
-
- status = acpi_remove_notify_handler(dev->handle,
- ACPI_SYSTEM_NOTIFY,
- handler);
- if (ACPI_FAILURE(status))
- goto out;
-
- dev->wakeup.flags.notifier_present = false;
-
- out:
- mutex_unlock(&pci_acpi_pm_notify_mtx);
- return status;
-}
-
/**
* pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus.
* @dev: ACPI device to add the notifier for.
acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
struct pci_bus *pci_bus)
{
- return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
+ return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
}
/**
*/
acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
{
- return remove_pm_notifier(dev, pci_acpi_wake_bus);
+ return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus);
}
/**
acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
struct pci_dev *pci_dev)
{
- return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
+ return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
}
/**
*/
acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
{
- return remove_pm_notifier(dev, pci_acpi_wake_dev);
+ return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev);
}
phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
return -ENODEV;
switch (state) {
+ case PCI_D3cold:
+ if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
+ PM_QOS_FLAGS_ALL) {
+ error = -EBUSY;
+ break;
+ }
case PCI_D0:
case PCI_D1:
case PCI_D2:
case PCI_D3hot:
- case PCI_D3cold:
error = acpi_bus_set_power(handle, state_conv[state]);
}