Merge branches 'pm-cpufreq' and 'pm-cpuidle'
* pm-cpufreq:
cpufreq: unlock when failing cpufreq_update_policy()
intel_pstate: Correct rounding in busy calculation
cpufreq: cpufreq-cpu0: fix CPU_THERMAL dependency
* pm-cpuidle:
cpuidle: mvebu: Fix the name of the states
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 6eaa9cd..8849049 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1474,6 +1474,13 @@
js= [HW,JOY] Analog joystick
See Documentation/input/joystick.txt.
+ kaslr/nokaslr [X86]
+ Enable/disable kernel and module base offset ASLR
+ (Address Space Layout Randomization) if built into
+ the kernel. When CONFIG_HIBERNATION is selected,
+ kASLR is disabled by default. When kASLR is enabled,
+ hibernation will be disabled.
+
keepinitrd [HW,ARM]
kernelcore=nn[KMG] [KNL,X86,IA-64,PPC] This parameter
@@ -2110,10 +2117,6 @@
noapic [SMP,APIC] Tells the kernel to not make use of any
IOAPICs that may be present in the system.
- nokaslr [X86]
- Disable kernel and module base offset ASLR (Address
- Space Layout Randomization) if built into the kernel.
-
noautogroup Disable scheduler automatic task group creation.
nobats [PPC] Do not use BATs for mapping kernel lowmem
@@ -2184,6 +2187,8 @@
in certain environments such as networked servers or
real-time systems.
+ nohibernate [HIBERNATION] Disable hibernation and resume.
+
nohz= [KNL] Boottime enable/disable dynamic ticks
Valid arguments: on, off
Default: on
@@ -2980,6 +2985,7 @@
noresume Don't check if there's a hibernation image
present during boot.
nocompress Don't compress/decompress hibernation images.
+ no Disable hibernation and resume.
retain_initrd [RAM] Keep initrd memory after extraction
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 1a871b7..344387a 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -242,7 +242,7 @@
struct pci_dev *sac_only_dev;
};
-static struct ioc *ioc_list;
+static struct ioc *ioc_list, *ioc_found;
static int reserve_sba_gart = 1;
static SBA_INLINE void sba_mark_invalid(struct ioc *, dma_addr_t, size_t);
@@ -1809,20 +1809,13 @@
{ SX2000_IOC_ID, "sx2000", NULL },
};
-static struct ioc *
-ioc_init(unsigned long hpa, void *handle)
+static void ioc_init(unsigned long hpa, struct ioc *ioc)
{
- struct ioc *ioc;
struct ioc_iommu *info;
- ioc = kzalloc(sizeof(*ioc), GFP_KERNEL);
- if (!ioc)
- return NULL;
-
ioc->next = ioc_list;
ioc_list = ioc;
- ioc->handle = handle;
ioc->ioc_hpa = ioremap(hpa, 0x1000);
ioc->func_id = READ_REG(ioc->ioc_hpa + IOC_FUNC_ID);
@@ -1863,8 +1856,6 @@
"%s %d.%d HPA 0x%lx IOVA space %dMb at 0x%lx\n",
ioc->name, (ioc->rev >> 4) & 0xF, ioc->rev & 0xF,
hpa, ioc->iov_size >> 20, ioc->ibase);
-
- return ioc;
}
@@ -2031,22 +2022,21 @@
#endif
}
-static int
-acpi_sba_ioc_add(struct acpi_device *device,
- const struct acpi_device_id *not_used)
+static void acpi_sba_ioc_add(struct ioc *ioc)
{
- struct ioc *ioc;
+ acpi_handle handle = ioc->handle;
acpi_status status;
u64 hpa, length;
struct acpi_device_info *adi;
- status = hp_acpi_csr_space(device->handle, &hpa, &length);
+ ioc_found = ioc->next;
+ status = hp_acpi_csr_space(handle, &hpa, &length);
if (ACPI_FAILURE(status))
- return 1;
+ goto err;
- status = acpi_get_object_info(device->handle, &adi);
+ status = acpi_get_object_info(handle, &adi);
if (ACPI_FAILURE(status))
- return 1;
+ goto err;
/*
* For HWP0001, only SBA appears in ACPI namespace. It encloses the PCI
@@ -2067,13 +2057,13 @@
if (!iovp_shift)
iovp_shift = 12;
- ioc = ioc_init(hpa, device->handle);
- if (!ioc)
- return 1;
-
+ ioc_init(hpa, ioc);
/* setup NUMA node association */
- sba_map_ioc_to_node(ioc, device->handle);
- return 0;
+ sba_map_ioc_to_node(ioc, handle);
+ return;
+
+ err:
+ kfree(ioc);
}
static const struct acpi_device_id hp_ioc_iommu_device_ids[] = {
@@ -2081,9 +2071,26 @@
{"HWP0004", 0},
{"", 0},
};
+
+static int acpi_sba_ioc_attach(struct acpi_device *device,
+ const struct acpi_device_id *not_used)
+{
+ struct ioc *ioc;
+
+ ioc = kzalloc(sizeof(*ioc), GFP_KERNEL);
+ if (!ioc)
+ return -ENOMEM;
+
+ ioc->next = ioc_found;
+ ioc_found = ioc;
+ ioc->handle = device->handle;
+ return 1;
+}
+
+
static struct acpi_scan_handler acpi_sba_ioc_handler = {
.ids = hp_ioc_iommu_device_ids,
- .attach = acpi_sba_ioc_add,
+ .attach = acpi_sba_ioc_attach,
};
static int __init acpi_sba_ioc_init_acpi(void)
@@ -2118,9 +2125,12 @@
#endif
/*
- * ioc_list should be populated by the acpi_sba_ioc_handler's .attach()
+ * ioc_found should be populated by the acpi_sba_ioc_handler's .attach()
* routine, but that only happens if acpi_scan_init() has already run.
*/
+ while (ioc_found)
+ acpi_sba_ioc_add(ioc_found);
+
if (!ioc_list) {
#ifdef CONFIG_IA64_GENERIC
/*
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index fcefdda..a8f749e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1672,7 +1672,6 @@
config RANDOMIZE_BASE
bool "Randomize the address of the kernel image"
depends on RELOCATABLE
- depends on !HIBERNATION
default n
---help---
Randomizes the physical and virtual address at which the
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 4dbf967..fc6091a 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -289,10 +289,17 @@
unsigned long choice = (unsigned long)output;
unsigned long random;
- if (cmdline_find_option_bool("nokaslr")) {
- debug_putstr("KASLR disabled...\n");
+#ifdef CONFIG_HIBERNATION
+ if (!cmdline_find_option_bool("kaslr")) {
+ debug_putstr("KASLR disabled by default...\n");
goto out;
}
+#else
+ if (cmdline_find_option_bool("nokaslr")) {
+ debug_putstr("KASLR disabled by cmdline...\n");
+ goto out;
+ }
+#endif
/* Record the various known unsafe memory ranges. */
mem_avoid_init((unsigned long)input, input_size,
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 63407d2..9cb65b0 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -34,6 +34,9 @@
/* Offsets relative to LPSS_PRIVATE_OFFSET */
#define LPSS_CLK_DIVIDER_DEF_MASK (BIT(1) | BIT(16))
+#define LPSS_RESETS 0x04
+#define LPSS_RESETS_RESET_FUNC BIT(0)
+#define LPSS_RESETS_RESET_APB BIT(1)
#define LPSS_GENERAL 0x08
#define LPSS_GENERAL_LTR_MODE_SW BIT(2)
#define LPSS_GENERAL_UART_RTS_OVRD BIT(3)
@@ -99,6 +102,17 @@
writel(reg | LPSS_GENERAL_UART_RTS_OVRD, pdata->mmio_base + offset);
}
+static void lpss_i2c_setup(struct lpss_private_data *pdata)
+{
+ unsigned int offset;
+ u32 val;
+
+ offset = pdata->dev_desc->prv_offset + LPSS_RESETS;
+ val = readl(pdata->mmio_base + offset);
+ val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC;
+ writel(val, pdata->mmio_base + offset);
+}
+
static struct lpss_device_desc lpt_dev_desc = {
.clk_required = true,
.prv_offset = 0x800,
@@ -171,6 +185,7 @@
.prv_offset = 0x800,
.save_ctx = true,
.shared_clock = &i2c_clock,
+ .setup = lpss_i2c_setup,
};
#else
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index e48fc98..0d7116f 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -32,6 +32,7 @@
#include <linux/jiffies.h>
#include <linux/async.h>
#include <linux/dmi.h>
+#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <asm/unaligned.h>
@@ -70,6 +71,7 @@
MODULE_LICENSE("GPL");
static int battery_bix_broken_package;
+static int battery_notification_delay_ms;
static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
@@ -930,7 +932,10 @@
goto end;
}
alarm_string[count] = '\0';
- battery->alarm = simple_strtol(alarm_string, NULL, 0);
+ if (kstrtoint(alarm_string, 0, &battery->alarm)) {
+ result = -EINVAL;
+ goto end;
+ }
result = acpi_battery_set_alarm(battery);
end:
if (!result)
@@ -1062,6 +1067,14 @@
if (!battery)
return;
old = battery->bat.dev;
+ /*
+ * On Acer Aspire V5-573G notifications are sometimes triggered too
+ * early. For example, when AC is unplugged and notification is
+ * triggered, battery state is still reported as "Full", and changes to
+ * "Discharging" only after short delay, without any notification.
+ */
+ if (battery_notification_delay_ms > 0)
+ msleep(battery_notification_delay_ms);
if (event == ACPI_BATTERY_NOTIFY_INFO)
acpi_battery_refresh(battery);
acpi_battery_update(battery, false);
@@ -1106,14 +1119,35 @@
return 0;
}
+static int battery_bix_broken_package_quirk(const struct dmi_system_id *d)
+{
+ battery_bix_broken_package = 1;
+ return 0;
+}
+
+static int battery_notification_delay_quirk(const struct dmi_system_id *d)
+{
+ battery_notification_delay_ms = 1000;
+ return 0;
+}
+
static struct dmi_system_id bat_dmi_table[] = {
{
+ .callback = battery_bix_broken_package_quirk,
.ident = "NEC LZ750/LS",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
},
},
+ {
+ .callback = battery_notification_delay_quirk,
+ .ident = "Acer Aspire V5-573G",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
+ },
+ },
{},
};
@@ -1227,8 +1261,7 @@
if (acpi_disabled)
return;
- if (dmi_check_system(bat_dmi_table))
- battery_bix_broken_package = 1;
+ dmi_check_system(bat_dmi_table);
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_dir = acpi_lock_battery_dir();
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 3f2bdc8..bad25b0 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -235,7 +235,8 @@
static unsigned long acpi_rsdp;
static int __init setup_acpi_rsdp(char *arg)
{
- acpi_rsdp = simple_strtoul(arg, NULL, 16);
+ if (kstrtoul(arg, 16, &acpi_rsdp))
+ return -EINVAL;
return 0;
}
early_param("acpi_rsdp", setup_acpi_rsdp);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 05550ba..6d5a6cd 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -360,7 +360,8 @@
if (!str)
return -EINVAL;
- acpi_apic_instance = simple_strtoul(str, NULL, 0);
+ if (kstrtoint(str, 0, &acpi_apic_instance))
+ return -EINVAL;
pr_notice("Shall use APIC/MADT table %d\n", acpi_apic_instance);
diff --git a/drivers/cpuidle/cpuidle-armada-370-xp.c b/drivers/cpuidle/cpuidle-armada-370-xp.c
index 28587d0..a5fba02 100644
--- a/drivers/cpuidle/cpuidle-armada-370-xp.c
+++ b/drivers/cpuidle/cpuidle-armada-370-xp.c
@@ -55,7 +55,7 @@
.power_usage = 50,
.target_residency = 100,
.flags = CPUIDLE_FLAG_TIME_VALID,
- .name = "MV CPU IDLE",
+ .name = "Idle",
.desc = "CPU power down",
},
.states[2] = {
@@ -65,7 +65,7 @@
.target_residency = 1000,
.flags = CPUIDLE_FLAG_TIME_VALID |
ARMADA_370_XP_FLAG_DEEP_IDLE,
- .name = "MV CPU DEEP IDLE",
+ .name = "Deep idle",
.desc = "CPU and L2 Fabric power down",
},
.state_count = ARMADA_370_XP_MAX_STATES,
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 6eb1d3c..9b9b6f2 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -53,7 +53,7 @@
u8 bit_offset;
u8 access_size;
u64 address;
-} __attribute__ ((packed));
+} __packed;
struct acpi_processor_cx {
u8 valid;
@@ -83,7 +83,7 @@
u64 domain;
u64 coord_type;
u64 num_processors;
-} __attribute__ ((packed));
+} __packed;
struct acpi_pct_register {
u8 descriptor;
@@ -93,7 +93,7 @@
u8 bit_offset;
u8 reserved;
u64 address;
-} __attribute__ ((packed));
+} __packed;
struct acpi_processor_px {
u64 core_frequency; /* megahertz */
@@ -124,7 +124,7 @@
u64 domain;
u64 coord_type;
u64 num_processors;
-} __attribute__ ((packed));
+} __packed;
struct acpi_ptc_register {
u8 descriptor;
@@ -134,7 +134,7 @@
u8 bit_offset;
u8 reserved;
u64 address;
-} __attribute__ ((packed));
+} __packed;
struct acpi_processor_tx_tss {
u64 freqpercentage; /* */
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index f76994b..519064e 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -327,6 +327,7 @@
extern void hibernation_set_ops(const struct platform_hibernation_ops *ops);
extern int hibernate(void);
extern bool system_entering_hibernation(void);
+extern bool hibernation_available(void);
asmlinkage int swsusp_save(void);
extern struct pbe *restore_pblist;
#else /* CONFIG_HIBERNATION */
@@ -339,6 +340,7 @@
static inline void hibernation_set_ops(const struct platform_hibernation_ops *ops) {}
static inline int hibernate(void) { return -ENOSYS; }
static inline bool system_entering_hibernation(void) { return false; }
+static inline bool hibernation_available(void) { return false; }
#endif /* CONFIG_HIBERNATION */
/* Hibernation and suspend events */
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 49e0a20..fcc2611 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -35,6 +35,7 @@
static int nocompress;
static int noresume;
+static int nohibernate;
static int resume_wait;
static unsigned int resume_delay;
static char resume_file[256] = CONFIG_PM_STD_PARTITION;
@@ -62,6 +63,11 @@
static const struct platform_hibernation_ops *hibernation_ops;
+bool hibernation_available(void)
+{
+ return (nohibernate == 0);
+}
+
/**
* hibernation_set_ops - Set the global hibernate operations.
* @ops: Hibernation operations to use in subsequent hibernation transitions.
@@ -642,6 +648,11 @@
{
int error;
+ if (!hibernation_available()) {
+ pr_debug("PM: Hibernation not available.\n");
+ return -EPERM;
+ }
+
lock_system_sleep();
/* The snapshot device should not be opened while we're running */
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
@@ -734,7 +745,7 @@
/*
* If the user said "noresume".. bail out early.
*/
- if (noresume)
+ if (noresume || !hibernation_available())
return 0;
/*
@@ -900,6 +911,9 @@
int i;
char *start = buf;
+ if (!hibernation_available())
+ return sprintf(buf, "[disabled]\n");
+
for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
if (!hibernation_modes[i])
continue;
@@ -934,6 +948,9 @@
char *p;
int mode = HIBERNATION_INVALID;
+ if (!hibernation_available())
+ return -EPERM;
+
p = memchr(buf, '\n', n);
len = p ? p - buf : n;
@@ -1101,6 +1118,10 @@
noresume = 1;
else if (!strncmp(str, "nocompress", 10))
nocompress = 1;
+ else if (!strncmp(str, "no", 2)) {
+ noresume = 1;
+ nohibernate = 1;
+ }
return 1;
}
@@ -1125,9 +1146,23 @@
return 1;
}
+static int __init nohibernate_setup(char *str)
+{
+ noresume = 1;
+ nohibernate = 1;
+ return 1;
+}
+
+static int __init kaslr_nohibernate_setup(char *str)
+{
+ return nohibernate_setup(str);
+}
+
__setup("noresume", noresume_setup);
__setup("resume_offset=", resume_offset_setup);
__setup("resume=", resume_setup);
__setup("hibernate=", hibernate_setup);
__setup("resumewait", resumewait_setup);
__setup("resumedelay=", resumedelay_setup);
+__setup("nohibernate", nohibernate_setup);
+__setup("kaslr", kaslr_nohibernate_setup);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 573410d..8e90f33 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -300,13 +300,11 @@
s += sprintf(s,"%s ", pm_states[i].label);
#endif
-#ifdef CONFIG_HIBERNATION
- s += sprintf(s, "%s\n", "disk");
-#else
+ if (hibernation_available())
+ s += sprintf(s, "disk ");
if (s != buf)
/* convert the last space to a newline */
*(s-1) = '\n';
-#endif
return (s - buf);
}
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 98d3575..526e891 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -49,6 +49,9 @@
struct snapshot_data *data;
int error;
+ if (!hibernation_available())
+ return -EPERM;
+
lock_system_sleep();
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {