Commit 0d22df90 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm-4.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
 "These revert one problematic commit related to system sleep and fix
  one recent intel_pstate regression.

  Specifics:

   - Revert a recent commit that attempted to avoid spurious wakeups
     from suspend-to-idle via ACPI SCI, but introduced regressions on
     some systems (Rafael Wysocki).

     We will get back to the problem it tried to address in the next
     cycle.

   - Fix a possible division by 0 during intel_pstate initialization
     due to a missing check (Rafael Wysocki)"

* tag 'pm-4.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  Revert "ACPI / sleep: Ignore spurious SCI wakeups from suspend-to-idle"
  cpufreq: intel_pstate: Avoid division by 0 in min_perf_pct_min()
parents aea4156c fbd78afe
...@@ -782,7 +782,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume) ...@@ -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_hard_event(&battery->device->dev); pm_wakeup_event(&battery->device->dev, 0);
return result; return result;
} }
......
...@@ -217,7 +217,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state) ...@@ -217,7 +217,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
} }
if (state) if (state)
pm_wakeup_hard_event(&device->dev); pm_wakeup_event(&device->dev, 0);
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)
...@@ -402,7 +402,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) ...@@ -402,7 +402,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
} else { } else {
int keycode; int keycode;
pm_wakeup_hard_event(&device->dev); pm_wakeup_event(&device->dev, 0);
if (button->suspended) if (button->suspended)
break; break;
...@@ -534,7 +534,6 @@ static int acpi_button_add(struct acpi_device *device) ...@@ -534,7 +534,6 @@ 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,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#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"
...@@ -400,7 +399,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) ...@@ -400,7 +399,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_ws_event(adev->wakeup.ws, 0, true); __pm_wakeup_event(adev->wakeup.ws, 0);
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);
} }
......
...@@ -663,40 +663,14 @@ static int acpi_freeze_prepare(void) ...@@ -663,40 +663,14 @@ 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();
} }
...@@ -708,8 +682,6 @@ static void acpi_freeze_end(void) ...@@ -708,8 +682,6 @@ 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,6 +1091,11 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a ...@@ -1091,6 +1091,11 @@ 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; ...@@ -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 greater than 0 and the system is suspending, terminate the suspend. */ /* If set and the system is suspending, terminate the suspend. */
static atomic_t pm_abort_suspend __read_mostly; static bool 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.
...@@ -855,26 +855,20 @@ bool pm_wakeup_pending(void) ...@@ -855,26 +855,20 @@ bool pm_wakeup_pending(void)
pm_print_active_wakeup_sources(); pm_print_active_wakeup_sources();
} }
return ret || atomic_read(&pm_abort_suspend) > 0; return ret || pm_abort_suspend;
} }
void pm_system_wakeup(void) void pm_system_wakeup(void)
{ {
atomic_inc(&pm_abort_suspend); pm_abort_suspend = true;
freeze_wake(); freeze_wake();
} }
EXPORT_SYMBOL_GPL(pm_system_wakeup); EXPORT_SYMBOL_GPL(pm_system_wakeup);
void pm_system_cancel_wakeup(void) void pm_wakeup_clear(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)
......
...@@ -571,9 +571,10 @@ static inline void update_turbo_state(void) ...@@ -571,9 +571,10 @@ static inline void update_turbo_state(void)
static int min_perf_pct_min(void) static int min_perf_pct_min(void)
{ {
struct cpudata *cpu = all_cpu_data[0]; struct cpudata *cpu = all_cpu_data[0];
int turbo_pstate = cpu->pstate.turbo_pstate;
return DIV_ROUND_UP(cpu->pstate.min_pstate * 100, return turbo_pstate ?
cpu->pstate.turbo_pstate); DIV_ROUND_UP(cpu->pstate.min_pstate * 100, turbo_pstate) : 0;
} }
static s16 intel_pstate_get_epb(struct cpudata *cpu_data) static s16 intel_pstate_get_epb(struct cpudata *cpu_data)
......
...@@ -189,8 +189,6 @@ struct platform_suspend_ops { ...@@ -189,8 +189,6 @@ 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);
}; };
...@@ -430,8 +428,7 @@ extern unsigned int pm_wakeup_irq; ...@@ -430,8 +428,7 @@ 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_system_cancel_wakeup(void); extern void pm_wakeup_clear(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);
...@@ -481,7 +478,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) ...@@ -481,7 +478,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(bool reset) {} static inline void pm_wakeup_clear(void) {}
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) ...@@ -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(true); pm_wakeup_clear();
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,8 +72,6 @@ static void freeze_begin(void) ...@@ -72,8 +72,6 @@ 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;
...@@ -100,27 +98,6 @@ static void freeze_enter(void) ...@@ -100,27 +98,6 @@ 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)
...@@ -394,8 +371,10 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) ...@@ -394,8 +371,10 @@ 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) {
s2idle_loop(); trace_suspend_resume(TPS("machine_suspend"), state, true);
goto Platform_early_resume; freeze_enter();
trace_suspend_resume(TPS("machine_suspend"), state, false);
goto Platform_wake;
} }
error = disable_nonboot_cpus(); error = disable_nonboot_cpus();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment