]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'pm+acpi-3.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 Jun 2014 04:58:57 +0000 (18:58 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 Jun 2014 04:58:57 +0000 (18:58 -1000)
Pull ACPI and power management fixes from Rafael Wysocki:
 "These are fixes mostly (ia64 regression related to the ACPI
  enumeration of devices, cpufreq regressions, fix for I2C controllers
  included in Intel SoCs, mvebu cpuidle driver fix related to sysfs)
  plus additional kernel command line arguments from Kees to make it
  possible to build kernel images with hibernation and the kernel
  address space randomization included simultaneously, a new ACPI
  battery driver quirk for a system with a broken BIOS and a couple of
  ACPI core cleanups.

  Specifics:

   - Fix for an ia64 regression introduced during the 3.11 cycle by a
     commit that modified the hardware initialization ordering and made
     device discovery fail on some systems.

   - Fix for a build problem on systems where the cpufreq-cpu0 driver is
     built-in and the cpu-thermal driver is modular from Arnd Bergmann.

   - Fix for a recently introduced computational mistake in the
     intel_pstate driver that leads to excessive rounding errors from
     Doug Smythies.

   - Fix for a failure code path in cpufreq_update_policy() that fails
     to unlock the locks acquired previously from Aaron Plattner.

   - Fix for the cpuidle mvebu driver to use shorter state names which
     will prevent the sysfs interface from returning mangled strings.
     From Gregory Clement.

   - ACPI LPSS driver fix to make sure that the I2C controllers included
     in BayTrail SoCs are not held in the reset state while they are
     being probed from Mika Westerberg.

   - New kernel command line arguments making it possible to build
     kernel images with hibernation and kASLR included at the same time
     and to select which of them will be used via the command line (they
     are still functionally mutually exclusive, though).  From Kees
     Cook.

   - ACPI battery driver quirk for Acer Aspire V5-573G that fails to
     send battery status change notifications timely from Alexander
     Mezin.

   - Two ACPI core cleanups from Christoph Jaeger and Fabian Frederick"

* tag 'pm+acpi-3.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpuidle: mvebu: Fix the name of the states
  cpufreq: unlock when failing cpufreq_update_policy()
  intel_pstate: Correct rounding in busy calculation
  ACPI: use kstrto*() instead of simple_strto*()
  ACPI / processor replace __attribute__((packed)) by __packed
  ACPI / battery: add quirk for Acer Aspire V5-573G
  ACPI / battery: use callback for setting up quirks
  ACPI / LPSS: Take I2C host controllers out of reset
  x86, kaslr: boot-time selectable with hibernation
  PM / hibernate: introduce "nohibernate" boot parameter
  cpufreq: cpufreq-cpu0: fix CPU_THERMAL dependency
  ACPI / ia64 / sba_iommu: Restore the working initialization ordering

17 files changed:
Documentation/kernel-parameters.txt
arch/ia64/hp/common/sba_iommu.c
arch/x86/Kconfig
arch/x86/boot/compressed/aslr.c
drivers/acpi/acpi_lpss.c
drivers/acpi/battery.c
drivers/acpi/osl.c
drivers/acpi/tables.c
drivers/cpufreq/Kconfig
drivers/cpufreq/cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpuidle/cpuidle-armada-370-xp.c
include/acpi/processor.h
include/linux/suspend.h
kernel/power/hibernate.c
kernel/power/main.c
kernel/power/user.c

index 6eaa9cdb7094b5785aecc54e55d4cb5bd08a8de9..884904975d0b98ec126f22b0a51b6b26569d0b99 100644 (file)
@@ -1474,6 +1474,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        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 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        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 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        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 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                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
 
