PCI: Introduce platform_pci_power_manageable function
Introduce function pointer platform_pci_power_manageable to be used by the platform-related code to point to a function allowing us to check if given device is power manageable by the platform. Introduce acpi_pci_power_manageable() playing that role for ACPI. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
committed by
Jesse Barnes
parent
3737b2b104
commit
961d9120fa
@@ -215,7 +215,6 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pci_osc_control_set);
|
EXPORT_SYMBOL(pci_osc_control_set);
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI_SLEEP
|
|
||||||
/*
|
/*
|
||||||
* _SxD returns the D-state with the highest power
|
* _SxD returns the D-state with the highest power
|
||||||
* (lowest D-state number) supported in the S-state "x".
|
* (lowest D-state number) supported in the S-state "x".
|
||||||
@@ -259,7 +258,13 @@ static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
|
|||||||
}
|
}
|
||||||
return PCI_POWER_ERROR;
|
return PCI_POWER_ERROR;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
static bool acpi_pci_power_manageable(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
|
||||||
|
|
||||||
|
return handle ? acpi_bus_power_manageable(handle) : false;
|
||||||
|
}
|
||||||
|
|
||||||
static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||||
{
|
{
|
||||||
@@ -290,6 +295,11 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
/* ACPI bus type */
|
/* ACPI bus type */
|
||||||
static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
|
static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
|
||||||
@@ -341,10 +351,7 @@ static int __init acpi_pci_init(void)
|
|||||||
ret = register_acpi_bus_type(&acpi_pci_bus);
|
ret = register_acpi_bus_type(&acpi_pci_bus);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef CONFIG_ACPI_SLEEP
|
pci_set_platform_pm(&acpi_pci_platform_pm);
|
||||||
platform_pci_choose_state = acpi_pci_choose_state;
|
|
||||||
#endif
|
|
||||||
platform_pci_set_power_state = acpi_pci_set_power_state;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arch_initcall(acpi_pci_init);
|
arch_initcall(acpi_pci_init);
|
||||||
|
@@ -376,7 +376,32 @@ pci_restore_bars(struct pci_dev *dev)
|
|||||||
pci_update_resource(dev, &dev->resource[i], i);
|
pci_update_resource(dev, &dev->resource[i], i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
|
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)
|
||||||
|
return -EINVAL;
|
||||||
|
pci_platform_pm = ops;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool platform_pci_power_manageable(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
return pci_platform_pm ? pci_platform_pm->is_manageable(dev) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int platform_pci_set_power_state(struct pci_dev *dev,
|
||||||
|
pci_power_t t)
|
||||||
|
{
|
||||||
|
return pci_platform_pm ? pci_platform_pm->set_state(dev, t) : -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
return pci_platform_pm ?
|
||||||
|
pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_set_power_state - Set the power state of a PCI device
|
* pci_set_power_state - Set the power state of a PCI device
|
||||||
@@ -479,8 +504,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||||||
* Give firmware a chance to be called, such as ACPI _PRx, _PSx
|
* Give firmware a chance to be called, such as ACPI _PRx, _PSx
|
||||||
* Firmware method after native method ?
|
* Firmware method after native method ?
|
||||||
*/
|
*/
|
||||||
if (platform_pci_set_power_state)
|
platform_pci_set_power_state(dev, state);
|
||||||
platform_pci_set_power_state(dev, state);
|
|
||||||
|
|
||||||
dev->current_state = state;
|
dev->current_state = state;
|
||||||
|
|
||||||
@@ -505,8 +529,6 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_choose_state - Choose the power state of a PCI device
|
* pci_choose_state - Choose the power state of a PCI device
|
||||||
* @dev: PCI device to be suspended
|
* @dev: PCI device to be suspended
|
||||||
@@ -524,11 +546,9 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
|
|||||||
if (!pci_find_capability(dev, PCI_CAP_ID_PM))
|
if (!pci_find_capability(dev, PCI_CAP_ID_PM))
|
||||||
return PCI_D0;
|
return PCI_D0;
|
||||||
|
|
||||||
if (platform_pci_choose_state) {
|
ret = platform_pci_choose_state(dev);
|
||||||
ret = platform_pci_choose_state(dev);
|
if (ret != PCI_POWER_ERROR)
|
||||||
if (ret != PCI_POWER_ERROR)
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state.event) {
|
switch (state.event) {
|
||||||
case PM_EVENT_ON:
|
case PM_EVENT_ON:
|
||||||
|
@@ -5,10 +5,28 @@ extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
|
|||||||
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
|
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
|
||||||
extern void pci_cleanup_rom(struct pci_dev *dev);
|
extern void pci_cleanup_rom(struct pci_dev *dev);
|
||||||
|
|
||||||
/* Firmware callbacks */
|
/**
|
||||||
extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev);
|
* Firmware PM callbacks
|
||||||
extern int (*platform_pci_set_power_state)(struct pci_dev *dev,
|
*
|
||||||
pci_power_t state);
|
* @is_manageable - returns 'true' if given device is power manageable by the
|
||||||
|
* platform firmware
|
||||||
|
*
|
||||||
|
* @set_state - invokes the platform firmware to set the device's power state
|
||||||
|
*
|
||||||
|
* @choose_state - returns PCI power state of given device preferred by the
|
||||||
|
* platform; to be used during system-wide transitions from a
|
||||||
|
* sleeping state to the working state and vice versa
|
||||||
|
*
|
||||||
|
* If given platform is generally capable of power managing PCI devices, all of
|
||||||
|
* these callbacks are mandatory.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
|
||||||
|
|
||||||
extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
|
extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
|
||||||
extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
|
extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
|
||||||
|
Reference in New Issue
Block a user