forked from Minki/linux
Merge branch 'pm-pci'
Merge PCI device power management updates for 5.16-rc1: - Make the association of ACPI device objects with PCI devices more straightforward and simplify the code doing that for all devices in general (Rafael Wysocki). - Eliminate struct pci_platform_pm_ops and handle the both of its users (PCI and Intel MID) directly in the PCI bus code (Rafael Wysocki). - Simplify and clarify ACPI PCI device PM helpers (Rafael Wysocki). - Fix ordering of operations in pci_back_from_sleep() (Rafael Wysocki). * pm-pci: PCI: PM: Fix ordering of operations in pci_back_from_sleep() PCI: PM: Do not call platform_pci_power_manageable() unnecessarily PCI: PM: Make pci_choose_state() call pci_target_state() PCI: PM: Rearrange pci_target_state() PCI: PM: Simplify acpi_pci_power_manageable() PCI: PM: Drop struct pci_platform_pm_ops PCI: ACPI: PM: Do not use pci_platform_pm_ops for ACPI PCI: PM: Do not use pci_platform_pm_ops for Intel MID PM ACPI: glue: Look for ACPI bus type only if ACPI companion is not known ACPI: glue: Drop cleanup callback from struct acpi_bus_type PCI: ACPI: Drop acpi_pci_bus
This commit is contained in:
commit
1fec16118f
@ -17,6 +17,8 @@
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "internal.h"
|
||||
@ -287,12 +289,13 @@ EXPORT_SYMBOL_GPL(acpi_unbind_one);
|
||||
|
||||
void acpi_device_notify(struct device *dev)
|
||||
{
|
||||
struct acpi_bus_type *type = acpi_get_bus_type(dev);
|
||||
struct acpi_device *adev;
|
||||
int ret;
|
||||
|
||||
ret = acpi_bind_one(dev, NULL);
|
||||
if (ret) {
|
||||
struct acpi_bus_type *type = acpi_get_bus_type(dev);
|
||||
|
||||
if (!type)
|
||||
goto err;
|
||||
|
||||
@ -304,17 +307,26 @@ void acpi_device_notify(struct device *dev)
|
||||
ret = acpi_bind_one(dev, adev);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (type->setup) {
|
||||
type->setup(dev);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
adev = ACPI_COMPANION(dev);
|
||||
|
||||
if (dev_is_pci(dev)) {
|
||||
pci_acpi_setup(dev, adev);
|
||||
goto done;
|
||||
} else if (dev_is_platform(dev)) {
|
||||
acpi_configure_pmsi_domain(dev);
|
||||
}
|
||||
}
|
||||
adev = ACPI_COMPANION(dev);
|
||||
|
||||
if (dev_is_platform(dev))
|
||||
acpi_configure_pmsi_domain(dev);
|
||||
|
||||
if (type && type->setup)
|
||||
type->setup(dev);
|
||||
else if (adev->handler && adev->handler->bind)
|
||||
if (adev->handler && adev->handler->bind)
|
||||
adev->handler->bind(dev);
|
||||
|
||||
done:
|
||||
acpi_handle_debug(ACPI_HANDLE(dev), "Bound to device %s\n",
|
||||
dev_name(dev));
|
||||
|
||||
@ -327,14 +339,12 @@ err:
|
||||
void acpi_device_notify_remove(struct device *dev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
struct acpi_bus_type *type;
|
||||
|
||||
if (!adev)
|
||||
return;
|
||||
|
||||
type = acpi_get_bus_type(dev);
|
||||
if (type && type->cleanup)
|
||||
type->cleanup(dev);
|
||||
if (dev_is_pci(dev))
|
||||
pci_acpi_cleanup(dev, adev);
|
||||
else if (adev->handler && adev->handler->unbind)
|
||||
adev->handler->unbind(dev);
|
||||
|
||||
|
@ -906,7 +906,7 @@ acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
|
||||
* choose highest power _SxD or any lower power
|
||||
*/
|
||||
|
||||
static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
|
||||
pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
|
||||
{
|
||||
int acpi_state, d_max;
|
||||
|
||||
@ -965,22 +965,20 @@ int pci_dev_acpi_reset(struct pci_dev *dev, bool probe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool acpi_pci_power_manageable(struct pci_dev *dev)
|
||||
bool acpi_pci_power_manageable(struct pci_dev *dev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
|
||||
|
||||
if (!adev)
|
||||
return false;
|
||||
return acpi_device_power_manageable(adev);
|
||||
return adev && acpi_device_power_manageable(adev);
|
||||
}
|
||||
|
||||
static bool acpi_pci_bridge_d3(struct pci_dev *dev)
|
||||
bool acpi_pci_bridge_d3(struct pci_dev *dev)
|
||||
{
|
||||
const union acpi_object *obj;
|
||||
struct acpi_device *adev;
|
||||
struct pci_dev *rpdev;
|
||||
|
||||
if (!dev->is_hotplug_bridge)
|
||||
if (acpi_pci_disabled || !dev->is_hotplug_bridge)
|
||||
return false;
|
||||
|
||||
/* Assume D3 support if the bridge is power-manageable by ACPI. */
|
||||
@ -1008,7 +1006,7 @@ static bool acpi_pci_bridge_d3(struct pci_dev *dev)
|
||||
return obj->integer.value == 1;
|
||||
}
|
||||
|
||||
static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
|
||||
static const u8 state_conv[] = {
|
||||
@ -1046,7 +1044,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
return error;
|
||||
}
|
||||
|
||||
static pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
|
||||
pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
|
||||
static const pci_power_t state_conv[] = {
|
||||
@ -1068,7 +1066,7 @@ static pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
|
||||
return state_conv[state];
|
||||
}
|
||||
|
||||
static void acpi_pci_refresh_power_state(struct pci_dev *dev)
|
||||
void acpi_pci_refresh_power_state(struct pci_dev *dev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
|
||||
|
||||
@ -1093,17 +1091,23 @@ static int acpi_pci_propagate_wakeup(struct pci_bus *bus, bool enable)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_pci_wakeup(struct pci_dev *dev, bool enable)
|
||||
int acpi_pci_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
if (acpi_pci_disabled)
|
||||
return 0;
|
||||
|
||||
if (acpi_pm_device_can_wakeup(&dev->dev))
|
||||
return acpi_pm_set_device_wakeup(&dev->dev, enable);
|
||||
|
||||
return acpi_pci_propagate_wakeup(dev->bus, enable);
|
||||
}
|
||||
|
||||
static bool acpi_pci_need_resume(struct pci_dev *dev)
|
||||
bool acpi_pci_need_resume(struct pci_dev *dev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
|
||||
struct acpi_device *adev;
|
||||
|
||||
if (acpi_pci_disabled)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* In some cases (eg. Samsung 305V4A) leaving a bridge in suspend over
|
||||
@ -1115,6 +1119,7 @@ static bool acpi_pci_need_resume(struct pci_dev *dev)
|
||||
if (pci_is_bridge(dev) && acpi_target_system_state() != ACPI_STATE_S0)
|
||||
return true;
|
||||
|
||||
adev = ACPI_COMPANION(&dev->dev);
|
||||
if (!adev || !acpi_device_power_manageable(adev))
|
||||
return false;
|
||||
|
||||
@ -1128,17 +1133,6 @@ static bool acpi_pci_need_resume(struct pci_dev *dev)
|
||||
return !!adev->power.flags.dsw_present;
|
||||
}
|
||||
|
||||
static const struct pci_platform_pm_ops acpi_pci_platform_pm = {
|
||||
.bridge_d3 = acpi_pci_bridge_d3,
|
||||
.is_manageable = acpi_pci_power_manageable,
|
||||
.set_state = acpi_pci_set_power_state,
|
||||
.get_state = acpi_pci_get_power_state,
|
||||
.refresh_state = acpi_pci_refresh_power_state,
|
||||
.choose_state = acpi_pci_choose_state,
|
||||
.set_wakeup = acpi_pci_wakeup,
|
||||
.need_resume = acpi_pci_need_resume,
|
||||
};
|
||||
|
||||
void acpi_pci_add_bus(struct pci_bus *bus)
|
||||
{
|
||||
union acpi_object *obj;
|
||||
@ -1356,13 +1350,9 @@ static void pci_acpi_set_external_facing(struct pci_dev *dev)
|
||||
dev->external_facing = 1;
|
||||
}
|
||||
|
||||
static void pci_acpi_setup(struct device *dev)
|
||||
void pci_acpi_setup(struct device *dev, struct acpi_device *adev)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
|
||||
if (!adev)
|
||||
return;
|
||||
|
||||
pci_acpi_optimize_delay(pci_dev, adev->handle);
|
||||
pci_acpi_set_external_facing(pci_dev);
|
||||
@ -1386,14 +1376,10 @@ static void pci_acpi_setup(struct device *dev)
|
||||
acpi_device_power_add_dependent(adev, dev);
|
||||
}
|
||||
|
||||
static void pci_acpi_cleanup(struct device *dev)
|
||||
void pci_acpi_cleanup(struct device *dev, struct acpi_device *adev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
|
||||
if (!adev)
|
||||
return;
|
||||
|
||||
pci_acpi_remove_edr_notifier(pci_dev);
|
||||
pci_acpi_remove_pm_notifier(adev);
|
||||
if (adev->wakeup.flags.valid) {
|
||||
@ -1405,20 +1391,6 @@ static void pci_acpi_cleanup(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static bool pci_acpi_bus_match(struct device *dev)
|
||||
{
|
||||
return dev_is_pci(dev);
|
||||
}
|
||||
|
||||
static struct acpi_bus_type acpi_pci_bus = {
|
||||
.name = "PCI",
|
||||
.match = pci_acpi_bus_match,
|
||||
.find_companion = acpi_pci_find_companion,
|
||||
.setup = pci_acpi_setup,
|
||||
.cleanup = pci_acpi_cleanup,
|
||||
};
|
||||
|
||||
|
||||
static struct fwnode_handle *(*pci_msi_get_fwnode_cb)(struct device *dev);
|
||||
|
||||
/**
|
||||
@ -1460,8 +1432,6 @@ struct irq_domain *pci_host_bridge_acpi_msi_domain(struct pci_bus *bus)
|
||||
|
||||
static int __init acpi_pci_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) {
|
||||
pr_info("ACPI FADT declares the system doesn't support MSI, so disable it\n");
|
||||
pci_no_msi();
|
||||
@ -1472,11 +1442,9 @@ static int __init acpi_pci_init(void)
|
||||
pcie_no_aspm();
|
||||
}
|
||||
|
||||
ret = register_acpi_bus_type(&acpi_pci_bus);
|
||||
if (ret)
|
||||
if (acpi_pci_disabled)
|
||||
return 0;
|
||||
|
||||
pci_set_platform_pm(&acpi_pci_platform_pm);
|
||||
acpi_pci_slot_init();
|
||||
acpiphp_init();
|
||||
|
||||
|
@ -16,45 +16,23 @@
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
static bool mid_pci_power_manageable(struct pci_dev *dev)
|
||||
static bool pci_mid_pm_enabled __read_mostly;
|
||||
|
||||
bool pci_use_mid_pm(void)
|
||||
{
|
||||
return true;
|
||||
return pci_mid_pm_enabled;
|
||||
}
|
||||
|
||||
static int mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state)
|
||||
int mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state)
|
||||
{
|
||||
return intel_mid_pci_set_power_state(pdev, state);
|
||||
}
|
||||
|
||||
static pci_power_t mid_pci_get_power_state(struct pci_dev *pdev)
|
||||
pci_power_t mid_pci_get_power_state(struct pci_dev *pdev)
|
||||
{
|
||||
return intel_mid_pci_get_power_state(pdev);
|
||||
}
|
||||
|
||||
static pci_power_t mid_pci_choose_state(struct pci_dev *pdev)
|
||||
{
|
||||
return PCI_D3hot;
|
||||
}
|
||||
|
||||
static int mid_pci_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool mid_pci_need_resume(struct pci_dev *dev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct pci_platform_pm_ops mid_pci_platform_pm = {
|
||||
.is_manageable = mid_pci_power_manageable,
|
||||
.set_state = mid_pci_set_power_state,
|
||||
.get_state = mid_pci_get_power_state,
|
||||
.choose_state = mid_pci_choose_state,
|
||||
.set_wakeup = mid_pci_wakeup,
|
||||
.need_resume = mid_pci_need_resume,
|
||||
};
|
||||
|
||||
/*
|
||||
* This table should be in sync with the one in
|
||||
* arch/x86/platform/intel-mid/pwr.c.
|
||||
@ -71,7 +49,8 @@ static int __init mid_pci_init(void)
|
||||
|
||||
id = x86_match_cpu(lpss_cpu_ids);
|
||||
if (id)
|
||||
pci_set_platform_pm(&mid_pci_platform_pm);
|
||||
pci_mid_pm_enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(mid_pci_init);
|
||||
|
@ -972,61 +972,67 @@ static void pci_restore_bars(struct pci_dev *dev)
|
||||
pci_update_resource(dev, i);
|
||||
}
|
||||
|
||||
static const struct pci_platform_pm_ops *pci_platform_pm;
|
||||
|
||||
int pci_set_platform_pm(const struct pci_platform_pm_ops *ops)
|
||||
{
|
||||
if (!ops->is_manageable || !ops->set_state || !ops->get_state ||
|
||||
!ops->choose_state || !ops->set_wakeup || !ops->need_resume)
|
||||
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;
|
||||
if (pci_use_mid_pm())
|
||||
return true;
|
||||
|
||||
return acpi_pci_power_manageable(dev);
|
||||
}
|
||||
|
||||
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;
|
||||
if (pci_use_mid_pm())
|
||||
return mid_pci_set_power_state(dev, t);
|
||||
|
||||
return acpi_pci_set_power_state(dev, t);
|
||||
}
|
||||
|
||||
static inline pci_power_t platform_pci_get_power_state(struct pci_dev *dev)
|
||||
{
|
||||
return pci_platform_pm ? pci_platform_pm->get_state(dev) : PCI_UNKNOWN;
|
||||
if (pci_use_mid_pm())
|
||||
return mid_pci_get_power_state(dev);
|
||||
|
||||
return acpi_pci_get_power_state(dev);
|
||||
}
|
||||
|
||||
static inline void platform_pci_refresh_power_state(struct pci_dev *dev)
|
||||
{
|
||||
if (pci_platform_pm && pci_platform_pm->refresh_state)
|
||||
pci_platform_pm->refresh_state(dev);
|
||||
if (!pci_use_mid_pm())
|
||||
acpi_pci_refresh_power_state(dev);
|
||||
}
|
||||
|
||||
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;
|
||||
if (pci_use_mid_pm())
|
||||
return PCI_POWER_ERROR;
|
||||
|
||||
return acpi_pci_choose_state(dev);
|
||||
}
|
||||
|
||||
static inline int platform_pci_set_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return pci_platform_pm ?
|
||||
pci_platform_pm->set_wakeup(dev, enable) : -ENODEV;
|
||||
if (pci_use_mid_pm())
|
||||
return PCI_POWER_ERROR;
|
||||
|
||||
return acpi_pci_wakeup(dev, enable);
|
||||
}
|
||||
|
||||
static inline bool platform_pci_need_resume(struct pci_dev *dev)
|
||||
{
|
||||
return pci_platform_pm ? pci_platform_pm->need_resume(dev) : false;
|
||||
if (pci_use_mid_pm())
|
||||
return false;
|
||||
|
||||
return acpi_pci_need_resume(dev);
|
||||
}
|
||||
|
||||
static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
|
||||
{
|
||||
if (pci_platform_pm && pci_platform_pm->bridge_d3)
|
||||
return pci_platform_pm->bridge_d3(dev);
|
||||
return false;
|
||||
if (pci_use_mid_pm())
|
||||
return false;
|
||||
|
||||
return acpi_pci_bridge_d3(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1185,9 +1191,7 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
|
||||
*/
|
||||
void pci_refresh_power_state(struct pci_dev *dev)
|
||||
{
|
||||
if (platform_pci_power_manageable(dev))
|
||||
platform_pci_refresh_power_state(dev);
|
||||
|
||||
platform_pci_refresh_power_state(dev);
|
||||
pci_update_current_state(dev, dev->current_state);
|
||||
}
|
||||
|
||||
@ -1200,14 +1204,10 @@ int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (platform_pci_power_manageable(dev)) {
|
||||
error = platform_pci_set_power_state(dev, state);
|
||||
if (!error)
|
||||
pci_update_current_state(dev, state);
|
||||
} else
|
||||
error = -ENODEV;
|
||||
|
||||
if (error && !dev->pm_cap) /* Fall back to PCI_D0 */
|
||||
error = platform_pci_set_power_state(dev, state);
|
||||
if (!error)
|
||||
pci_update_current_state(dev, state);
|
||||
else if (!dev->pm_cap) /* Fall back to PCI_D0 */
|
||||
dev->current_state = PCI_D0;
|
||||
|
||||
return error;
|
||||
@ -1388,44 +1388,6 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
}
|
||||
EXPORT_SYMBOL(pci_set_power_state);
|
||||
|
||||
/**
|
||||
* pci_choose_state - Choose the power state of a PCI device
|
||||
* @dev: PCI device to be suspended
|
||||
* @state: target sleep state for the whole system. This is the value
|
||||
* that is passed to suspend() function.
|
||||
*
|
||||
* Returns PCI power state suitable for given device and given system
|
||||
* message.
|
||||
*/
|
||||
pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
|
||||
{
|
||||
pci_power_t ret;
|
||||
|
||||
if (!dev->pm_cap)
|
||||
return PCI_D0;
|
||||
|
||||
ret = platform_pci_choose_state(dev);
|
||||
if (ret != PCI_POWER_ERROR)
|
||||
return ret;
|
||||
|
||||
switch (state.event) {
|
||||
case PM_EVENT_ON:
|
||||
return PCI_D0;
|
||||
case PM_EVENT_FREEZE:
|
||||
case PM_EVENT_PRETHAW:
|
||||
/* REVISIT both freeze and pre-thaw "should" use D0 */
|
||||
case PM_EVENT_SUSPEND:
|
||||
case PM_EVENT_HIBERNATE:
|
||||
return PCI_D3hot;
|
||||
default:
|
||||
pci_info(dev, "unrecognized suspend event %d\n",
|
||||
state.event);
|
||||
BUG();
|
||||
}
|
||||
return PCI_D0;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_choose_state);
|
||||
|
||||
#define PCI_EXP_SAVE_REGS 7
|
||||
|
||||
static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev,
|
||||
@ -2577,8 +2539,6 @@ EXPORT_SYMBOL(pci_wake_from_d3);
|
||||
*/
|
||||
static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
|
||||
{
|
||||
pci_power_t target_state = PCI_D3hot;
|
||||
|
||||
if (platform_pci_power_manageable(dev)) {
|
||||
/*
|
||||
* Call the platform to find the target state for the device.
|
||||
@ -2588,32 +2548,29 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
|
||||
switch (state) {
|
||||
case PCI_POWER_ERROR:
|
||||
case PCI_UNKNOWN:
|
||||
break;
|
||||
return PCI_D3hot;
|
||||
|
||||
case PCI_D1:
|
||||
case PCI_D2:
|
||||
if (pci_no_d1d2(dev))
|
||||
break;
|
||||
fallthrough;
|
||||
default:
|
||||
target_state = state;
|
||||
return PCI_D3hot;
|
||||
}
|
||||
|
||||
return target_state;
|
||||
return state;
|
||||
}
|
||||
|
||||
if (!dev->pm_cap)
|
||||
target_state = PCI_D0;
|
||||
|
||||
/*
|
||||
* If the device is in D3cold even though it's not power-manageable by
|
||||
* the platform, it may have been powered down by non-standard means.
|
||||
* Best to let it slumber.
|
||||
*/
|
||||
if (dev->current_state == PCI_D3cold)
|
||||
target_state = PCI_D3cold;
|
||||
return PCI_D3cold;
|
||||
else if (!dev->pm_cap)
|
||||
return PCI_D0;
|
||||
|
||||
if (wakeup && dev->pme_support) {
|
||||
pci_power_t state = target_state;
|
||||
pci_power_t state = PCI_D3hot;
|
||||
|
||||
/*
|
||||
* Find the deepest state from which the device can generate
|
||||
@ -2628,7 +2585,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup)
|
||||
return PCI_D0;
|
||||
}
|
||||
|
||||
return target_state;
|
||||
return PCI_D3hot;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2681,8 +2638,13 @@ EXPORT_SYMBOL(pci_prepare_to_sleep);
|
||||
*/
|
||||
int pci_back_from_sleep(struct pci_dev *dev)
|
||||
{
|
||||
int ret = pci_set_power_state(dev, PCI_D0);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pci_enable_wake(dev, PCI_D0, false);
|
||||
return pci_set_power_state(dev, PCI_D0);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_back_from_sleep);
|
||||
|
||||
@ -2842,6 +2804,22 @@ void pci_dev_complete_resume(struct pci_dev *pci_dev)
|
||||
spin_unlock_irq(&dev->power.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_choose_state - Choose the power state of a PCI device.
|
||||
* @dev: Target PCI device.
|
||||
* @state: Target state for the whole system.
|
||||
*
|
||||
* Returns PCI power state suitable for @dev and @state.
|
||||
*/
|
||||
pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
|
||||
{
|
||||
if (state.event == PM_EVENT_ON)
|
||||
return PCI_D0;
|
||||
|
||||
return pci_target_state(dev, false);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_choose_state);
|
||||
|
||||
void pci_config_pm_runtime_get(struct pci_dev *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -63,45 +63,6 @@ struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
|
||||
#define PCI_PM_D3HOT_WAIT 10 /* msec */
|
||||
#define PCI_PM_D3COLD_WAIT 100 /* msec */
|
||||
|
||||
/**
|
||||
* struct pci_platform_pm_ops - Firmware PM callbacks
|
||||
*
|
||||
* @bridge_d3: Does the bridge allow entering into D3
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @get_state: queries the platform firmware for a device's current power state
|
||||
*
|
||||
* @refresh_state: asks the platform to refresh the device's power state data
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @set_wakeup: enables/disables wakeup capability for the device
|
||||
*
|
||||
* @need_resume: returns 'true' if the given device (which is currently
|
||||
* suspended) needs to be resumed to be configured for system
|
||||
* wakeup.
|
||||
*
|
||||
* If given platform is generally capable of power managing PCI devices, all of
|
||||
* these callbacks are mandatory.
|
||||
*/
|
||||
struct pci_platform_pm_ops {
|
||||
bool (*bridge_d3)(struct pci_dev *dev);
|
||||
bool (*is_manageable)(struct pci_dev *dev);
|
||||
int (*set_state)(struct pci_dev *dev, pci_power_t state);
|
||||
pci_power_t (*get_state)(struct pci_dev *dev);
|
||||
void (*refresh_state)(struct pci_dev *dev);
|
||||
pci_power_t (*choose_state)(struct pci_dev *dev);
|
||||
int (*set_wakeup)(struct pci_dev *dev, bool enable);
|
||||
bool (*need_resume)(struct pci_dev *dev);
|
||||
};
|
||||
|
||||
int pci_set_platform_pm(const struct pci_platform_pm_ops *ops);
|
||||
void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
|
||||
void pci_refresh_power_state(struct pci_dev *dev);
|
||||
int pci_power_up(struct pci_dev *dev);
|
||||
@ -725,17 +686,53 @@ int pci_acpi_program_hp_params(struct pci_dev *dev);
|
||||
extern const struct attribute_group pci_dev_acpi_attr_group;
|
||||
void pci_set_acpi_fwnode(struct pci_dev *dev);
|
||||
int pci_dev_acpi_reset(struct pci_dev *dev, bool probe);
|
||||
bool acpi_pci_power_manageable(struct pci_dev *dev);
|
||||
bool acpi_pci_bridge_d3(struct pci_dev *dev);
|
||||
int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state);
|
||||
pci_power_t acpi_pci_get_power_state(struct pci_dev *dev);
|
||||
void acpi_pci_refresh_power_state(struct pci_dev *dev);
|
||||
int acpi_pci_wakeup(struct pci_dev *dev, bool enable);
|
||||
bool acpi_pci_need_resume(struct pci_dev *dev);
|
||||
pci_power_t acpi_pci_choose_state(struct pci_dev *pdev);
|
||||
#else
|
||||
static inline int pci_dev_acpi_reset(struct pci_dev *dev, bool probe)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
static inline void pci_set_acpi_fwnode(struct pci_dev *dev) {}
|
||||
static inline int pci_acpi_program_hp_params(struct pci_dev *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline bool acpi_pci_power_manageable(struct pci_dev *dev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline bool acpi_pci_bridge_d3(struct pci_dev *dev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
|
||||
{
|
||||
return PCI_UNKNOWN;
|
||||
}
|
||||
static inline void acpi_pci_refresh_power_state(struct pci_dev *dev) {}
|
||||
static inline int acpi_pci_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline bool acpi_pci_need_resume(struct pci_dev *dev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
|
||||
{
|
||||
return PCI_POWER_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCIEASPM
|
||||
@ -744,4 +741,23 @@ extern const struct attribute_group aspm_ctrl_attr_group;
|
||||
|
||||
extern const struct attribute_group pci_dev_reset_method_attr_group;
|
||||
|
||||
#ifdef CONFIG_X86_INTEL_MID
|
||||
bool pci_use_mid_pm(void);
|
||||
int mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state);
|
||||
pci_power_t mid_pci_get_power_state(struct pci_dev *pdev);
|
||||
#else
|
||||
static inline bool pci_use_mid_pm(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline int mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline pci_power_t mid_pci_get_power_state(struct pci_dev *pdev)
|
||||
{
|
||||
return PCI_UNKNOWN;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DRIVERS_PCI_H */
|
||||
|
@ -570,7 +570,6 @@ struct acpi_bus_type {
|
||||
bool (*match)(struct device *dev);
|
||||
struct acpi_device * (*find_companion)(struct device *);
|
||||
void (*setup)(struct device *);
|
||||
void (*cleanup)(struct device *);
|
||||
};
|
||||
int register_acpi_bus_type(struct acpi_bus_type *);
|
||||
int unregister_acpi_bus_type(struct acpi_bus_type *);
|
||||
|
@ -84,6 +84,14 @@ extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
|
||||
void acpi_pci_add_bus(struct pci_bus *bus);
|
||||
void acpi_pci_remove_bus(struct pci_bus *bus);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
void pci_acpi_setup(struct device *dev, struct acpi_device *adev);
|
||||
void pci_acpi_cleanup(struct device *dev, struct acpi_device *adev);
|
||||
#else
|
||||
static inline void pci_acpi_setup(struct device *dev, struct acpi_device *adev) {}
|
||||
static inline void pci_acpi_cleanup(struct device *dev, struct acpi_device *adev) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI_PCI_SLOT
|
||||
void acpi_pci_slot_init(void);
|
||||
void acpi_pci_slot_enumerate(struct pci_bus *bus);
|
||||
|
Loading…
Reference in New Issue
Block a user