Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2e5f0c1 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

ACPI / PCI: Rework the setup and cleanup of device wakeup



Currently, the ACPI wakeup capability of PCI devices is set up
in two different places, partially in acpi_pci_bind() where
runtime wakeup is initialized and partially in
platform_pci_wakeup_init(), where system wakeup is initialized.
The cleanup is only done in acpi_pci_unbind() and it only covers
runtime wakeup.

Use the new .setup() and .cleanup() callbacks in struct acpi_bus_type
to consolidate that code and do the setup and the cleanup each in one
place.

Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarYinghai Lu <yinghai@kernel.org>
Acked-by: default avatarToshi Kani <toshi.kani@hp.com>
parent 11909ca1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -353,7 +353,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 * acpi_dev_pm_get_node - Get ACPI device node for the given physical device.
 * @dev: Device to get the ACPI node for.
 */
static struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
{
	acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
	struct acpi_device *adev;
+0 −5
Original line number Diff line number Diff line
@@ -43,8 +43,6 @@ static int acpi_pci_unbind(struct acpi_device *device)
	if (!dev)
		goto out;

	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)
@@ -71,10 +69,7 @@ static int acpi_pci_bind(struct acpi_device *device)
	if (!dev)
		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);

	/*
	 * Install the 'bind' function to facilitate callbacks for
+29 −1
Original line number Diff line number Diff line
@@ -283,7 +283,6 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
	.is_manageable = acpi_pci_power_manageable,
	.set_state = acpi_pci_set_power_state,
	.choose_state = acpi_pci_choose_state,
	.can_wakeup = acpi_pci_can_wakeup,
	.sleep_wake = acpi_pci_sleep_wake,
	.run_wake = acpi_pci_run_wake,
};
@@ -321,10 +320,39 @@ static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
	return 0;
}

static void acpi_pci_wakeup_setup(struct device *dev)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
	struct pci_dev *pci_dev = to_pci_dev(dev);

	if (!adev || !adev->wakeup.flags.valid)
		return;

	device_set_wakeup_capable(dev, true);
	acpi_pci_sleep_wake(pci_dev, false);

	pci_acpi_add_pm_notifier(adev, pci_dev);
	if (adev->wakeup.flags.run_wake)
		device_set_run_wake(dev, true);
}

static void acpi_pci_wakeup_cleanup(struct device *dev)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);

	if (adev && adev->wakeup.flags.valid) {
		device_set_wakeup_capable(dev, false);
		device_set_run_wake(dev, false);
		pci_acpi_remove_pm_notifier(adev);
	}
}

static struct acpi_bus_type acpi_pci_bus = {
	.bus = &pci_bus_type,
	.find_device = acpi_pci_find_device,
	.find_bridge = acpi_pci_find_root_bridge,
	.setup = acpi_pci_wakeup_setup,
	.cleanup = acpi_pci_wakeup_cleanup,
};

static int __init acpi_pci_init(void)
+1 −25
Original line number Diff line number Diff line
@@ -450,7 +450,7 @@ static struct pci_platform_pm_ops *pci_platform_pm;
int pci_set_platform_pm(struct pci_platform_pm_ops *ops)
{
	if (!ops->is_manageable || !ops->set_state || !ops->choose_state
	    || !ops->sleep_wake || !ops->can_wakeup)
	    || !ops->sleep_wake)
		return -EINVAL;
	pci_platform_pm = ops;
	return 0;
@@ -473,11 +473,6 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev)
			pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR;
}

static inline bool platform_pci_can_wakeup(struct pci_dev *dev)
{
	return pci_platform_pm ? pci_platform_pm->can_wakeup(dev) : false;
}

static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
{
	return pci_platform_pm ?
@@ -1985,25 +1980,6 @@ void pci_pm_init(struct pci_dev *dev)
	}
}

/**
 * platform_pci_wakeup_init - init platform wakeup if present
 * @dev: PCI device
 *
 * Some devices don't have PCI PM caps but can still generate wakeup
 * events through platform methods (like ACPI events).  If @dev supports
 * platform wakeup events, set the device flag to indicate as much.  This
 * may be redundant if the device also supports PCI PM caps, but double
 * initialization should be safe in that case.
 */
void platform_pci_wakeup_init(struct pci_dev *dev)
{
	if (!platform_pci_can_wakeup(dev))
		return;

	device_set_wakeup_capable(&dev->dev, true);
	platform_pci_sleep_wake(dev, false);
}

static void pci_add_saved_cap(struct pci_dev *pci_dev,
	struct pci_cap_saved_state *new_cap)
{
+0 −5
Original line number Diff line number Diff line
@@ -43,9 +43,6 @@ int pci_probe_reset_function(struct pci_dev *dev);
 *                platform; to be used during system-wide transitions from a
 *                sleeping state to the working state and vice versa
 *
 * @can_wakeup: returns 'true' if given device is capable of waking up the
 *              system from a sleeping state
 *
 * @sleep_wake: enables/disables the system wake up capability of given device
 *
 * @run_wake: enables/disables the platform to generate run-time wake-up events
@@ -59,7 +56,6 @@ struct pci_platform_pm_ops {
	bool (*is_manageable)(struct pci_dev *dev);
	int (*set_state)(struct pci_dev *dev, pci_power_t state);
	pci_power_t (*choose_state)(struct pci_dev *dev);
	bool (*can_wakeup)(struct pci_dev *dev);
	int (*sleep_wake)(struct pci_dev *dev, bool enable);
	int (*run_wake)(struct pci_dev *dev, bool enable);
};
@@ -74,7 +70,6 @@ extern void pci_wakeup_bus(struct pci_bus *bus);
extern void pci_config_pm_runtime_get(struct pci_dev *dev);
extern void pci_config_pm_runtime_put(struct pci_dev *dev);
extern void pci_pm_init(struct pci_dev *dev);
extern void platform_pci_wakeup_init(struct pci_dev *dev);
extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
void pci_free_cap_save_buffers(struct pci_dev *dev);

Loading