/** * acpi_dev_pm_attach - Prepare device for ACPI power management. * @dev: Device to prepare. * @power_on: Whether or not to power on the device. * * If @dev has a valid ACPI handle that has a valid struct acpi_device object * attached to it, install a wakeup notification handler for the device and * add it to the general ACPI PM domain. If @power_on is set, the device will * be put into the ACPI D0 state before the function returns. * * This assumes that the @dev's bus type uses generic power management callbacks * (or doesn't use any power management callbacks at all). * * Callers must ensure proper synchronization of this function with power * management callbacks. */ int acpi_dev_pm_attach(struct device *dev, bool power_on) { struct acpi_device *adev = acpi_dev_pm_get_node(dev); if (!adev) return -ENODEV; if (dev->pm_domain) return -EEXIST; /* * Only attach the power domain to the first device if the * companion is shared by multiple. This is to prevent doing power * management twice. */ if (!acpi_device_is_first_physical_node(adev, dev)) return -EBUSY; acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); dev_pm_domain_set(dev, &acpi_general_pm_domain); if (power_on) { acpi_dev_pm_full_power(adev); __acpi_device_run_wake(adev, false); } return 0; }
/** * acpi_dev_pm_attach - Prepare device for ACPI power management. * @dev: Device to prepare. * @power_on: Whether or not to power on the device. * * If @dev has a valid ACPI handle that has a valid struct acpi_device object * attached to it, install a wakeup notification handler for the device and * add it to the general ACPI PM domain. If @power_on is set, the device will * be put into the ACPI D0 state before the function returns. * * This assumes that the @dev's bus type uses generic power management callbacks * (or doesn't use any power management callbacks at all). * * Callers must ensure proper synchronization of this function with power * management callbacks. */ int acpi_dev_pm_attach(struct device *dev, bool power_on) { struct acpi_device *adev = ACPI_COMPANION(dev); if (!adev) return -ENODEV; if (!strcmp(dev_name(dev), "80860F28:00")) { dev_info(dev, "Skipping ACPI power domain attach\n"); return -ENODEV; } if (dev->pm_domain) return -EEXIST; acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); dev->pm_domain = &acpi_general_pm_domain; if (power_on) { acpi_dev_pm_full_power(adev); __acpi_device_run_wake(adev, false); } dev->pm_domain->detach = acpi_dev_pm_detach; return 0; }
/** * acpi_dev_runtime_resume - Put device into the full-power state using ACPI. * @dev: Device to put into the full-power state. * * Put the given device into the full-power state using the standard ACPI * mechanism at run time. Set the power state of the device to ACPI D0 and * disable remote wakeup. */ int acpi_dev_runtime_resume(struct device *dev) { struct acpi_device *adev = acpi_dev_pm_get_node(dev); int error; if (!adev) return 0; error = acpi_dev_pm_full_power(adev); __acpi_device_run_wake(adev, false); return error; }
/** * acpi_dev_runtime_suspend - Put device into a low-power state using ACPI. * @dev: Device to put into a low-power state. * * Put the given device into a runtime low-power state using the standard ACPI * mechanism. Set up remote wakeup if desired, choose the state to put the * device into (this checks if remote wakeup is expected to work too), and set * the power state of the device. */ int acpi_dev_runtime_suspend(struct device *dev) { struct acpi_device *adev = acpi_dev_pm_get_node(dev); bool remote_wakeup; int error; if (!adev) return 0; remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) > PM_QOS_FLAGS_NONE; error = __acpi_device_run_wake(adev, remote_wakeup); if (remote_wakeup && error) return -EAGAIN; error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); if (error) __acpi_device_run_wake(adev, false); return error; }
/** * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. * @dev: Device to enable/disable the platform to wake up. * @enable: Whether to enable or disable the wakeup functionality. */ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) { struct acpi_device *adev; acpi_handle handle; if (!device_run_wake(phys_dev)) return -EINVAL; handle = ACPI_HANDLE(phys_dev); if (!handle || acpi_bus_get_device(handle, &adev)) { dev_dbg(phys_dev, "ACPI handle without context in %s!\n", __func__); return -ENODEV; } return __acpi_device_run_wake(adev, enable); }
/** * acpi_dev_pm_attach - Prepare device for ACPI power management. * @dev: Device to prepare. * @power_on: Whether or not to power on the device. * * If @dev has a valid ACPI handle that has a valid struct acpi_device object * attached to it, install a wakeup notification handler for the device and * add it to the general ACPI PM domain. If @power_on is set, the device will * be put into the ACPI D0 state before the function returns. * * This assumes that the @dev's bus type uses generic power management callbacks * (or doesn't use any power management callbacks at all). * * Callers must ensure proper synchronization of this function with power * management callbacks. */ int acpi_dev_pm_attach(struct device *dev, bool power_on) { struct acpi_device *adev = acpi_dev_pm_get_node(dev); if (!adev) return -ENODEV; if (dev->pm_domain) return -EEXIST; acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); dev->pm_domain = &acpi_general_pm_domain; if (power_on) { acpi_dev_pm_full_power(adev); __acpi_device_run_wake(adev, false); } return 0; }
/** * acpi_dev_pm_detach - Remove ACPI power management from the device. * @dev: Device to take care of. * @power_off: Whether or not to try to remove power from the device. * * Remove the device from the general ACPI PM domain and remove its wakeup * notifier. If @power_off is set, additionally remove power from the device if * possible. * * Callers must ensure proper synchronization of this function with power * management callbacks. */ void acpi_dev_pm_detach(struct device *dev, bool power_off) { struct acpi_device *adev = acpi_dev_pm_get_node(dev); if (adev && dev->pm_domain == &acpi_general_pm_domain) { dev->pm_domain = NULL; acpi_remove_pm_notifier(adev, acpi_wakeup_device); if (power_off) { /* * If the device's PM QoS resume latency limit or flags * have been exposed to user space, they have to be * hidden at this point, so that they don't affect the * choice of the low-power state to put the device into. */ dev_pm_qos_hide_latency_limit(dev); dev_pm_qos_hide_flags(dev); __acpi_device_run_wake(adev, false); acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); } } }