Merge branches 'pm-domains', 'pm-cpuidle', 'pm-sleep' and 'powercap'
* pm-domains: PM / Domains: Add DT file to MAINTAINERS PM / Domains: Fix DT example * pm-cpuidle: x86/intel_idle: add Gemini Lake support cpuidle: check dev before usage in cpuidle_use_deepest_state() * pm-sleep: ACPI / sleep: Ignore spurious SCI wakeups from suspend-to-idle PM / wakeup: Integrate mechanism to abort transitions in progress * powercap: powercap: intel_rapl: Add support for Gemini Lake
This commit is contained in:
commit
80449d89d4
|
@ -81,7 +81,7 @@ Example 3:
|
||||||
child: power-controller@12341000 {
|
child: power-controller@12341000 {
|
||||||
compatible = "foo,power-controller";
|
compatible = "foo,power-controller";
|
||||||
reg = <0x12341000 0x1000>;
|
reg = <0x12341000 0x1000>;
|
||||||
power-domains = <&parent 0>;
|
power-domains = <&parent>;
|
||||||
#power-domain-cells = <0>;
|
#power-domain-cells = <0>;
|
||||||
domain-idle-states = <&DOMAIN_PWR_DN>;
|
domain-idle-states = <&DOMAIN_PWR_DN>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -5523,6 +5523,7 @@ L: linux-pm@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/base/power/domain*.c
|
F: drivers/base/power/domain*.c
|
||||||
F: include/linux/pm_domain.h
|
F: include/linux/pm_domain.h
|
||||||
|
F: Documentation/devicetree/bindings/power/power_domain.txt
|
||||||
|
|
||||||
GENERIC UIO DRIVER FOR PCI DEVICES
|
GENERIC UIO DRIVER FOR PCI DEVICES
|
||||||
M: "Michael S. Tsirkin" <mst@redhat.com>
|
M: "Michael S. Tsirkin" <mst@redhat.com>
|
||||||
|
|
|
@ -782,7 +782,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
|
||||||
if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
|
if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
|
||||||
(test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
|
(test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
|
||||||
(battery->capacity_now <= battery->alarm)))
|
(battery->capacity_now <= battery->alarm)))
|
||||||
pm_wakeup_event(&battery->device->dev, 0);
|
pm_wakeup_hard_event(&battery->device->dev);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state)
|
if (state)
|
||||||
pm_wakeup_event(&device->dev, 0);
|
pm_wakeup_hard_event(&device->dev);
|
||||||
|
|
||||||
ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
|
ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
|
||||||
if (ret == NOTIFY_DONE)
|
if (ret == NOTIFY_DONE)
|
||||||
|
@ -398,7 +398,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
|
||||||
} else {
|
} else {
|
||||||
int keycode;
|
int keycode;
|
||||||
|
|
||||||
pm_wakeup_event(&device->dev, 0);
|
pm_wakeup_hard_event(&device->dev);
|
||||||
if (button->suspended)
|
if (button->suspended)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -530,6 +530,7 @@ static int acpi_button_add(struct acpi_device *device)
|
||||||
lid_device = device;
|
lid_device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device_init_wakeup(&device->dev, true);
|
||||||
printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
|
printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <linux/pm_qos.h>
|
#include <linux/pm_qos.h>
|
||||||
#include <linux/pm_domain.h>
|
#include <linux/pm_domain.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/suspend.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
@ -399,7 +400,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
|
||||||
mutex_lock(&acpi_pm_notifier_lock);
|
mutex_lock(&acpi_pm_notifier_lock);
|
||||||
|
|
||||||
if (adev->wakeup.flags.notifier_present) {
|
if (adev->wakeup.flags.notifier_present) {
|
||||||
__pm_wakeup_event(adev->wakeup.ws, 0);
|
pm_wakeup_ws_event(adev->wakeup.ws, 0, true);
|
||||||
if (adev->wakeup.context.work.func)
|
if (adev->wakeup.context.work.func)
|
||||||
queue_pm_work(&adev->wakeup.context.work);
|
queue_pm_work(&adev->wakeup.context.work);
|
||||||
}
|
}
|
||||||
|
|
|
@ -662,14 +662,40 @@ static int acpi_freeze_prepare(void)
|
||||||
acpi_os_wait_events_complete();
|
acpi_os_wait_events_complete();
|
||||||
if (acpi_sci_irq_valid())
|
if (acpi_sci_irq_valid())
|
||||||
enable_irq_wake(acpi_sci_irq);
|
enable_irq_wake(acpi_sci_irq);
|
||||||
|
|
||||||
return 0;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
static void acpi_freeze_restore(void)
|
static void acpi_freeze_restore(void)
|
||||||
{
|
{
|
||||||
acpi_disable_wakeup_devices(ACPI_STATE_S0);
|
acpi_disable_wakeup_devices(ACPI_STATE_S0);
|
||||||
if (acpi_sci_irq_valid())
|
if (acpi_sci_irq_valid())
|
||||||
disable_irq_wake(acpi_sci_irq);
|
disable_irq_wake(acpi_sci_irq);
|
||||||
|
|
||||||
acpi_enable_all_runtime_gpes();
|
acpi_enable_all_runtime_gpes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,6 +707,8 @@ static void acpi_freeze_end(void)
|
||||||
static const struct platform_freeze_ops acpi_freeze_ops = {
|
static const struct platform_freeze_ops acpi_freeze_ops = {
|
||||||
.begin = acpi_freeze_begin,
|
.begin = acpi_freeze_begin,
|
||||||
.prepare = acpi_freeze_prepare,
|
.prepare = acpi_freeze_prepare,
|
||||||
|
.wake = acpi_freeze_wake,
|
||||||
|
.sync = acpi_freeze_sync,
|
||||||
.restore = acpi_freeze_restore,
|
.restore = acpi_freeze_restore,
|
||||||
.end = acpi_freeze_end,
|
.end = acpi_freeze_end,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1091,11 +1091,6 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a
|
||||||
if (async_error)
|
if (async_error)
|
||||||
goto Complete;
|
goto Complete;
|
||||||
|
|
||||||
if (pm_wakeup_pending()) {
|
|
||||||
async_error = -EBUSY;
|
|
||||||
goto Complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev->power.syscore || dev->power.direct_complete)
|
if (dev->power.syscore || dev->power.direct_complete)
|
||||||
goto Complete;
|
goto Complete;
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ bool events_check_enabled __read_mostly;
|
||||||
/* First wakeup IRQ seen by the kernel in the last cycle. */
|
/* First wakeup IRQ seen by the kernel in the last cycle. */
|
||||||
unsigned int pm_wakeup_irq __read_mostly;
|
unsigned int pm_wakeup_irq __read_mostly;
|
||||||
|
|
||||||
/* If set and the system is suspending, terminate the suspend. */
|
/* If greater than 0 and the system is suspending, terminate the suspend. */
|
||||||
static bool pm_abort_suspend __read_mostly;
|
static atomic_t pm_abort_suspend __read_mostly;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Combined counters of registered wakeup events and wakeup events in progress.
|
* Combined counters of registered wakeup events and wakeup events in progress.
|
||||||
|
@ -512,12 +512,13 @@ static bool wakeup_source_not_registered(struct wakeup_source *ws)
|
||||||
/**
|
/**
|
||||||
* wakup_source_activate - Mark given wakeup source as active.
|
* wakup_source_activate - Mark given wakeup source as active.
|
||||||
* @ws: Wakeup source to handle.
|
* @ws: Wakeup source to handle.
|
||||||
|
* @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
|
||||||
*
|
*
|
||||||
* Update the @ws' statistics and, if @ws has just been activated, notify the PM
|
* Update the @ws' statistics and, if @ws has just been activated, notify the PM
|
||||||
* core of the event by incrementing the counter of of wakeup events being
|
* core of the event by incrementing the counter of of wakeup events being
|
||||||
* processed.
|
* processed.
|
||||||
*/
|
*/
|
||||||
static void wakeup_source_activate(struct wakeup_source *ws)
|
static void wakeup_source_activate(struct wakeup_source *ws, bool hard)
|
||||||
{
|
{
|
||||||
unsigned int cec;
|
unsigned int cec;
|
||||||
|
|
||||||
|
@ -525,11 +526,8 @@ static void wakeup_source_activate(struct wakeup_source *ws)
|
||||||
"unregistered wakeup source\n"))
|
"unregistered wakeup source\n"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
if (hard)
|
||||||
* active wakeup source should bring the system
|
pm_system_wakeup();
|
||||||
* out of PM_SUSPEND_FREEZE state
|
|
||||||
*/
|
|
||||||
freeze_wake();
|
|
||||||
|
|
||||||
ws->active = true;
|
ws->active = true;
|
||||||
ws->active_count++;
|
ws->active_count++;
|
||||||
|
@ -546,8 +544,9 @@ static void wakeup_source_activate(struct wakeup_source *ws)
|
||||||
/**
|
/**
|
||||||
* wakeup_source_report_event - Report wakeup event using the given source.
|
* wakeup_source_report_event - Report wakeup event using the given source.
|
||||||
* @ws: Wakeup source to report the event for.
|
* @ws: Wakeup source to report the event for.
|
||||||
|
* @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
|
||||||
*/
|
*/
|
||||||
static void wakeup_source_report_event(struct wakeup_source *ws)
|
static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
|
||||||
{
|
{
|
||||||
ws->event_count++;
|
ws->event_count++;
|
||||||
/* This is racy, but the counter is approximate anyway. */
|
/* This is racy, but the counter is approximate anyway. */
|
||||||
|
@ -555,7 +554,7 @@ static void wakeup_source_report_event(struct wakeup_source *ws)
|
||||||
ws->wakeup_count++;
|
ws->wakeup_count++;
|
||||||
|
|
||||||
if (!ws->active)
|
if (!ws->active)
|
||||||
wakeup_source_activate(ws);
|
wakeup_source_activate(ws, hard);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -573,7 +572,7 @@ void __pm_stay_awake(struct wakeup_source *ws)
|
||||||
|
|
||||||
spin_lock_irqsave(&ws->lock, flags);
|
spin_lock_irqsave(&ws->lock, flags);
|
||||||
|
|
||||||
wakeup_source_report_event(ws);
|
wakeup_source_report_event(ws, false);
|
||||||
del_timer(&ws->timer);
|
del_timer(&ws->timer);
|
||||||
ws->timer_expires = 0;
|
ws->timer_expires = 0;
|
||||||
|
|
||||||
|
@ -739,9 +738,10 @@ static void pm_wakeup_timer_fn(unsigned long data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __pm_wakeup_event - Notify the PM core of a wakeup event.
|
* pm_wakeup_ws_event - Notify the PM core of a wakeup event.
|
||||||
* @ws: Wakeup source object associated with the event source.
|
* @ws: Wakeup source object associated with the event source.
|
||||||
* @msec: Anticipated event processing time (in milliseconds).
|
* @msec: Anticipated event processing time (in milliseconds).
|
||||||
|
* @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
|
||||||
*
|
*
|
||||||
* Notify the PM core of a wakeup event whose source is @ws that will take
|
* Notify the PM core of a wakeup event whose source is @ws that will take
|
||||||
* approximately @msec milliseconds to be processed by the kernel. If @ws is
|
* approximately @msec milliseconds to be processed by the kernel. If @ws is
|
||||||
|
@ -750,7 +750,7 @@ static void pm_wakeup_timer_fn(unsigned long data)
|
||||||
*
|
*
|
||||||
* It is safe to call this function from interrupt context.
|
* It is safe to call this function from interrupt context.
|
||||||
*/
|
*/
|
||||||
void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
|
void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned long expires;
|
unsigned long expires;
|
||||||
|
@ -760,7 +760,7 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
|
||||||
|
|
||||||
spin_lock_irqsave(&ws->lock, flags);
|
spin_lock_irqsave(&ws->lock, flags);
|
||||||
|
|
||||||
wakeup_source_report_event(ws);
|
wakeup_source_report_event(ws, hard);
|
||||||
|
|
||||||
if (!msec) {
|
if (!msec) {
|
||||||
wakeup_source_deactivate(ws);
|
wakeup_source_deactivate(ws);
|
||||||
|
@ -779,17 +779,17 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
|
||||||
unlock:
|
unlock:
|
||||||
spin_unlock_irqrestore(&ws->lock, flags);
|
spin_unlock_irqrestore(&ws->lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__pm_wakeup_event);
|
EXPORT_SYMBOL_GPL(pm_wakeup_ws_event);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pm_wakeup_event - Notify the PM core of a wakeup event.
|
* pm_wakeup_event - Notify the PM core of a wakeup event.
|
||||||
* @dev: Device the wakeup event is related to.
|
* @dev: Device the wakeup event is related to.
|
||||||
* @msec: Anticipated event processing time (in milliseconds).
|
* @msec: Anticipated event processing time (in milliseconds).
|
||||||
|
* @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
|
||||||
*
|
*
|
||||||
* Call __pm_wakeup_event() for the @dev's wakeup source object.
|
* Call pm_wakeup_ws_event() for the @dev's wakeup source object.
|
||||||
*/
|
*/
|
||||||
void pm_wakeup_event(struct device *dev, unsigned int msec)
|
void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
@ -797,10 +797,10 @@ void pm_wakeup_event(struct device *dev, unsigned int msec)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->power.lock, flags);
|
spin_lock_irqsave(&dev->power.lock, flags);
|
||||||
__pm_wakeup_event(dev->power.wakeup, msec);
|
pm_wakeup_ws_event(dev->power.wakeup, msec, hard);
|
||||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pm_wakeup_event);
|
EXPORT_SYMBOL_GPL(pm_wakeup_dev_event);
|
||||||
|
|
||||||
void pm_print_active_wakeup_sources(void)
|
void pm_print_active_wakeup_sources(void)
|
||||||
{
|
{
|
||||||
|
@ -856,20 +856,26 @@ bool pm_wakeup_pending(void)
|
||||||
pm_print_active_wakeup_sources();
|
pm_print_active_wakeup_sources();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret || pm_abort_suspend;
|
return ret || atomic_read(&pm_abort_suspend) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pm_system_wakeup(void)
|
void pm_system_wakeup(void)
|
||||||
{
|
{
|
||||||
pm_abort_suspend = true;
|
atomic_inc(&pm_abort_suspend);
|
||||||
freeze_wake();
|
freeze_wake();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pm_system_wakeup);
|
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;
|
pm_wakeup_irq = 0;
|
||||||
|
if (reset)
|
||||||
|
atomic_set(&pm_abort_suspend, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pm_system_irq_wakeup(unsigned int irq_number)
|
void pm_system_irq_wakeup(unsigned int irq_number)
|
||||||
|
|
|
@ -111,7 +111,8 @@ void cpuidle_use_deepest_state(bool enable)
|
||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
dev = cpuidle_get_device();
|
dev = cpuidle_get_device();
|
||||||
dev->use_deepest_state = enable;
|
if (dev)
|
||||||
|
dev->use_deepest_state = enable;
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1097,6 +1097,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
|
||||||
ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl),
|
ICPU(INTEL_FAM6_XEON_PHI_KNL, idle_cpu_knl),
|
||||||
ICPU(INTEL_FAM6_XEON_PHI_KNM, idle_cpu_knl),
|
ICPU(INTEL_FAM6_XEON_PHI_KNM, idle_cpu_knl),
|
||||||
ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt),
|
ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt),
|
||||||
|
ICPU(INTEL_FAM6_ATOM_GEMINI_LAKE, idle_cpu_bxt),
|
||||||
ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv),
|
ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv),
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
@ -1309,6 +1310,7 @@ static void intel_idle_state_table_update(void)
|
||||||
ivt_idle_state_table_update();
|
ivt_idle_state_table_update();
|
||||||
break;
|
break;
|
||||||
case INTEL_FAM6_ATOM_GOLDMONT:
|
case INTEL_FAM6_ATOM_GOLDMONT:
|
||||||
|
case INTEL_FAM6_ATOM_GEMINI_LAKE:
|
||||||
bxt_idle_state_table_update();
|
bxt_idle_state_table_update();
|
||||||
break;
|
break;
|
||||||
case INTEL_FAM6_SKYLAKE_DESKTOP:
|
case INTEL_FAM6_SKYLAKE_DESKTOP:
|
||||||
|
|
|
@ -1164,6 +1164,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
|
||||||
RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD, rapl_defaults_tng),
|
RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD, rapl_defaults_tng),
|
||||||
RAPL_CPU(INTEL_FAM6_ATOM_MOOREFIELD, rapl_defaults_ann),
|
RAPL_CPU(INTEL_FAM6_ATOM_MOOREFIELD, rapl_defaults_ann),
|
||||||
RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core),
|
RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core),
|
||||||
|
RAPL_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, rapl_defaults_core),
|
||||||
RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core),
|
RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core),
|
||||||
|
|
||||||
RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server),
|
RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server),
|
||||||
|
|
|
@ -106,8 +106,8 @@ extern void __pm_stay_awake(struct wakeup_source *ws);
|
||||||
extern void pm_stay_awake(struct device *dev);
|
extern void pm_stay_awake(struct device *dev);
|
||||||
extern void __pm_relax(struct wakeup_source *ws);
|
extern void __pm_relax(struct wakeup_source *ws);
|
||||||
extern void pm_relax(struct device *dev);
|
extern void pm_relax(struct device *dev);
|
||||||
extern void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec);
|
extern void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard);
|
||||||
extern void pm_wakeup_event(struct device *dev, unsigned int msec);
|
extern void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard);
|
||||||
|
|
||||||
#else /* !CONFIG_PM_SLEEP */
|
#else /* !CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
|
@ -182,9 +182,11 @@ static inline void __pm_relax(struct wakeup_source *ws) {}
|
||||||
|
|
||||||
static inline void pm_relax(struct device *dev) {}
|
static inline void pm_relax(struct device *dev) {}
|
||||||
|
|
||||||
static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) {}
|
static inline void pm_wakeup_ws_event(struct wakeup_source *ws,
|
||||||
|
unsigned int msec, bool hard) {}
|
||||||
|
|
||||||
static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {}
|
static inline void pm_wakeup_dev_event(struct device *dev, unsigned int msec,
|
||||||
|
bool hard) {}
|
||||||
|
|
||||||
#endif /* !CONFIG_PM_SLEEP */
|
#endif /* !CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
|
@ -201,4 +203,19 @@ static inline void wakeup_source_trash(struct wakeup_source *ws)
|
||||||
wakeup_source_drop(ws);
|
wakeup_source_drop(ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
|
||||||
|
{
|
||||||
|
return pm_wakeup_ws_event(ws, msec, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pm_wakeup_event(struct device *dev, unsigned int msec)
|
||||||
|
{
|
||||||
|
return pm_wakeup_dev_event(dev, msec, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pm_wakeup_hard_event(struct device *dev)
|
||||||
|
{
|
||||||
|
return pm_wakeup_dev_event(dev, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _LINUX_PM_WAKEUP_H */
|
#endif /* _LINUX_PM_WAKEUP_H */
|
||||||
|
|
|
@ -189,6 +189,8 @@ struct platform_suspend_ops {
|
||||||
struct platform_freeze_ops {
|
struct platform_freeze_ops {
|
||||||
int (*begin)(void);
|
int (*begin)(void);
|
||||||
int (*prepare)(void);
|
int (*prepare)(void);
|
||||||
|
void (*wake)(void);
|
||||||
|
void (*sync)(void);
|
||||||
void (*restore)(void);
|
void (*restore)(void);
|
||||||
void (*end)(void);
|
void (*end)(void);
|
||||||
};
|
};
|
||||||
|
@ -428,7 +430,8 @@ extern unsigned int pm_wakeup_irq;
|
||||||
|
|
||||||
extern bool pm_wakeup_pending(void);
|
extern bool pm_wakeup_pending(void);
|
||||||
extern void pm_system_wakeup(void);
|
extern void pm_system_wakeup(void);
|
||||||
extern void pm_wakeup_clear(void);
|
extern void pm_system_cancel_wakeup(void);
|
||||||
|
extern void pm_wakeup_clear(bool reset);
|
||||||
extern void pm_system_irq_wakeup(unsigned int irq_number);
|
extern void pm_system_irq_wakeup(unsigned int irq_number);
|
||||||
extern bool pm_get_wakeup_count(unsigned int *count, bool block);
|
extern bool pm_get_wakeup_count(unsigned int *count, bool block);
|
||||||
extern bool pm_save_wakeup_count(unsigned int count);
|
extern bool pm_save_wakeup_count(unsigned int count);
|
||||||
|
@ -478,7 +481,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
|
||||||
|
|
||||||
static inline bool pm_wakeup_pending(void) { return false; }
|
static inline bool pm_wakeup_pending(void) { return false; }
|
||||||
static inline void pm_system_wakeup(void) {}
|
static inline void pm_system_wakeup(void) {}
|
||||||
static inline void pm_wakeup_clear(void) {}
|
static inline void pm_wakeup_clear(bool reset) {}
|
||||||
static inline void pm_system_irq_wakeup(unsigned int irq_number) {}
|
static inline void pm_system_irq_wakeup(unsigned int irq_number) {}
|
||||||
|
|
||||||
static inline void lock_system_sleep(void) {}
|
static inline void lock_system_sleep(void) {}
|
||||||
|
|
|
@ -132,7 +132,7 @@ int freeze_processes(void)
|
||||||
if (!pm_freezing)
|
if (!pm_freezing)
|
||||||
atomic_inc(&system_freezing_cnt);
|
atomic_inc(&system_freezing_cnt);
|
||||||
|
|
||||||
pm_wakeup_clear();
|
pm_wakeup_clear(true);
|
||||||
pr_info("Freezing user space processes ... ");
|
pr_info("Freezing user space processes ... ");
|
||||||
pm_freezing = true;
|
pm_freezing = true;
|
||||||
error = try_to_freeze_tasks(true);
|
error = try_to_freeze_tasks(true);
|
||||||
|
|
|
@ -72,6 +72,8 @@ static void freeze_begin(void)
|
||||||
|
|
||||||
static void freeze_enter(void)
|
static void freeze_enter(void)
|
||||||
{
|
{
|
||||||
|
trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, true);
|
||||||
|
|
||||||
spin_lock_irq(&suspend_freeze_lock);
|
spin_lock_irq(&suspend_freeze_lock);
|
||||||
if (pm_wakeup_pending())
|
if (pm_wakeup_pending())
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -98,6 +100,27 @@ static void freeze_enter(void)
|
||||||
out:
|
out:
|
||||||
suspend_freeze_state = FREEZE_STATE_NONE;
|
suspend_freeze_state = FREEZE_STATE_NONE;
|
||||||
spin_unlock_irq(&suspend_freeze_lock);
|
spin_unlock_irq(&suspend_freeze_lock);
|
||||||
|
|
||||||
|
trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void s2idle_loop(void)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
freeze_enter();
|
||||||
|
|
||||||
|
if (freeze_ops && freeze_ops->wake)
|
||||||
|
freeze_ops->wake();
|
||||||
|
|
||||||
|
dpm_resume_noirq(PMSG_RESUME);
|
||||||
|
if (freeze_ops && freeze_ops->sync)
|
||||||
|
freeze_ops->sync();
|
||||||
|
|
||||||
|
if (pm_wakeup_pending())
|
||||||
|
break;
|
||||||
|
|
||||||
|
pm_wakeup_clear(false);
|
||||||
|
} while (!dpm_suspend_noirq(PMSG_SUSPEND));
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeze_wake(void)
|
void freeze_wake(void)
|
||||||
|
@ -371,10 +394,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
|
||||||
* all the devices are suspended.
|
* all the devices are suspended.
|
||||||
*/
|
*/
|
||||||
if (state == PM_SUSPEND_FREEZE) {
|
if (state == PM_SUSPEND_FREEZE) {
|
||||||
trace_suspend_resume(TPS("machine_suspend"), state, true);
|
s2idle_loop();
|
||||||
freeze_enter();
|
goto Platform_early_resume;
|
||||||
trace_suspend_resume(TPS("machine_suspend"), state, false);
|
|
||||||
goto Platform_wake;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error = disable_nonboot_cpus();
|
error = disable_nonboot_cpus();
|
||||||
|
|
Loading…
Reference in New Issue