index 1a871b78e5709232f1f5f3e9aa8021cb4d02dd59..344387a554066b7c7b455c08ff583ede09d82625 100644 (file)
@@ -242,7 +242,7 @@ struct ioc {
        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 @@ static struct ioc_iommu ioc_iommu_info[] __initdata = {
        { 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 @@ ioc_init(unsigned long hpa, void *handle)
                "%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 @@ sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
 #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 @@ acpi_sba_ioc_add(struct acpi_device *device,
        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 @@ static const struct acpi_device_id hp_ioc_iommu_device_ids[] = {
        {"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 @@ sba_init(void)
 #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
                /*
index fcefdda5136dde37c2a8893519912286f6551cf5..a8f749ef0fdcc626a16d2a94e02c6a65d26a2fe8 100644 (file)
@@ -1672,7 +1672,6 @@ config RELOCATABLE
 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
index 4dbf967da50daab8c7ed9f3952fa08b18b5b6271..fc6091abedb7ff363da950a0766f45f9834cf1df 100644 (file)
@@ -289,10 +289,17 @@ unsigned char *choose_kernel_location(unsigned char *input,
        unsigned long choice = (unsigned long)output;
        unsigned long random;
 
+#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...\n");
+               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,
index 63407d264885a200db03d8b152d53efcfae13cbe..9cb65b0e7597287531144d876d9eaed132ae7b5a 100644 (file)
@@ -34,6 +34,9 @@ ACPI_MODULE_NAME("acpi_lpss");
 
 /* 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 @@ static void lpss_uart_setup(struct lpss_private_data *pdata)
        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 @@ static struct lpss_device_desc byt_i2c_dev_desc = {
        .prv_offset = 0x800,
        .save_ctx = true,
        .shared_clock = &i2c_clock,
+       .setup = lpss_i2c_setup,
 };
 
 #else
index e48fc98e71c48379694bbbd76119dd1c222660ac..0d7116f34b95aa32f0e2ef044205cdf28df107fe 100644 (file)
@@ -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_DESCRIPTION("ACPI Battery Driver");
 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 @@ static ssize_t acpi_battery_write_alarm(struct file *file,
                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 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
        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 @@ static int battery_notify(struct notifier_block *nb,
        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 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
        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();
index 3f2bdc812d23b7c2b4175448793eb56c96af2b47..bad25b070fe0bfe8b0204cce2ddd5ce30f07ec91 100644 (file)
@@ -235,7 +235,8 @@ void acpi_os_vprintf(const char *fmt, va_list args)
 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);
index 05550ba44d32ba59dba6cea489dc622965cc9692..6d5a6cda0734de6a46a577a71225dd43163acc69 100644 (file)
@@ -360,7 +360,8 @@ static int __init acpi_parse_apic_instance(char *str)
        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);
 
index e473d6555f96de1666f725c2966373d2b7e21ce1..ffe350f86bca570e879177c63395efff5de6587d 100644 (file)
@@ -186,6 +186,8 @@ config CPU_FREQ_GOV_CONSERVATIVE
 config GENERIC_CPUFREQ_CPU0
        tristate "Generic CPU0 cpufreq driver"
        depends on HAVE_CLK && OF
+       # if CPU_THERMAL is on and THERMAL=m, CPU0 cannot be =y:
+       depends on !CPU_THERMAL || THERMAL
        select PM_OPP
        help
          This adds a generic cpufreq driver for CPU0 frequency management.
index aed2b0cb83dc109203368d85b8cc76178211053c..62259d27f03e6a012bb47f349cc681b9aa9f7e43 100644 (file)
@@ -2242,10 +2242,8 @@ int cpufreq_update_policy(unsigned int cpu)
        struct cpufreq_policy new_policy;
        int ret;
 
-       if (!policy) {
-               ret = -ENODEV;
-               goto no_policy;
-       }
+       if (!policy)
+               return -ENODEV;
 
        down_write(&policy->rwsem);
 
@@ -2264,7 +2262,7 @@ int cpufreq_update_policy(unsigned int cpu)
                new_policy.cur = cpufreq_driver->get(cpu);
                if (WARN_ON(!new_policy.cur)) {
                        ret = -EIO;
-                       goto no_policy;
+                       goto unlock;
                }
 
                if (!policy->cur) {
@@ -2279,10 +2277,10 @@ int cpufreq_update_policy(unsigned int cpu)
 
        ret = cpufreq_set_policy(policy, &new_policy);
 
+unlock:
        up_write(&policy->rwsem);
 
        cpufreq_cpu_put(policy);
-no_policy:
        return ret;
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
index 4e7f492ad5839d43ef02a092d1b8cd9fde735278..924bb2d42b1c8cd4121289f1569107ffa3a58a4b 100644 (file)
@@ -196,10 +196,7 @@ static signed int pid_calc(struct _pid *pid, int32_t busy)
        pid->last_err = fp_error;
 
        result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm;
-       if (result >= 0)
-               result = result + (1 << (FRAC_BITS-1));
-       else
-               result = result - (1 << (FRAC_BITS-1));
+       result = result + (1 << (FRAC_BITS-1));
        return (signed int)fp_toint(result);
 }
 
index 28587d0f3947dfd715f1c7c24d374c0cc35559cf..a5fba0287bfb4ed49e02d1f292312067e0b42251 100644 (file)
@@ -55,7 +55,7 @@ static struct cpuidle_driver armada_370_xp_idle_driver = {
                .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 @@ static struct cpuidle_driver armada_370_xp_idle_driver = {
                .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,
index 6eb1d3cb5104ce9e16d239a5b3dcfd4e8088148c..9b9b6f29bbf3aaa051e048ee7ab4f365a143f5aa 100644 (file)
@@ -53,7 +53,7 @@ struct acpi_power_register {
        u8 bit_offset;
        u8 access_size;
        u64 address;
-} __attribute__ ((packed));
+} __packed;
 
 struct acpi_processor_cx {
        u8 valid;
@@ -83,7 +83,7 @@ struct acpi_psd_package {
        u64 domain;
        u64 coord_type;
        u64 num_processors;
-} __attribute__ ((packed));
+} __packed;
 
 struct acpi_pct_register {
        u8 descriptor;
@@ -93,7 +93,7 @@ struct acpi_pct_register {
        u8 bit_offset;
        u8 reserved;
        u64 address;
-} __attribute__ ((packed));
+} __packed;
 
 struct acpi_processor_px {
        u64 core_frequency;     /* megahertz */
@@ -124,7 +124,7 @@ struct acpi_tsd_package {
        u64 domain;
        u64 coord_type;
        u64 num_processors;
-} __attribute__ ((packed));
+} __packed;
 
 struct acpi_ptc_register {
        u8 descriptor;
@@ -134,7 +134,7 @@ struct acpi_ptc_register {
        u8 bit_offset;
        u8 reserved;
        u64 address;
-} __attribute__ ((packed));
+} __packed;
 
 struct acpi_processor_tx_tss {
        u64 freqpercentage;     /* */
index f76994b9396ccaf7b575f0312900f9398a1665cd..519064e0c94302fd39ced27b6aab51b55f904f60 100644 (file)
@@ -327,6 +327,7 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);
 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 swsusp_unset_page_free(struct page *p) {}
 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 */
index 49e0a20fd01043eb3cf21b5394758571e0b4e7aa..fcc2611d3f145da1dcb32aa4814a2fa3b6fd6404 100644 (file)
@@ -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 @@ bool freezer_test_done;
 
 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 hibernate(void)
 {
        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 @@ static int software_resume(void)
        /*
         * If the user said "noresume".. bail out early.
         */
-       if (noresume)
+       if (noresume || !hibernation_available())
                return 0;
 
        /*
@@ -900,6 +911,9 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
        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 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
        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 @@ static int __init hibernate_setup(char *str)
                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 @@ static int __init resumedelay_setup(char *str)
        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);
index 573410d6647e2a374feca5f46146a5b0ab61cec7..8e90f330f1398277d1b41b0e94c99e71759e2665 100644 (file)
@@ -300,13 +300,11 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
                        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);
 }
 
index 98d357584cd6bad7bdc87cbc63e5c296a8393b60..526e8911460a0b550011b2aae89c1fe9ad11a2cf 100644 (file)
@@ -49,6 +49,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
        struct snapshot_data *data;
        int error;
 
+       if (!hibernation_available())
+               return -EPERM;
+
        lock_system_sleep();
 
        if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {