Merge branches 'acpi-pm' and 'pm-sleep'

* acpi-pm:
  platform/x86: surfacepro3: Support for wakeup from suspend-to-idle
  ACPI / PM: Use Low Power S0 Idle on more systems
  ACPI / PM: Make it possible to ignore the system sleep blacklist

* pm-sleep:
  PM / hibernate: Drop unused parameter of enough_swap
  block, scsi: Fix race between SPI domain validation and system suspend
  PM / sleep: Make lock/unlock_system_sleep() available to kernel modules
  PM: hibernate: Do not subtract NR_FILE_MAPPED in minimum_image_size()
This commit is contained in:
Rafael J. Wysocki 2018-01-18 02:55:28 +01:00
commit bcaea4678f
10 changed files with 73 additions and 38 deletions

View File

@ -223,7 +223,7 @@
acpi_sleep= [HW,ACPI] Sleep options acpi_sleep= [HW,ACPI] Sleep options
Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
old_ordering, nonvs, sci_force_enable } old_ordering, nonvs, sci_force_enable, nobl }
See Documentation/power/video.txt for information on See Documentation/power/video.txt for information on
s3_bios and s3_mode. s3_bios and s3_mode.
s3_beep is for debugging; it makes the PC's speaker beep s3_beep is for debugging; it makes the PC's speaker beep
@ -239,6 +239,9 @@
sci_force_enable causes the kernel to set SCI_EN directly sci_force_enable causes the kernel to set SCI_EN directly
on resume from S1/S3 (which is against the ACPI spec, on resume from S1/S3 (which is against the ACPI spec,
but some broken systems don't work without it). but some broken systems don't work without it).
nobl causes the internal blacklist of systems known to
behave incorrectly in some ways with respect to system
suspend and resume to be ignored (use wisely).
acpi_use_timer_override [HW,ACPI] acpi_use_timer_override [HW,ACPI]
Use timer override. For some broken Nvidia NF5 boards Use timer override. For some broken Nvidia NF5 boards

View File

@ -138,6 +138,8 @@ static int __init acpi_sleep_setup(char *str)
acpi_nvs_nosave_s3(); acpi_nvs_nosave_s3();
if (strncmp(str, "old_ordering", 12) == 0) if (strncmp(str, "old_ordering", 12) == 0)
acpi_old_suspend_ordering(); acpi_old_suspend_ordering();
if (strncmp(str, "nobl", 4) == 0)
acpi_sleep_no_blacklist();
str = strchr(str, ','); str = strchr(str, ',');
if (str != NULL) if (str != NULL)
str += strspn(str, ", \t"); str += strspn(str, ", \t");

View File

@ -367,10 +367,20 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
{}, {},
}; };
static bool ignore_blacklist;
void __init acpi_sleep_no_blacklist(void)
{
ignore_blacklist = true;
}
static void __init acpi_sleep_dmi_check(void) static void __init acpi_sleep_dmi_check(void)
{ {
int year; int year;
if (ignore_blacklist)
return;
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012) if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012)
acpi_nvs_nosave_s3(); acpi_nvs_nosave_s3();
@ -697,7 +707,8 @@ static const struct acpi_device_id lps0_device_ids[] = {
#define ACPI_LPS0_ENTRY 5 #define ACPI_LPS0_ENTRY 5
#define ACPI_LPS0_EXIT 6 #define ACPI_LPS0_EXIT 6
#define ACPI_S2IDLE_FUNC_MASK ((1 << ACPI_LPS0_ENTRY) | (1 << ACPI_LPS0_EXIT)) #define ACPI_LPS0_SCREEN_MASK ((1 << ACPI_LPS0_SCREEN_OFF) | (1 << ACPI_LPS0_SCREEN_ON))
#define ACPI_LPS0_PLATFORM_MASK ((1 << ACPI_LPS0_ENTRY) | (1 << ACPI_LPS0_EXIT))
static acpi_handle lps0_device_handle; static acpi_handle lps0_device_handle;
static guid_t lps0_dsm_guid; static guid_t lps0_dsm_guid;
@ -900,7 +911,8 @@ static int lps0_device_attach(struct acpi_device *adev,
if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) { if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) {
char bitmask = *(char *)out_obj->buffer.pointer; char bitmask = *(char *)out_obj->buffer.pointer;
if ((bitmask & ACPI_S2IDLE_FUNC_MASK) == ACPI_S2IDLE_FUNC_MASK) { if ((bitmask & ACPI_LPS0_PLATFORM_MASK) == ACPI_LPS0_PLATFORM_MASK ||
(bitmask & ACPI_LPS0_SCREEN_MASK) == ACPI_LPS0_SCREEN_MASK) {
lps0_dsm_func_mask = bitmask; lps0_dsm_func_mask = bitmask;
lps0_device_handle = adev->handle; lps0_device_handle = adev->handle;
/* /*

View File

@ -119,7 +119,7 @@ static void surface_button_notify(struct acpi_device *device, u32 event)
if (key_code == KEY_RESERVED) if (key_code == KEY_RESERVED)
return; return;
if (pressed) if (pressed)
pm_wakeup_event(&device->dev, 0); pm_wakeup_dev_event(&device->dev, 0, button->suspended);
if (button->suspended) if (button->suspended)
return; return;
input_report_key(input, key_code, pressed?1:0); input_report_key(input, key_code, pressed?1:0);
@ -185,6 +185,8 @@ static int surface_button_add(struct acpi_device *device)
error = input_register_device(input); error = input_register_device(input);
if (error) if (error)
goto err_free_input; goto err_free_input;
device_init_wakeup(&device->dev, true);
dev_info(&device->dev, dev_info(&device->dev,
"%s [%s]\n", name, acpi_device_bid(device)); "%s [%s]\n", name, acpi_device_bid(device));
return 0; return 0;

View File

@ -26,6 +26,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/suspend.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include "scsi_priv.h" #include "scsi_priv.h"
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
@ -1009,11 +1010,20 @@ spi_dv_device(struct scsi_device *sdev)
u8 *buffer; u8 *buffer;
const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; const int len = SPI_MAX_ECHO_BUFFER_SIZE*2;
/*
* Because this function and the power management code both call
* scsi_device_quiesce(), it is not safe to perform domain validation
* while suspend or resume is in progress. Hence the
* lock/unlock_system_sleep() calls.
*/
lock_system_sleep();
if (unlikely(spi_dv_in_progress(starget))) if (unlikely(spi_dv_in_progress(starget)))
return; goto unlock;
if (unlikely(scsi_device_get(sdev))) if (unlikely(scsi_device_get(sdev)))
return; goto unlock;
spi_dv_in_progress(starget) = 1; spi_dv_in_progress(starget) = 1;
buffer = kzalloc(len, GFP_KERNEL); buffer = kzalloc(len, GFP_KERNEL);
@ -1049,6 +1059,8 @@ spi_dv_device(struct scsi_device *sdev)
out_put: out_put:
spi_dv_in_progress(starget) = 0; spi_dv_in_progress(starget) = 0;
scsi_device_put(sdev); scsi_device_put(sdev);
unlock:
unlock_system_sleep();
} }
EXPORT_SYMBOL(spi_dv_device); EXPORT_SYMBOL(spi_dv_device);

View File

@ -451,6 +451,7 @@ void __init acpi_no_s4_hw_signature(void);
void __init acpi_old_suspend_ordering(void); void __init acpi_old_suspend_ordering(void);
void __init acpi_nvs_nosave(void); void __init acpi_nvs_nosave(void);
void __init acpi_nvs_nosave_s3(void); void __init acpi_nvs_nosave_s3(void);
void __init acpi_sleep_no_blacklist(void);
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
struct acpi_osc_context { struct acpi_osc_context {

View File

@ -443,32 +443,8 @@ extern bool pm_save_wakeup_count(unsigned int count);
extern void pm_wakep_autosleep_enabled(bool set); extern void pm_wakep_autosleep_enabled(bool set);
extern void pm_print_active_wakeup_sources(void); extern void pm_print_active_wakeup_sources(void);
static inline void lock_system_sleep(void) extern void lock_system_sleep(void);
{ extern void unlock_system_sleep(void);
current->flags |= PF_FREEZER_SKIP;
mutex_lock(&pm_mutex);
}
static inline void unlock_system_sleep(void)
{
/*
* Don't use freezer_count() because we don't want the call to
* try_to_freeze() here.
*
* Reason:
* Fundamentally, we just don't need it, because freezing condition
* doesn't come into effect until we release the pm_mutex lock,
* since the freezer always works with pm_mutex held.
*
* More importantly, in the case of hibernation,
* unlock_system_sleep() gets called in snapshot_read() and
* snapshot_write() when the freezing condition is still in effect.
* Which means, if we use try_to_freeze() here, it would make them
* enter the refrigerator, thus causing hibernation to lockup.
*/
current->flags &= ~PF_FREEZER_SKIP;
mutex_unlock(&pm_mutex);
}
#else /* !CONFIG_PM_SLEEP */ #else /* !CONFIG_PM_SLEEP */

View File

@ -22,6 +22,35 @@ DEFINE_MUTEX(pm_mutex);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
void lock_system_sleep(void)
{
current->flags |= PF_FREEZER_SKIP;
mutex_lock(&pm_mutex);
}
EXPORT_SYMBOL_GPL(lock_system_sleep);
void unlock_system_sleep(void)
{
/*
* Don't use freezer_count() because we don't want the call to
* try_to_freeze() here.
*
* Reason:
* Fundamentally, we just don't need it, because freezing condition
* doesn't come into effect until we release the pm_mutex lock,
* since the freezer always works with pm_mutex held.
*
* More importantly, in the case of hibernation,
* unlock_system_sleep() gets called in snapshot_read() and
* snapshot_write() when the freezing condition is still in effect.
* Which means, if we use try_to_freeze() here, it would make them
* enter the refrigerator, thus causing hibernation to lockup.
*/
current->flags &= ~PF_FREEZER_SKIP;
mutex_unlock(&pm_mutex);
}
EXPORT_SYMBOL_GPL(unlock_system_sleep);
/* Routines for PM-transition notifications */ /* Routines for PM-transition notifications */
static BLOCKING_NOTIFIER_HEAD(pm_chain_head); static BLOCKING_NOTIFIER_HEAD(pm_chain_head);

View File

@ -1645,8 +1645,7 @@ static unsigned long free_unnecessary_pages(void)
* [number of saveable pages] - [number of pages that can be freed in theory] * [number of saveable pages] - [number of pages that can be freed in theory]
* *
* where the second term is the sum of (1) reclaimable slab pages, (2) active * where the second term is the sum of (1) reclaimable slab pages, (2) active
* and (3) inactive anonymous pages, (4) active and (5) inactive file pages, * and (3) inactive anonymous pages, (4) active and (5) inactive file pages.
* minus mapped file pages.
*/ */
static unsigned long minimum_image_size(unsigned long saveable) static unsigned long minimum_image_size(unsigned long saveable)
{ {
@ -1656,8 +1655,7 @@ static unsigned long minimum_image_size(unsigned long saveable)
+ global_node_page_state(NR_ACTIVE_ANON) + global_node_page_state(NR_ACTIVE_ANON)
+ global_node_page_state(NR_INACTIVE_ANON) + global_node_page_state(NR_INACTIVE_ANON)
+ global_node_page_state(NR_ACTIVE_FILE) + global_node_page_state(NR_ACTIVE_FILE)
+ global_node_page_state(NR_INACTIVE_FILE) + global_node_page_state(NR_INACTIVE_FILE);
- global_node_page_state(NR_FILE_MAPPED);
return saveable <= size ? 0 : saveable - size; return saveable <= size ? 0 : saveable - size;
} }

View File

@ -879,7 +879,7 @@ out_clean:
* space avaiable from the resume partition. * space avaiable from the resume partition.
*/ */
static int enough_swap(unsigned int nr_pages, unsigned int flags) static int enough_swap(unsigned int nr_pages)
{ {
unsigned int free_swap = count_swap_pages(root_swap, 1); unsigned int free_swap = count_swap_pages(root_swap, 1);
unsigned int required; unsigned int required;
@ -915,7 +915,7 @@ int swsusp_write(unsigned int flags)
return error; return error;
} }
if (flags & SF_NOCOMPRESS_MODE) { if (flags & SF_NOCOMPRESS_MODE) {
if (!enough_swap(pages, flags)) { if (!enough_swap(pages)) {
pr_err("Not enough free swap\n"); pr_err("Not enough free swap\n");
error = -ENOSPC; error = -ENOSPC;
goto out_finish; goto out_finish;