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: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> Acked-by: Toshi Kani <toshi.kani@hp.com>
This commit is contained in:
		
					parent
					
						
							
								11909ca1cf
							
						
					
				
			
			
				commit
				
					
						d2e5f0c16a
					
				
			
		
					 7 changed files with 36 additions and 38 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1280,7 +1280,6 @@ static void pci_init_capabilities(struct pci_dev *dev)
 | 
			
		|||
 | 
			
		||||
	/* Power Management */
 | 
			
		||||
	pci_pm_init(dev);
 | 
			
		||||
	platform_pci_wakeup_init(dev);
 | 
			
		||||
 | 
			
		||||
	/* Vital Product Data */
 | 
			
		||||
	pci_vpd_pci22_init(dev);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -526,9 +526,14 @@ static inline int acpi_subsys_resume_early(struct device *dev) { return 0; }
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_ACPI) && defined(CONFIG_PM)
 | 
			
		||||
struct acpi_device *acpi_dev_pm_get_node(struct device *dev);
 | 
			
		||||
int acpi_dev_pm_attach(struct device *dev, bool power_on);
 | 
			
		||||
void acpi_dev_pm_detach(struct device *dev, bool power_off);
 | 
			
		||||
#else
 | 
			
		||||
static inline struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
 | 
			
		||||
{
 | 
			
		||||
	return -ENODEV;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue