You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'acpi-pm'
* acpi-pm: PM / core: Drop run_wake flag from struct dev_pm_info PCI / PM: Simplify device wakeup settings code PCI / PM: Drop pme_interrupt flag from struct pci_dev ACPI / PM: Consolidate device wakeup settings code ACPI / PM: Drop run_wake from struct acpi_device_wakeup_flags ACPI / sleep: EC-based wakeup from suspend-to-idle on recent systems platform: x86: intel-hid: Wake up the system from suspend-to-idle platform: x86: intel-vbtn: Wake up the system from suspend-to-idle ACPI / PM: Ignore spurious SCI wakeups from suspend-to-idle platform/x86: Add driver for ACPI INT0002 Virtual GPIO device PCI / PM: Restore PME Enable if skipping wakeup setup PM / sleep: Print timing information if debug is enabled ACPI / PM: Clean up device wakeup enable/disable code ACPI / PM: Change log level of wakeup-related message USB / PCI / PM: Allow the PCI core to do the resume cleanup ACPI / PM: Run wakeup notify handlers synchronously Conflicts: drivers/base/power/main.c
This commit is contained in:
@@ -105,9 +105,9 @@ knows what to do to handle the device).
|
||||
|
||||
In particular, if the driver requires remote wakeup capability (i.e. hardware
|
||||
mechanism allowing the device to request a change of its power state, such as
|
||||
PCI PME) for proper functioning and device_run_wake() returns 'false' for the
|
||||
PCI PME) for proper functioning and device_can_wakeup() returns 'false' for the
|
||||
device, then ->runtime_suspend() should return -EBUSY. On the other hand, if
|
||||
device_run_wake() returns 'true' for the device and the device is put into a
|
||||
device_can_wakeup() returns 'true' for the device and the device is put into a
|
||||
low-power state during the execution of the suspend callback, it is expected
|
||||
that remote wakeup will be enabled for the device. Generally, remote wakeup
|
||||
should be enabled for all input devices put into low-power states at run time.
|
||||
@@ -253,9 +253,6 @@ defined in include/linux/pm.h:
|
||||
being executed for that device and it is not practical to wait for the
|
||||
suspend to complete; means "start a resume as soon as you've suspended"
|
||||
|
||||
unsigned int run_wake;
|
||||
- set if the device is capable of generating runtime wake-up events
|
||||
|
||||
enum rpm_status runtime_status;
|
||||
- the runtime PM status of the device; this field's initial value is
|
||||
RPM_SUSPENDED, which means that each device is initially regarded by the
|
||||
|
||||
@@ -782,7 +782,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
|
||||
if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
|
||||
(test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
|
||||
(battery->capacity_now <= battery->alarm)))
|
||||
pm_wakeup_event(&battery->device->dev, 0);
|
||||
acpi_pm_wakeup_event(&battery->device->dev);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
|
||||
}
|
||||
|
||||
if (state)
|
||||
pm_wakeup_event(&device->dev, 0);
|
||||
acpi_pm_wakeup_event(&device->dev);
|
||||
|
||||
ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
|
||||
if (ret == NOTIFY_DONE)
|
||||
@@ -402,7 +402,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
|
||||
} else {
|
||||
int keycode;
|
||||
|
||||
pm_wakeup_event(&device->dev, 0);
|
||||
acpi_pm_wakeup_event(&device->dev);
|
||||
if (button->suspended)
|
||||
break;
|
||||
|
||||
@@ -534,6 +534,7 @@ static int acpi_button_add(struct acpi_device *device)
|
||||
lid_device = device;
|
||||
}
|
||||
|
||||
device_init_wakeup(&device->dev, true);
|
||||
printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
|
||||
return 0;
|
||||
|
||||
|
||||
+42
-60
@@ -24,6 +24,7 @@
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -385,6 +386,12 @@ EXPORT_SYMBOL(acpi_bus_power_manageable);
|
||||
#ifdef CONFIG_PM
|
||||
static DEFINE_MUTEX(acpi_pm_notifier_lock);
|
||||
|
||||
void acpi_pm_wakeup_event(struct device *dev)
|
||||
{
|
||||
pm_wakeup_dev_event(dev, 0, acpi_s2idle_wakeup());
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_pm_wakeup_event);
|
||||
|
||||
static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
@@ -399,9 +406,9 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
|
||||
mutex_lock(&acpi_pm_notifier_lock);
|
||||
|
||||
if (adev->wakeup.flags.notifier_present) {
|
||||
__pm_wakeup_event(adev->wakeup.ws, 0);
|
||||
if (adev->wakeup.context.work.func)
|
||||
queue_pm_work(&adev->wakeup.context.work);
|
||||
pm_wakeup_ws_event(adev->wakeup.ws, 0, acpi_s2idle_wakeup());
|
||||
if (adev->wakeup.context.func)
|
||||
adev->wakeup.context.func(&adev->wakeup.context);
|
||||
}
|
||||
|
||||
mutex_unlock(&acpi_pm_notifier_lock);
|
||||
@@ -413,7 +420,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
|
||||
* acpi_add_pm_notifier - Register PM notify handler for given ACPI device.
|
||||
* @adev: ACPI device to add the notify handler for.
|
||||
* @dev: Device to generate a wakeup event for while handling the notification.
|
||||
* @work_func: Work function to execute when handling the notification.
|
||||
* @func: Work function to execute when handling the notification.
|
||||
*
|
||||
* NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
|
||||
* PM wakeup events. For example, wakeup events may be generated for bridges
|
||||
@@ -421,11 +428,11 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
|
||||
* bridge itself doesn't have a wakeup GPE associated with it.
|
||||
*/
|
||||
acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
|
||||
void (*work_func)(struct work_struct *work))
|
||||
void (*func)(struct acpi_device_wakeup_context *context))
|
||||
{
|
||||
acpi_status status = AE_ALREADY_EXISTS;
|
||||
|
||||
if (!dev && !work_func)
|
||||
if (!dev && !func)
|
||||
return AE_BAD_PARAMETER;
|
||||
|
||||
mutex_lock(&acpi_pm_notifier_lock);
|
||||
@@ -435,8 +442,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
|
||||
|
||||
adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev));
|
||||
adev->wakeup.context.dev = dev;
|
||||
if (work_func)
|
||||
INIT_WORK(&adev->wakeup.context.work, work_func);
|
||||
adev->wakeup.context.func = func;
|
||||
|
||||
status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY,
|
||||
acpi_pm_notify_handler, NULL);
|
||||
@@ -469,10 +475,7 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
|
||||
if (ACPI_FAILURE(status))
|
||||
goto out;
|
||||
|
||||
if (adev->wakeup.context.work.func) {
|
||||
cancel_work_sync(&adev->wakeup.context.work);
|
||||
adev->wakeup.context.work.func = NULL;
|
||||
}
|
||||
adev->wakeup.context.func = NULL;
|
||||
adev->wakeup.context.dev = NULL;
|
||||
wakeup_source_unregister(adev->wakeup.ws);
|
||||
|
||||
@@ -493,6 +496,13 @@ bool acpi_bus_can_wakeup(acpi_handle handle)
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_can_wakeup);
|
||||
|
||||
bool acpi_pm_device_can_wakeup(struct device *dev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
|
||||
return adev ? acpi_device_can_wakeup(adev) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_dev_pm_get_state - Get preferred power state of ACPI device.
|
||||
* @dev: Device whose preferred target power state to return.
|
||||
@@ -658,16 +668,15 @@ EXPORT_SYMBOL(acpi_pm_device_sleep_state);
|
||||
|
||||
/**
|
||||
* acpi_pm_notify_work_func - ACPI devices wakeup notification work function.
|
||||
* @work: Work item to handle.
|
||||
* @context: Device wakeup context.
|
||||
*/
|
||||
static void acpi_pm_notify_work_func(struct work_struct *work)
|
||||
static void acpi_pm_notify_work_func(struct acpi_device_wakeup_context *context)
|
||||
{
|
||||
struct device *dev;
|
||||
struct device *dev = context->dev;
|
||||
|
||||
dev = container_of(work, struct acpi_device_wakeup_context, work)->dev;
|
||||
if (dev) {
|
||||
pm_wakeup_event(dev, 0);
|
||||
pm_runtime_resume(dev);
|
||||
pm_request_resume(dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,80 +702,53 @@ static int acpi_device_wakeup(struct acpi_device *adev, u32 target_state,
|
||||
acpi_status res;
|
||||
int error;
|
||||
|
||||
if (adev->wakeup.flags.enabled)
|
||||
return 0;
|
||||
|
||||
error = acpi_enable_wakeup_device_power(adev, target_state);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (adev->wakeup.flags.enabled)
|
||||
return 0;
|
||||
|
||||
res = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
|
||||
if (ACPI_SUCCESS(res)) {
|
||||
adev->wakeup.flags.enabled = 1;
|
||||
} else {
|
||||
if (ACPI_FAILURE(res)) {
|
||||
acpi_disable_wakeup_device_power(adev);
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
if (adev->wakeup.flags.enabled) {
|
||||
acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
|
||||
adev->wakeup.flags.enabled = 0;
|
||||
}
|
||||
adev->wakeup.flags.enabled = 1;
|
||||
} else if (adev->wakeup.flags.enabled) {
|
||||
acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
|
||||
acpi_disable_wakeup_device_power(adev);
|
||||
adev->wakeup.flags.enabled = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
|
||||
* @dev: Device to enable/disable the platform to wake up.
|
||||
* acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device.
|
||||
* @dev: Device to enable/disable to generate wakeup events.
|
||||
* @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;
|
||||
|
||||
if (!device_run_wake(phys_dev))
|
||||
return -EINVAL;
|
||||
|
||||
adev = ACPI_COMPANION(phys_dev);
|
||||
if (!adev) {
|
||||
dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return acpi_device_wakeup(adev, ACPI_STATE_S0, enable);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_pm_device_run_wake);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/**
|
||||
* acpi_pm_device_sleep_wake - Enable or disable device to wake up the system.
|
||||
* @dev: Device to enable/desible to wake up the system from sleep states.
|
||||
* @enable: Whether to enable or disable @dev to wake up the system.
|
||||
*/
|
||||
int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
|
||||
int acpi_pm_set_device_wakeup(struct device *dev, bool enable)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
int error;
|
||||
|
||||
if (!device_can_wakeup(dev))
|
||||
return -EINVAL;
|
||||
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (!adev) {
|
||||
dev_dbg(dev, "ACPI companion missing in %s!\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!acpi_device_can_wakeup(adev))
|
||||
return -EINVAL;
|
||||
|
||||
error = acpi_device_wakeup(adev, acpi_target_system_state(), enable);
|
||||
if (!error)
|
||||
dev_info(dev, "System wakeup %s by ACPI\n",
|
||||
enable ? "enabled" : "disabled");
|
||||
dev_dbg(dev, "Wakeup %s by ACPI\n", enable ? "enabled" : "disabled");
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
EXPORT_SYMBOL(acpi_pm_set_device_wakeup);
|
||||
|
||||
/**
|
||||
* acpi_dev_pm_low_power - Put ACPI device into a low-power state.
|
||||
|
||||
+1
-1
@@ -1835,7 +1835,7 @@ static int acpi_ec_suspend(struct device *dev)
|
||||
struct acpi_ec *ec =
|
||||
acpi_driver_data(to_acpi_device(dev));
|
||||
|
||||
if (ec_freeze_events)
|
||||
if (acpi_sleep_no_ec_events() && ec_freeze_events)
|
||||
acpi_ec_disable_event(ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -198,8 +198,12 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
|
||||
Suspend/Resume
|
||||
-------------------------------------------------------------------------- */
|
||||
#ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT
|
||||
extern bool acpi_s2idle_wakeup(void);
|
||||
extern bool acpi_sleep_no_ec_events(void);
|
||||
extern int acpi_sleep_init(void);
|
||||
#else
|
||||
static inline bool acpi_s2idle_wakeup(void) { return false; }
|
||||
static inline bool acpi_sleep_no_ec_events(void) { return true; }
|
||||
static inline int acpi_sleep_init(void) { return -ENXIO; }
|
||||
#endif
|
||||
|
||||
|
||||
@@ -608,8 +608,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
|
||||
pcie_no_aspm();
|
||||
|
||||
pci_acpi_add_bus_pm_notifier(device);
|
||||
if (device->wakeup.flags.run_wake)
|
||||
device_set_run_wake(root->bus->bridge, true);
|
||||
device_set_wakeup_capable(root->bus->bridge, device->wakeup.flags.valid);
|
||||
|
||||
if (hotadd) {
|
||||
pcibios_resource_survey_bus(root->bus);
|
||||
@@ -649,7 +648,7 @@ static void acpi_pci_root_remove(struct acpi_device *device)
|
||||
pci_stop_root_bus(root->bus);
|
||||
|
||||
pci_ioapic_remove(root);
|
||||
device_set_run_wake(root->bus->bridge, false);
|
||||
device_set_wakeup_capable(root->bus->bridge, false);
|
||||
pci_acpi_remove_bus_pm_notifier(device);
|
||||
|
||||
pci_remove_root_bus(root->bus);
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
|
||||
|
||||
if (!dev->physical_node_count) {
|
||||
seq_printf(seq, "%c%-8s\n",
|
||||
dev->wakeup.flags.run_wake ? '*' : ' ',
|
||||
dev->wakeup.flags.valid ? '*' : ' ',
|
||||
device_may_wakeup(&dev->dev) ?
|
||||
"enabled" : "disabled");
|
||||
} else {
|
||||
@@ -58,7 +58,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
|
||||
seq_printf(seq, "\t\t");
|
||||
|
||||
seq_printf(seq, "%c%-8s %s:%s\n",
|
||||
dev->wakeup.flags.run_wake ? '*' : ' ',
|
||||
dev->wakeup.flags.valid ? '*' : ' ',
|
||||
(device_may_wakeup(&dev->dev) ||
|
||||
device_may_wakeup(ldev)) ?
|
||||
"enabled" : "disabled",
|
||||
|
||||
+8
-15
@@ -835,7 +835,7 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void acpi_wakeup_gpe_init(struct acpi_device *device)
|
||||
static bool acpi_wakeup_gpe_init(struct acpi_device *device)
|
||||
{
|
||||
static const struct acpi_device_id button_device_ids[] = {
|
||||
{"PNP0C0C", 0},
|
||||
@@ -845,13 +845,11 @@ static void acpi_wakeup_gpe_init(struct acpi_device *device)
|
||||
};
|
||||
struct acpi_device_wakeup *wakeup = &device->wakeup;
|
||||
acpi_status status;
|
||||
acpi_event_status event_status;
|
||||
|
||||
wakeup->flags.notifier_present = 0;
|
||||
|
||||
/* Power button, Lid switch always enable wakeup */
|
||||
if (!acpi_match_device_ids(device, button_device_ids)) {
|
||||
wakeup->flags.run_wake = 1;
|
||||
if (!acpi_match_device_ids(device, &button_device_ids[1])) {
|
||||
/* Do not use Lid/sleep button for S5 wakeup */
|
||||
if (wakeup->sleep_state == ACPI_STATE_S5)
|
||||
@@ -859,17 +857,12 @@ static void acpi_wakeup_gpe_init(struct acpi_device *device)
|
||||
}
|
||||
acpi_mark_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number);
|
||||
device_set_wakeup_capable(&device->dev, true);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
acpi_setup_gpe_for_wake(device->handle, wakeup->gpe_device,
|
||||
wakeup->gpe_number);
|
||||
status = acpi_get_gpe_status(wakeup->gpe_device, wakeup->gpe_number,
|
||||
&event_status);
|
||||
if (ACPI_FAILURE(status))
|
||||
return;
|
||||
|
||||
wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HAS_HANDLER);
|
||||
status = acpi_setup_gpe_for_wake(device->handle, wakeup->gpe_device,
|
||||
wakeup->gpe_number);
|
||||
return ACPI_SUCCESS(status);
|
||||
}
|
||||
|
||||
static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
|
||||
@@ -887,10 +880,10 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
|
||||
return;
|
||||
}
|
||||
|
||||
device->wakeup.flags.valid = 1;
|
||||
device->wakeup.flags.valid = acpi_wakeup_gpe_init(device);
|
||||
device->wakeup.prepare_count = 0;
|
||||
acpi_wakeup_gpe_init(device);
|
||||
/* Call _PSW/_DSW object to disable its ability to wake the sleeping
|
||||
/*
|
||||
* Call _PSW/_DSW object to disable its ability to wake the sleeping
|
||||
* system for the ACPI device with the _PRW object.
|
||||
* The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
|
||||
* So it is necessary to call _DSW object first. Only when it is not
|
||||
|
||||
+147
-5
@@ -650,38 +650,165 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = {
|
||||
.recover = acpi_pm_finish,
|
||||
};
|
||||
|
||||
static bool s2idle_in_progress;
|
||||
static bool s2idle_wakeup;
|
||||
|
||||
/*
|
||||
* On platforms supporting the Low Power S0 Idle interface there is an ACPI
|
||||
* device object with the PNP0D80 compatible device ID (System Power Management
|
||||
* Controller) and a specific _DSM method under it. That method, if present,
|
||||
* can be used to indicate to the platform that the OS is transitioning into a
|
||||
* low-power state in which certain types of activity are not desirable or that
|
||||
* it is leaving such a state, which allows the platform to adjust its operation
|
||||
* mode accordingly.
|
||||
*/
|
||||
static const struct acpi_device_id lps0_device_ids[] = {
|
||||
{"PNP0D80", },
|
||||
{"", },
|
||||
};
|
||||
|
||||
#define ACPI_LPS0_DSM_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
|
||||
|
||||
#define ACPI_LPS0_SCREEN_OFF 3
|
||||
#define ACPI_LPS0_SCREEN_ON 4
|
||||
#define ACPI_LPS0_ENTRY 5
|
||||
#define ACPI_LPS0_EXIT 6
|
||||
|
||||
#define ACPI_S2IDLE_FUNC_MASK ((1 << ACPI_LPS0_ENTRY) | (1 << ACPI_LPS0_EXIT))
|
||||
|
||||
static acpi_handle lps0_device_handle;
|
||||
static guid_t lps0_dsm_guid;
|
||||
static char lps0_dsm_func_mask;
|
||||
|
||||
static void acpi_sleep_run_lps0_dsm(unsigned int func)
|
||||
{
|
||||
union acpi_object *out_obj;
|
||||
|
||||
if (!(lps0_dsm_func_mask & (1 << func)))
|
||||
return;
|
||||
|
||||
out_obj = acpi_evaluate_dsm(lps0_device_handle, &lps0_dsm_guid, 1, func, NULL);
|
||||
ACPI_FREE(out_obj);
|
||||
|
||||
acpi_handle_debug(lps0_device_handle, "_DSM function %u evaluation %s\n",
|
||||
func, out_obj ? "successful" : "failed");
|
||||
}
|
||||
|
||||
static int lps0_device_attach(struct acpi_device *adev,
|
||||
const struct acpi_device_id *not_used)
|
||||
{
|
||||
union acpi_object *out_obj;
|
||||
|
||||
if (lps0_device_handle)
|
||||
return 0;
|
||||
|
||||
if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
|
||||
return 0;
|
||||
|
||||
guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid);
|
||||
/* Check if the _DSM is present and as expected. */
|
||||
out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL);
|
||||
if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) {
|
||||
char bitmask = *(char *)out_obj->buffer.pointer;
|
||||
|
||||
if ((bitmask & ACPI_S2IDLE_FUNC_MASK) == ACPI_S2IDLE_FUNC_MASK) {
|
||||
lps0_dsm_func_mask = bitmask;
|
||||
lps0_device_handle = adev->handle;
|
||||
}
|
||||
|
||||
acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
|
||||
bitmask);
|
||||
} else {
|
||||
acpi_handle_debug(adev->handle,
|
||||
"_DSM function 0 evaluation failed\n");
|
||||
}
|
||||
ACPI_FREE(out_obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct acpi_scan_handler lps0_handler = {
|
||||
.ids = lps0_device_ids,
|
||||
.attach = lps0_device_attach,
|
||||
};
|
||||
|
||||
static int acpi_freeze_begin(void)
|
||||
{
|
||||
acpi_scan_lock_acquire();
|
||||
s2idle_in_progress = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_freeze_prepare(void)
|
||||
{
|
||||
acpi_enable_wakeup_devices(ACPI_STATE_S0);
|
||||
acpi_enable_all_wakeup_gpes();
|
||||
acpi_os_wait_events_complete();
|
||||
if (lps0_device_handle) {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
|
||||
} else {
|
||||
/*
|
||||
* The configuration of GPEs is changed here to avoid spurious
|
||||
* wakeups, but that should not be necessary if this is a
|
||||
* "low-power S0" platform and the low-power S0 _DSM is present.
|
||||
*/
|
||||
acpi_enable_all_wakeup_gpes();
|
||||
acpi_os_wait_events_complete();
|
||||
}
|
||||
if (acpi_sci_irq_valid())
|
||||
enable_irq_wake(acpi_sci_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_freeze_wake(void)
|
||||
{
|
||||
/*
|
||||
* If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means
|
||||
* that the SCI has triggered while suspended, so cancel the wakeup in
|
||||
* case it has not been a wakeup event (the GPEs will be checked later).
|
||||
*/
|
||||
if (acpi_sci_irq_valid() &&
|
||||
!irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) {
|
||||
pm_system_cancel_wakeup();
|
||||
s2idle_wakeup = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_freeze_sync(void)
|
||||
{
|
||||
/*
|
||||
* Process all pending events in case there are any wakeup ones.
|
||||
*
|
||||
* The EC driver uses the system workqueue, so that one needs to be
|
||||
* flushed too.
|
||||
*/
|
||||
acpi_os_wait_events_complete();
|
||||
flush_scheduled_work();
|
||||
s2idle_wakeup = false;
|
||||
}
|
||||
|
||||
static void acpi_freeze_restore(void)
|
||||
{
|
||||
acpi_disable_wakeup_devices(ACPI_STATE_S0);
|
||||
if (acpi_sci_irq_valid())
|
||||
disable_irq_wake(acpi_sci_irq);
|
||||
acpi_enable_all_runtime_gpes();
|
||||
|
||||
if (lps0_device_handle) {
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
|
||||
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
|
||||
} else {
|
||||
acpi_enable_all_runtime_gpes();
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_freeze_end(void)
|
||||
{
|
||||
s2idle_in_progress = false;
|
||||
acpi_scan_lock_release();
|
||||
}
|
||||
|
||||
static const struct platform_freeze_ops acpi_freeze_ops = {
|
||||
.begin = acpi_freeze_begin,
|
||||
.prepare = acpi_freeze_prepare,
|
||||
.wake = acpi_freeze_wake,
|
||||
.sync = acpi_freeze_sync,
|
||||
.restore = acpi_freeze_restore,
|
||||
.end = acpi_freeze_end,
|
||||
};
|
||||
@@ -696,13 +823,28 @@ static void acpi_sleep_suspend_setup(void)
|
||||
|
||||
suspend_set_ops(old_suspend_ordering ?
|
||||
&acpi_suspend_ops_old : &acpi_suspend_ops);
|
||||
|
||||
acpi_scan_add_handler(&lps0_handler);
|
||||
freeze_set_ops(&acpi_freeze_ops);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_SUSPEND */
|
||||
#define s2idle_in_progress (false)
|
||||
#define s2idle_wakeup (false)
|
||||
#define lps0_device_handle (NULL)
|
||||
static inline void acpi_sleep_suspend_setup(void) {}
|
||||
#endif /* !CONFIG_SUSPEND */
|
||||
|
||||
bool acpi_s2idle_wakeup(void)
|
||||
{
|
||||
return s2idle_wakeup;
|
||||
}
|
||||
|
||||
bool acpi_sleep_no_ec_events(void)
|
||||
{
|
||||
return !s2idle_in_progress || !lps0_device_handle;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static u32 saved_bm_rld;
|
||||
|
||||
|
||||
@@ -174,8 +174,7 @@ void zpodd_enable_run_wake(struct ata_device *dev)
|
||||
sdev_disable_disk_events(dev->sdev);
|
||||
|
||||
zpodd->powered_off = true;
|
||||
device_set_run_wake(&dev->tdev, true);
|
||||
acpi_pm_device_run_wake(&dev->tdev, true);
|
||||
acpi_pm_set_device_wakeup(&dev->tdev, true);
|
||||
}
|
||||
|
||||
/* Disable runtime wake capability if it is enabled */
|
||||
@@ -183,10 +182,8 @@ void zpodd_disable_run_wake(struct ata_device *dev)
|
||||
{
|
||||
struct zpodd *zpodd = dev->zpodd;
|
||||
|
||||
if (zpodd->powered_off) {
|
||||
acpi_pm_device_run_wake(&dev->tdev, false);
|
||||
device_set_run_wake(&dev->tdev, false);
|
||||
}
|
||||
if (zpodd->powered_off)
|
||||
acpi_pm_set_device_wakeup(&dev->tdev, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -418,6 +418,7 @@ static void pm_dev_err(struct device *dev, pm_message_t state, const char *info,
|
||||
dev_name(dev), pm_verb(state.event), info, error);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_DEBUG
|
||||
static void dpm_show_time(ktime_t starttime, pm_message_t state,
|
||||
const char *info)
|
||||
{
|
||||
@@ -435,6 +436,10 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state,
|
||||
info ?: "", info ? " " : "", pm_verb(state.event),
|
||||
usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
|
||||
}
|
||||
#else
|
||||
static inline void dpm_show_time(ktime_t starttime, pm_message_t state,
|
||||
const char *info) {}
|
||||
#endif /* CONFIG_PM_DEBUG */
|
||||
|
||||
static int dpm_run_callback(pm_callback_t cb, struct device *dev,
|
||||
pm_message_t state, const char *info)
|
||||
@@ -1093,11 +1098,6 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a
|
||||
if (async_error)
|
||||
goto Complete;
|
||||
|
||||
if (pm_wakeup_pending()) {
|
||||
async_error = -EBUSY;
|
||||
goto Complete;
|
||||
}
|
||||
|
||||
if (dev->power.syscore || dev->power.direct_complete)
|
||||
goto Complete;
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ bool events_check_enabled __read_mostly;
|
||||
/* First wakeup IRQ seen by the kernel in the last cycle. */
|
||||
unsigned int pm_wakeup_irq __read_mostly;
|
||||
|
||||
/* If set and the system is suspending, terminate the suspend. */
|
||||
static bool pm_abort_suspend __read_mostly;
|
||||
/* If greater than 0 and the system is suspending, terminate the suspend. */
|
||||
static atomic_t pm_abort_suspend __read_mostly;
|
||||
|
||||
/*
|
||||
* Combined counters of registered wakeup events and wakeup events in progress.
|
||||
@@ -857,20 +857,26 @@ bool pm_wakeup_pending(void)
|
||||
pm_print_active_wakeup_sources();
|
||||
}
|
||||
|
||||
return ret || pm_abort_suspend;
|
||||
return ret || atomic_read(&pm_abort_suspend) > 0;
|
||||
}
|
||||
|
||||
void pm_system_wakeup(void)
|
||||
{
|
||||
pm_abort_suspend = true;
|
||||
atomic_inc(&pm_abort_suspend);
|
||||
freeze_wake();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_system_wakeup);
|
||||
|
||||
void pm_wakeup_clear(void)
|
||||
void pm_system_cancel_wakeup(void)
|
||||
{
|
||||
atomic_dec(&pm_abort_suspend);
|
||||
}
|
||||
|
||||
void pm_wakeup_clear(bool reset)
|
||||
{
|
||||
pm_abort_suspend = false;
|
||||
pm_wakeup_irq = 0;
|
||||
if (reset)
|
||||
atomic_set(&pm_abort_suspend, 0);
|
||||
}
|
||||
|
||||
void pm_system_irq_wakeup(unsigned int irq_number)
|
||||
|
||||
+22
-68
@@ -394,29 +394,26 @@ bool pciehp_is_native(struct pci_dev *pdev)
|
||||
|
||||
/**
|
||||
* pci_acpi_wake_bus - Root bus wakeup notification fork function.
|
||||
* @work: Work item to handle.
|
||||
* @context: Device wakeup context.
|
||||
*/
|
||||
static void pci_acpi_wake_bus(struct work_struct *work)
|
||||
static void pci_acpi_wake_bus(struct acpi_device_wakeup_context *context)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
struct acpi_pci_root *root;
|
||||
|
||||
adev = container_of(work, struct acpi_device, wakeup.context.work);
|
||||
adev = container_of(context, struct acpi_device, wakeup.context);
|
||||
root = acpi_driver_data(adev);
|
||||
pci_pme_wakeup_bus(root->bus);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_acpi_wake_dev - PCI device wakeup notification work function.
|
||||
* @handle: ACPI handle of a device the notification is for.
|
||||
* @work: Work item to handle.
|
||||
* @context: Device wakeup context.
|
||||
*/
|
||||
static void pci_acpi_wake_dev(struct work_struct *work)
|
||||
static void pci_acpi_wake_dev(struct acpi_device_wakeup_context *context)
|
||||
{
|
||||
struct acpi_device_wakeup_context *context;
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
context = container_of(work, struct acpi_device_wakeup_context, work);
|
||||
pci_dev = to_pci_dev(context->dev);
|
||||
|
||||
if (pci_dev->pme_poll)
|
||||
@@ -424,7 +421,7 @@ static void pci_acpi_wake_dev(struct work_struct *work)
|
||||
|
||||
if (pci_dev->current_state == PCI_D3cold) {
|
||||
pci_wakeup_event(pci_dev);
|
||||
pm_runtime_resume(&pci_dev->dev);
|
||||
pm_request_resume(&pci_dev->dev);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -433,7 +430,7 @@ static void pci_acpi_wake_dev(struct work_struct *work)
|
||||
pci_check_pme_status(pci_dev);
|
||||
|
||||
pci_wakeup_event(pci_dev);
|
||||
pm_runtime_resume(&pci_dev->dev);
|
||||
pm_request_resume(&pci_dev->dev);
|
||||
|
||||
pci_pme_wakeup_bus(pci_dev->subordinate);
|
||||
}
|
||||
@@ -572,67 +569,29 @@ static pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
|
||||
return state_conv[state];
|
||||
}
|
||||
|
||||
static bool acpi_pci_can_wakeup(struct pci_dev *dev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
|
||||
return adev ? acpi_device_can_wakeup(adev) : false;
|
||||
}
|
||||
|
||||
static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable)
|
||||
static int acpi_pci_propagate_wakeup(struct pci_bus *bus, bool enable)
|
||||
{
|
||||
while (bus->parent) {
|
||||
if (!acpi_pm_device_sleep_wake(&bus->self->dev, enable))
|
||||
return;
|
||||
if (acpi_pm_device_can_wakeup(&bus->self->dev))
|
||||
return acpi_pm_set_device_wakeup(&bus->self->dev, enable);
|
||||
|
||||
bus = bus->parent;
|
||||
}
|
||||
|
||||
/* We have reached the root bus. */
|
||||
if (bus->bridge)
|
||||
acpi_pm_device_sleep_wake(bus->bridge, enable);
|
||||
}
|
||||
|
||||
static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
if (acpi_pci_can_wakeup(dev))
|
||||
return acpi_pm_device_sleep_wake(&dev->dev, enable);
|
||||
|
||||
acpi_pci_propagate_wakeup_enable(dev->bus, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable)
|
||||
{
|
||||
while (bus->parent) {
|
||||
struct pci_dev *bridge = bus->self;
|
||||
|
||||
if (bridge->pme_interrupt)
|
||||
return;
|
||||
if (!acpi_pm_device_run_wake(&bridge->dev, enable))
|
||||
return;
|
||||
bus = bus->parent;
|
||||
if (bus->bridge) {
|
||||
if (acpi_pm_device_can_wakeup(bus->bridge))
|
||||
return acpi_pm_set_device_wakeup(bus->bridge, enable);
|
||||
}
|
||||
|
||||
/* We have reached the root bus. */
|
||||
if (bus->bridge)
|
||||
acpi_pm_device_run_wake(bus->bridge, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_pci_run_wake(struct pci_dev *dev, bool enable)
|
||||
static int acpi_pci_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
/*
|
||||
* Per PCI Express Base Specification Revision 2.0 section
|
||||
* 5.3.3.2 Link Wakeup, platform support is needed for D3cold
|
||||
* waking up to power on the main link even if there is PME
|
||||
* support for D3cold
|
||||
*/
|
||||
if (dev->pme_interrupt && !dev->runtime_d3cold)
|
||||
return 0;
|
||||
if (acpi_pm_device_can_wakeup(&dev->dev))
|
||||
return acpi_pm_set_device_wakeup(&dev->dev, enable);
|
||||
|
||||
if (!acpi_pm_device_run_wake(&dev->dev, enable))
|
||||
return 0;
|
||||
|
||||
acpi_pci_propagate_run_wake(dev->bus, enable);
|
||||
return 0;
|
||||
return acpi_pci_propagate_wakeup(dev->bus, enable);
|
||||
}
|
||||
|
||||
static bool acpi_pci_need_resume(struct pci_dev *dev)
|
||||
@@ -656,8 +615,7 @@ static const struct pci_platform_pm_ops acpi_pci_platform_pm = {
|
||||
.set_state = acpi_pci_set_power_state,
|
||||
.get_state = acpi_pci_get_power_state,
|
||||
.choose_state = acpi_pci_choose_state,
|
||||
.sleep_wake = acpi_pci_sleep_wake,
|
||||
.run_wake = acpi_pci_run_wake,
|
||||
.set_wakeup = acpi_pci_wakeup,
|
||||
.need_resume = acpi_pci_need_resume,
|
||||
};
|
||||
|
||||
@@ -780,9 +738,7 @@ static void pci_acpi_setup(struct device *dev)
|
||||
return;
|
||||
|
||||
device_set_wakeup_capable(dev, true);
|
||||
acpi_pci_sleep_wake(pci_dev, false);
|
||||
if (adev->wakeup.flags.run_wake)
|
||||
device_set_run_wake(dev, true);
|
||||
acpi_pci_wakeup(pci_dev, false);
|
||||
}
|
||||
|
||||
static void pci_acpi_cleanup(struct device *dev)
|
||||
@@ -793,10 +749,8 @@ static void pci_acpi_cleanup(struct device *dev)
|
||||
return;
|
||||
|
||||
pci_acpi_remove_pm_notifier(adev);
|
||||
if (adev->wakeup.flags.valid) {
|
||||
if (adev->wakeup.flags.valid)
|
||||
device_set_wakeup_capable(dev, false);
|
||||
device_set_run_wake(dev, false);
|
||||
}
|
||||
}
|
||||
|
||||
static bool pci_acpi_bus_match(struct device *dev)
|
||||
|
||||
@@ -1216,7 +1216,7 @@ static int pci_pm_runtime_resume(struct device *dev)
|
||||
|
||||
pci_restore_standard_config(pci_dev);
|
||||
pci_fixup_device(pci_fixup_resume_early, pci_dev);
|
||||
__pci_enable_wake(pci_dev, PCI_D0, true, false);
|
||||
pci_enable_wake(pci_dev, PCI_D0, false);
|
||||
pci_fixup_device(pci_fixup_resume, pci_dev);
|
||||
|
||||
rc = pm->runtime_resume(dev);
|
||||
|
||||
@@ -39,12 +39,7 @@ static pci_power_t mid_pci_choose_state(struct pci_dev *pdev)
|
||||
return PCI_D3hot;
|
||||
}
|
||||
|
||||
static int mid_pci_sleep_wake(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mid_pci_run_wake(struct pci_dev *dev, bool enable)
|
||||
static int mid_pci_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -59,8 +54,7 @@ static const struct pci_platform_pm_ops mid_pci_platform_pm = {
|
||||
.set_state = mid_pci_set_power_state,
|
||||
.get_state = mid_pci_get_power_state,
|
||||
.choose_state = mid_pci_choose_state,
|
||||
.sleep_wake = mid_pci_sleep_wake,
|
||||
.run_wake = mid_pci_run_wake,
|
||||
.set_wakeup = mid_pci_wakeup,
|
||||
.need_resume = mid_pci_need_resume,
|
||||
};
|
||||
|
||||
|
||||
+37
-31
@@ -574,8 +574,7 @@ 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->sleep_wake || !ops->run_wake ||
|
||||
!ops->need_resume)
|
||||
!ops->choose_state || !ops->set_wakeup || !ops->need_resume)
|
||||
return -EINVAL;
|
||||
pci_platform_pm = ops;
|
||||
return 0;
|
||||
@@ -603,16 +602,10 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev)
|
||||
pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR;
|
||||
}
|
||||
|
||||
static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
|
||||
static inline int platform_pci_set_wakeup(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return pci_platform_pm ?
|
||||
pci_platform_pm->sleep_wake(dev, enable) : -ENODEV;
|
||||
}
|
||||
|
||||
static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
return pci_platform_pm ?
|
||||
pci_platform_pm->run_wake(dev, enable) : -ENODEV;
|
||||
pci_platform_pm->set_wakeup(dev, enable) : -ENODEV;
|
||||
}
|
||||
|
||||
static inline bool platform_pci_need_resume(struct pci_dev *dev)
|
||||
@@ -1805,6 +1798,23 @@ static void __pci_pme_active(struct pci_dev *dev, bool enable)
|
||||
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
|
||||
}
|
||||
|
||||
static void pci_pme_restore(struct pci_dev *dev)
|
||||
{
|
||||
u16 pmcsr;
|
||||
|
||||
if (!dev->pme_support)
|
||||
return;
|
||||
|
||||
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
|
||||
if (dev->wakeup_prepared) {
|
||||
pmcsr |= PCI_PM_CTRL_PME_ENABLE;
|
||||
} else {
|
||||
pmcsr &= ~PCI_PM_CTRL_PME_ENABLE;
|
||||
pmcsr |= PCI_PM_CTRL_PME_STATUS;
|
||||
}
|
||||
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_pme_active - enable or disable PCI device's PME# function
|
||||
* @dev: PCI device to handle.
|
||||
@@ -1872,10 +1882,9 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
|
||||
EXPORT_SYMBOL(pci_pme_active);
|
||||
|
||||
/**
|
||||
* __pci_enable_wake - enable PCI device as wakeup event source
|
||||
* pci_enable_wake - enable PCI device as wakeup event source
|
||||
* @dev: PCI device affected
|
||||
* @state: PCI state from which device will issue wakeup events
|
||||
* @runtime: True if the events are to be generated at run time
|
||||
* @enable: True to enable event generation; false to disable
|
||||
*
|
||||
* This enables the device as a wakeup event source, or disables it.
|
||||
@@ -1891,17 +1900,18 @@ EXPORT_SYMBOL(pci_pme_active);
|
||||
* Error code depending on the platform is returned if both the platform and
|
||||
* the native mechanism fail to enable the generation of wake-up events
|
||||
*/
|
||||
int __pci_enable_wake(struct pci_dev *dev, pci_power_t state,
|
||||
bool runtime, bool enable)
|
||||
int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (enable && !runtime && !device_may_wakeup(&dev->dev))
|
||||
return -EINVAL;
|
||||
|
||||
/* Don't do the same thing twice in a row for one device. */
|
||||
if (!!enable == !!dev->wakeup_prepared)
|
||||
/*
|
||||
* Don't do the same thing twice in a row for one device, but restore
|
||||
* PME Enable in case it has been updated by config space restoration.
|
||||
*/
|
||||
if (!!enable == !!dev->wakeup_prepared) {
|
||||
pci_pme_restore(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* According to "PCI System Architecture" 4th ed. by Tom Shanley & Don
|
||||
@@ -1916,24 +1926,20 @@ int __pci_enable_wake(struct pci_dev *dev, pci_power_t state,
|
||||
pci_pme_active(dev, true);
|
||||
else
|
||||
ret = 1;
|
||||
error = runtime ? platform_pci_run_wake(dev, true) :
|
||||
platform_pci_sleep_wake(dev, true);
|
||||
error = platform_pci_set_wakeup(dev, true);
|
||||
if (ret)
|
||||
ret = error;
|
||||
if (!ret)
|
||||
dev->wakeup_prepared = true;
|
||||
} else {
|
||||
if (runtime)
|
||||
platform_pci_run_wake(dev, false);
|
||||
else
|
||||
platform_pci_sleep_wake(dev, false);
|
||||
platform_pci_set_wakeup(dev, false);
|
||||
pci_pme_active(dev, false);
|
||||
dev->wakeup_prepared = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(__pci_enable_wake);
|
||||
EXPORT_SYMBOL(pci_enable_wake);
|
||||
|
||||
/**
|
||||
* pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold
|
||||
@@ -2075,12 +2081,12 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
|
||||
|
||||
dev->runtime_d3cold = target_state == PCI_D3cold;
|
||||
|
||||
__pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev));
|
||||
pci_enable_wake(dev, target_state, pci_dev_run_wake(dev));
|
||||
|
||||
error = pci_set_power_state(dev, target_state);
|
||||
|
||||
if (error) {
|
||||
__pci_enable_wake(dev, target_state, true, false);
|
||||
pci_enable_wake(dev, target_state, false);
|
||||
dev->runtime_d3cold = false;
|
||||
}
|
||||
|
||||
@@ -2099,7 +2105,7 @@ bool pci_dev_run_wake(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_bus *bus = dev->bus;
|
||||
|
||||
if (device_run_wake(&dev->dev))
|
||||
if (device_can_wakeup(&dev->dev))
|
||||
return true;
|
||||
|
||||
if (!dev->pme_support)
|
||||
@@ -2112,7 +2118,7 @@ bool pci_dev_run_wake(struct pci_dev *dev)
|
||||
while (bus->parent) {
|
||||
struct pci_dev *bridge = bus->self;
|
||||
|
||||
if (device_run_wake(&bridge->dev))
|
||||
if (device_can_wakeup(&bridge->dev))
|
||||
return true;
|
||||
|
||||
bus = bus->parent;
|
||||
@@ -2120,7 +2126,7 @@ bool pci_dev_run_wake(struct pci_dev *dev)
|
||||
|
||||
/* We have reached the root bus. */
|
||||
if (bus->bridge)
|
||||
return device_run_wake(bus->bridge);
|
||||
return device_can_wakeup(bus->bridge);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+2
-7
@@ -47,11 +47,7 @@ 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
|
||||
*
|
||||
* @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
|
||||
* for given device (the device's wake-up capability has to be
|
||||
* enabled by @sleep_wake for this feature to work)
|
||||
* @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
|
||||
@@ -65,8 +61,7 @@ struct pci_platform_pm_ops {
|
||||
int (*set_state)(struct pci_dev *dev, pci_power_t state);
|
||||
pci_power_t (*get_state)(struct pci_dev *dev);
|
||||
pci_power_t (*choose_state)(struct pci_dev *dev);
|
||||
int (*sleep_wake)(struct pci_dev *dev, bool enable);
|
||||
int (*run_wake)(struct pci_dev *dev, bool enable);
|
||||
int (*set_wakeup)(struct pci_dev *dev, bool enable);
|
||||
bool (*need_resume)(struct pci_dev *dev);
|
||||
};
|
||||
|
||||
|
||||
@@ -294,31 +294,29 @@ static irqreturn_t pcie_pme_irq(int irq, void *context)
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_pme_set_native - Set the PME interrupt flag for given device.
|
||||
* pcie_pme_can_wakeup - Set the wakeup capability flag.
|
||||
* @dev: PCI device to handle.
|
||||
* @ign: Ignored.
|
||||
*/
|
||||
static int pcie_pme_set_native(struct pci_dev *dev, void *ign)
|
||||
static int pcie_pme_can_wakeup(struct pci_dev *dev, void *ign)
|
||||
{
|
||||
device_set_run_wake(&dev->dev, true);
|
||||
dev->pme_interrupt = true;
|
||||
device_set_wakeup_capable(&dev->dev, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_pme_mark_devices - Set the PME interrupt flag for devices below a port.
|
||||
* pcie_pme_mark_devices - Set the wakeup flag for devices below a port.
|
||||
* @port: PCIe root port or event collector to handle.
|
||||
*
|
||||
* For each device below given root port, including the port itself (or for each
|
||||
* root complex integrated endpoint if @port is a root complex event collector)
|
||||
* set the flag indicating that it can signal run-time wake-up events via PCIe
|
||||
* PME interrupts.
|
||||
* set the flag indicating that it can signal run-time wake-up events.
|
||||
*/
|
||||
static void pcie_pme_mark_devices(struct pci_dev *port)
|
||||
{
|
||||
pcie_pme_set_native(port, NULL);
|
||||
pcie_pme_can_wakeup(port, NULL);
|
||||
if (port->subordinate)
|
||||
pci_walk_bus(port->subordinate, pcie_pme_set_native, NULL);
|
||||
pci_walk_bus(port->subordinate, pcie_pme_can_wakeup, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -794,6 +794,25 @@ config INTEL_CHT_INT33FE
|
||||
This driver instantiates i2c-clients for these, so that standard
|
||||
i2c drivers for these chips can bind to the them.
|
||||
|
||||
config INTEL_INT0002_VGPIO
|
||||
tristate "Intel ACPI INT0002 Virtual GPIO driver"
|
||||
depends on GPIOLIB && ACPI
|
||||
select GPIOLIB_IRQCHIP
|
||||
---help---
|
||||
Some peripherals on Bay Trail and Cherry Trail platforms signal a
|
||||
Power Management Event (PME) to the Power Management Controller (PMC)
|
||||
to wakeup the system. When this happens software needs to explicitly
|
||||
clear the PME bus 0 status bit in the GPE0a_STS register to avoid an
|
||||
IRQ storm on IRQ 9.
|
||||
|
||||
This is modelled in ACPI through the INT0002 ACPI device, which is
|
||||
called a "Virtual GPIO controller" in ACPI because it defines the
|
||||
event handler to call when the PME triggers through _AEI and _L02
|
||||
methods as would be done for a real GPIO interrupt in ACPI.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called intel_int0002_vgpio.
|
||||
|
||||
config INTEL_HID_EVENT
|
||||
tristate "INTEL HID Event"
|
||||
depends on ACPI
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user