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:
Коммит
bcaea4678f
|
@ -223,7 +223,7 @@
|
|||
|
||||
acpi_sleep= [HW,ACPI] Sleep options
|
||||
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
|
||||
s3_bios and s3_mode.
|
||||
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
|
||||
on resume from S1/S3 (which is against the ACPI spec,
|
||||
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]
|
||||
Use timer override. For some broken Nvidia NF5 boards
|
||||
|
|
|
@ -138,6 +138,8 @@ static int __init acpi_sleep_setup(char *str)
|
|||
acpi_nvs_nosave_s3();
|
||||
if (strncmp(str, "old_ordering", 12) == 0)
|
||||
acpi_old_suspend_ordering();
|
||||
if (strncmp(str, "nobl", 4) == 0)
|
||||
acpi_sleep_no_blacklist();
|
||||
str = strchr(str, ',');
|
||||
if (str != NULL)
|
||||
str += strspn(str, ", \t");
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
int year;
|
||||
|
||||
if (ignore_blacklist)
|
||||
return;
|
||||
|
||||
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012)
|
||||
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_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 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) {
|
||||
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_device_handle = adev->handle;
|
||||
/*
|
||||
|
|
|
@ -119,7 +119,7 @@ static void surface_button_notify(struct acpi_device *device, u32 event)
|
|||
if (key_code == KEY_RESERVED)
|
||||
return;
|
||||
if (pressed)
|
||||
pm_wakeup_event(&device->dev, 0);
|
||||
pm_wakeup_dev_event(&device->dev, 0, button->suspended);
|
||||
if (button->suspended)
|
||||
return;
|
||||
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);
|
||||
if (error)
|
||||
goto err_free_input;
|
||||
|
||||
device_init_wakeup(&device->dev, true);
|
||||
dev_info(&device->dev,
|
||||
"%s [%s]\n", name, acpi_device_bid(device));
|
||||
return 0;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include "scsi_priv.h"
|
||||
#include <scsi/scsi_device.h>
|
||||
|
@ -1009,11 +1010,20 @@ spi_dv_device(struct scsi_device *sdev)
|
|||
u8 *buffer;
|
||||
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)))
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
if (unlikely(scsi_device_get(sdev)))
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
spi_dv_in_progress(starget) = 1;
|
||||
|
||||
buffer = kzalloc(len, GFP_KERNEL);
|
||||
|
@ -1049,6 +1059,8 @@ spi_dv_device(struct scsi_device *sdev)
|
|||
out_put:
|
||||
spi_dv_in_progress(starget) = 0;
|
||||
scsi_device_put(sdev);
|
||||
unlock:
|
||||
unlock_system_sleep();
|
||||
}
|
||||
EXPORT_SYMBOL(spi_dv_device);
|
||||
|
||||
|
|
|
@ -451,6 +451,7 @@ void __init acpi_no_s4_hw_signature(void);
|
|||
void __init acpi_old_suspend_ordering(void);
|
||||
void __init acpi_nvs_nosave(void);
|
||||
void __init acpi_nvs_nosave_s3(void);
|
||||
void __init acpi_sleep_no_blacklist(void);
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
struct acpi_osc_context {
|
||||
|
|
|
@ -443,32 +443,8 @@ extern bool pm_save_wakeup_count(unsigned int count);
|
|||
extern void pm_wakep_autosleep_enabled(bool set);
|
||||
extern void pm_print_active_wakeup_sources(void);
|
||||
|
||||
static inline void lock_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);
|
||||
}
|
||||
extern void lock_system_sleep(void);
|
||||
extern void unlock_system_sleep(void);
|
||||
|
||||
#else /* !CONFIG_PM_SLEEP */
|
||||
|
||||
|
|
|
@ -22,6 +22,35 @@ DEFINE_MUTEX(pm_mutex);
|
|||
|
||||
#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 */
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
|
||||
|
|
|
@ -1645,8 +1645,7 @@ static unsigned long free_unnecessary_pages(void)
|
|||
* [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
|
||||
* and (3) inactive anonymous pages, (4) active and (5) inactive file pages,
|
||||
* minus mapped file pages.
|
||||
* and (3) inactive anonymous pages, (4) active and (5) inactive file pages.
|
||||
*/
|
||||
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_INACTIVE_ANON)
|
||||
+ global_node_page_state(NR_ACTIVE_FILE)
|
||||
+ global_node_page_state(NR_INACTIVE_FILE)
|
||||
- global_node_page_state(NR_FILE_MAPPED);
|
||||
+ global_node_page_state(NR_INACTIVE_FILE);
|
||||
|
||||
return saveable <= size ? 0 : saveable - size;
|
||||
}
|
||||
|
|
|
@ -879,7 +879,7 @@ out_clean:
|
|||
* 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 required;
|
||||
|
@ -915,7 +915,7 @@ int swsusp_write(unsigned int flags)
|
|||
return error;
|
||||
}
|
||||
if (flags & SF_NOCOMPRESS_MODE) {
|
||||
if (!enough_swap(pages, flags)) {
|
||||
if (!enough_swap(pages)) {
|
||||
pr_err("Not enough free swap\n");
|
||||
error = -ENOSPC;
|
||||
goto out_finish;
|
||||
|
|
Загрузка…
Ссылка в новой задаче