]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.34 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Fri, 30 Jul 2010 01:07:32 +0000 (18:07 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 30 Jul 2010 01:07:32 +0000 (18:07 -0700)
queue-2.6.34/acpi-store-nvs-state-even-when-entering-suspend-to-ram.patch [deleted file]
queue-2.6.34/drm-i915-add-panel_unlock_regs-definition.patch [new file with mode: 0644]
queue-2.6.34/drm-i915-make-sure-edp-panel-is-turned-on.patch [new file with mode: 0644]
queue-2.6.34/drm-i915-make-sure-we-shut-off-the-panel-in-edp-configs.patch [new file with mode: 0644]
queue-2.6.34/series
queue-2.6.34/suspend-move-nvs-save-restore-code-to-generic-suspend-functionality.patch [deleted file]

diff --git a/queue-2.6.34/acpi-store-nvs-state-even-when-entering-suspend-to-ram.patch b/queue-2.6.34/acpi-store-nvs-state-even-when-entering-suspend-to-ram.patch
deleted file mode 100644 (file)
index 26fd517..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-From 2a6b69765ad794389f2fc3e14a0afa1a995221c2 Mon Sep 17 00:00:00 2001
-From: Matthew Garrett <mjg@redhat.com>
-Date: Fri, 28 May 2010 16:32:15 -0400
-Subject: ACPI: Store NVS state even when entering suspend to RAM
-
-From: Matthew Garrett <mjg@redhat.com>
-
-commit 2a6b69765ad794389f2fc3e14a0afa1a995221c2 upstream.
-
-https://bugzilla.kernel.org/show_bug.cgi?id=13931 describes a bug where
-a system fails to successfully resume after the second suspend. Maxim
-Levitsky discovered that this could be rectified by forcibly saving
-and restoring the ACPI non-volatile state. The spec indicates that this
-is only required for S4, but testing the behaviour of Windows by adding
-an ACPI NVS region to qemu's e820 map and registering a custom memory
-read/write handler reveals that it's saved and restored even over suspend
-to RAM. We should mimic that behaviour to avoid other broken platforms.
-
-Signed-off-by: Matthew Garrett <mjg@redhat.com>
-Signed-off-by: Len Brown <len.brown@intel.com>
-Cc: Rafael Wysocki <rjw@sisk.pl>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- drivers/acpi/sleep.c |   21 +++++++++++++--------
- 1 file changed, 13 insertions(+), 8 deletions(-)
-
---- a/drivers/acpi/sleep.c
-+++ b/drivers/acpi/sleep.c
-@@ -112,6 +112,8 @@ static int __acpi_pm_prepare(void)
- {
-       int error = acpi_sleep_prepare(acpi_target_sleep_state);
-+      suspend_nvs_save();
-+
-       if (error)
-               acpi_target_sleep_state = ACPI_STATE_S0;
-       return error;
-@@ -140,6 +142,8 @@ static void acpi_pm_finish(void)
- {
-       u32 acpi_state = acpi_target_sleep_state;
-+      suspend_nvs_free();
-+
-       if (acpi_state == ACPI_STATE_S0)
-               return;
-@@ -189,6 +193,11 @@ static int acpi_suspend_begin(suspend_st
-       u32 acpi_state = acpi_suspend_states[pm_state];
-       int error = 0;
-+      error = suspend_nvs_alloc();
-+
-+      if (error)
-+              return error;
-+
-       if (sleep_states[acpi_state]) {
-               acpi_target_sleep_state = acpi_state;
-               acpi_sleep_tts_switch(acpi_target_sleep_state);
-@@ -264,6 +273,8 @@ static int acpi_suspend_enter(suspend_st
-       if (acpi_state == ACPI_STATE_S3)
-               acpi_restore_state_mem();
-+      suspend_nvs_restore();
-+
-       return ACPI_SUCCESS(status) ? 0 : -EFAULT;
- }
-@@ -430,12 +441,6 @@ static int acpi_hibernation_enter(void)
-       return ACPI_SUCCESS(status) ? 0 : -EFAULT;
- }
--static void acpi_hibernation_finish(void)
--{
--      suspend_nvs_free();
--      acpi_pm_finish();
--}
--
- static void acpi_hibernation_leave(void)
- {
-       /*
-@@ -473,7 +478,7 @@ static struct platform_hibernation_ops a
-       .begin = acpi_hibernation_begin,
-       .end = acpi_pm_end,
-       .pre_snapshot = acpi_hibernation_pre_snapshot,
--      .finish = acpi_hibernation_finish,
-+      .finish = acpi_pm_finish,
-       .prepare = acpi_pm_prepare,
-       .enter = acpi_hibernation_enter,
-       .leave = acpi_hibernation_leave,
-@@ -526,7 +531,7 @@ static struct platform_hibernation_ops a
-       .begin = acpi_hibernation_begin_old,
-       .end = acpi_pm_end,
-       .pre_snapshot = acpi_hibernation_pre_snapshot_old,
--      .finish = acpi_hibernation_finish,
-+      .finish = acpi_pm_finish,
-       .prepare = acpi_pm_disable_gpes,
-       .enter = acpi_hibernation_enter,
-       .leave = acpi_hibernation_leave,
diff --git a/queue-2.6.34/drm-i915-add-panel_unlock_regs-definition.patch b/queue-2.6.34/drm-i915-add-panel_unlock_regs-definition.patch
new file mode 100644 (file)
index 0000000..fb43941
--- /dev/null
@@ -0,0 +1,53 @@
+From 4a655f043160eeae447efd3be297b6b4c397a640 Mon Sep 17 00:00:00 2001
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+Date: Thu, 22 Jul 2010 13:18:18 -0700
+Subject: drm/i915: add PANEL_UNLOCK_REGS definition
+
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+
+commit 4a655f043160eeae447efd3be297b6b4c397a640 upstream.
+
+In some cases, unlocking the panel regs is safe and can help us avoid a
+flickery, full mode set sequence.  So define the unlock key and use it.
+
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_reg.h      |    1 +
+ drivers/gpu/drm/i915/intel_display.c |    6 ++++--
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -2687,6 +2687,7 @@
+ #define PCH_PP_STATUS         0xc7200
+ #define PCH_PP_CONTROL                0xc7204
++#define  PANEL_UNLOCK_REGS    (0xabcd << 16)
+ #define  EDP_FORCE_VDD                (1 << 3)
+ #define  EDP_BLC_ENABLE               (1 << 2)
+ #define  PANEL_POWER_RESET    (1 << 1)
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -3950,7 +3950,8 @@ static void intel_increase_pllclock(stru
+               DRM_DEBUG_DRIVER("upclocking LVDS\n");
+               /* Unlock panel regs */
+-              I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
++              I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
++                         PANEL_UNLOCK_REGS);
+               dpll &= ~DISPLAY_RATE_SELECT_FPA1;
+               I915_WRITE(dpll_reg, dpll);
+@@ -3993,7 +3994,8 @@ static void intel_decrease_pllclock(stru
+               DRM_DEBUG_DRIVER("downclocking LVDS\n");
+               /* Unlock panel regs */
+-              I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
++              I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
++                         PANEL_UNLOCK_REGS);
+               dpll |= DISPLAY_RATE_SELECT_FPA1;
+               I915_WRITE(dpll_reg, dpll);
diff --git a/queue-2.6.34/drm-i915-make-sure-edp-panel-is-turned-on.patch b/queue-2.6.34/drm-i915-make-sure-edp-panel-is-turned-on.patch
new file mode 100644 (file)
index 0000000..eaf5369
--- /dev/null
@@ -0,0 +1,103 @@
+From 9934c132989d5c488d2e15188220ce240960ce96 Mon Sep 17 00:00:00 2001
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+Date: Thu, 22 Jul 2010 13:18:19 -0700
+Subject: drm/i915: make sure eDP panel is turned on
+
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+
+commit 9934c132989d5c488d2e15188220ce240960ce96 upstream.
+
+When enabling the eDP port, we need to make sure the panel is turned on
+after training the link.  If we don't, it likely won't come back after
+suspend or may not come up at all.
+
+For unknown reasons, unlocking the panel regs before initiating a power
+on sequence is necessary.  There are known bugs in the PCH panel
+sequencing logic, apparently this is one possible workaround.
+
+Fixes https://bugs.freedesktop.org/show_bug.cgi?id=28739.
+
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Tested-by: "Paulo J. S. Silva" <pjssilva@gmail.com>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_dp.c |   53 ++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 51 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_dp.c
++++ b/drivers/gpu/drm/i915/intel_dp.c
+@@ -677,6 +677,51 @@ intel_dp_mode_set(struct drm_encoder *en
+       }
+ }
++static void ironlake_edp_panel_on (struct drm_device *dev)
++{
++      struct drm_i915_private *dev_priv = dev->dev_private;
++      unsigned long timeout = jiffies + msecs_to_jiffies(5000);
++      u32 pp, pp_status;
++
++      pp_status = I915_READ(PCH_PP_STATUS);
++      if (pp_status & PP_ON)
++              return;
++
++      pp = I915_READ(PCH_PP_CONTROL);
++      pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
++      I915_WRITE(PCH_PP_CONTROL, pp);
++      do {
++              pp_status = I915_READ(PCH_PP_STATUS);
++      } while (((pp_status & PP_ON) == 0) && !time_after(jiffies, timeout));
++
++      if (time_after(jiffies, timeout))
++              DRM_DEBUG_KMS("panel on wait timed out: 0x%08x\n", pp_status);
++
++      pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD);
++      I915_WRITE(PCH_PP_CONTROL, pp);
++}
++
++static void ironlake_edp_panel_off (struct drm_device *dev)
++{
++      struct drm_i915_private *dev_priv = dev->dev_private;
++      unsigned long timeout = jiffies + msecs_to_jiffies(5000);
++      u32 pp, pp_status;
++
++      pp = I915_READ(PCH_PP_CONTROL);
++      pp &= ~POWER_TARGET_ON;
++      I915_WRITE(PCH_PP_CONTROL, pp);
++      do {
++              pp_status = I915_READ(PCH_PP_STATUS);
++      } while ((pp_status & PP_ON) && !time_after(jiffies, timeout));
++
++      if (time_after(jiffies, timeout))
++              DRM_DEBUG_KMS("panel off wait timed out\n");
++
++      /* Make sure VDD is enabled so DP AUX will work */
++      pp |= EDP_FORCE_VDD;
++      I915_WRITE(PCH_PP_CONTROL, pp);
++}
++
+ static void ironlake_edp_backlight_on (struct drm_device *dev)
+ {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+@@ -711,14 +756,18 @@ intel_dp_dpms(struct drm_encoder *encode
+       if (mode != DRM_MODE_DPMS_ON) {
+               if (dp_reg & DP_PORT_EN) {
+                       intel_dp_link_down(intel_encoder, dp_priv->DP);
+-                      if (IS_eDP(intel_encoder))
++                      if (IS_eDP(intel_encoder)) {
++                              ironlake_edp_backlight_off(dev);
+                               ironlake_edp_backlight_off(dev);
++                      }
+               }
+       } else {
+               if (!(dp_reg & DP_PORT_EN)) {
+                       intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
+-                      if (IS_eDP(intel_encoder))
++                      if (IS_eDP(intel_encoder)) {
++                              ironlake_edp_panel_on(dev);
+                               ironlake_edp_backlight_on(dev);
++                      }
+               }
+       }
+       dp_priv->dpms_mode = mode;
diff --git a/queue-2.6.34/drm-i915-make-sure-we-shut-off-the-panel-in-edp-configs.patch b/queue-2.6.34/drm-i915-make-sure-we-shut-off-the-panel-in-edp-configs.patch
new file mode 100644 (file)
index 0000000..73d2df1
--- /dev/null
@@ -0,0 +1,31 @@
+From 5620ae29f1eabe655f44335231b580a78c8364ea Mon Sep 17 00:00:00 2001
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+Date: Mon, 26 Jul 2010 13:51:22 -0700
+Subject: drm/i915: make sure we shut off the panel in eDP configs
+
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+
+commit 5620ae29f1eabe655f44335231b580a78c8364ea upstream.
+
+Fix error from the last pull request.  Making sure we shut the panel off
+is more correct and saves power.
+
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/intel_dp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/intel_dp.c
++++ b/drivers/gpu/drm/i915/intel_dp.c
+@@ -758,7 +758,7 @@ intel_dp_dpms(struct drm_encoder *encode
+                       intel_dp_link_down(intel_encoder, dp_priv->DP);
+                       if (IS_eDP(intel_encoder)) {
+                               ironlake_edp_backlight_off(dev);
+-                              ironlake_edp_backlight_off(dev);
++                              ironlake_edp_panel_off(dev);
+                       }
+               }
+       } else {
index 2d01f239b3ff9be7944faadaabc5b273770262d1..b3432814e9e7fcdcb2ac4ddfc6a06c31a9e2e9f7 100644 (file)
@@ -184,8 +184,6 @@ block-don-t-count_vm_events-for-discard-bio-in-submit_bio.patch
 iwlagn-verify-flow-id-in-compressed-ba-packet.patch
 iwlwifi-recover-tx-flow-stall-due-to-stuck-queue.patch
 iwl3945-enable-stuck-queue-detection-on-3945.patch
-suspend-move-nvs-save-restore-code-to-generic-suspend-functionality.patch
-acpi-store-nvs-state-even-when-entering-suspend-to-ram.patch
 kbuild-fix-modpost-segfault.patch
 acpi-acpica-use-helper-function-for-computing-gpe-masks.patch
 acpi-acpica-fix-low-level-gpe-manipulation-code.patch
@@ -202,3 +200,6 @@ input-rx51-keymap-fix-recent-compile-breakage.patch
 ocfs2-make-xattr-extension-work-with-new-local-alloc-reservation.patch
 acpi-processor-fix-processor_physically_present-on-up.patch
 alsa-hda-fix-pin-detection-of-nvidia-hdmi.patch
+drm-i915-add-panel_unlock_regs-definition.patch
+drm-i915-make-sure-edp-panel-is-turned-on.patch
+drm-i915-make-sure-we-shut-off-the-panel-in-edp-configs.patch
diff --git a/queue-2.6.34/suspend-move-nvs-save-restore-code-to-generic-suspend-functionality.patch b/queue-2.6.34/suspend-move-nvs-save-restore-code-to-generic-suspend-functionality.patch
deleted file mode 100644 (file)
index 49fd273..0000000
+++ /dev/null
@@ -1,468 +0,0 @@
-From dd4c4f17d722ffeb2515bf781400675a30fcead7 Mon Sep 17 00:00:00 2001
-From: Matthew Garrett <mjg@redhat.com>
-Date: Fri, 28 May 2010 16:32:14 -0400
-Subject: suspend: Move NVS save/restore code to generic suspend functionality
-
-From: Matthew Garrett <mjg@redhat.com>
-
-commit dd4c4f17d722ffeb2515bf781400675a30fcead7 upstream.
-
-Saving platform non-volatile state may be required for suspend to RAM as
-well as hibernation. Move it to more generic code.
-
-Signed-off-by: Matthew Garrett <mjg@redhat.com>
-Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
-Tested-by: Maxim Levitsky <maximlevitsky@gmail.com>
-Signed-off-by: Len Brown <len.brown@intel.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- arch/x86/kernel/e820.c       |    2 
- drivers/acpi/sleep.c         |   12 +--
- include/linux/suspend.h      |   26 ++++----
- kernel/power/Kconfig         |    9 +-
- kernel/power/Makefile        |    2 
- kernel/power/hibernate_nvs.c |  136 -------------------------------------------
- kernel/power/nvs.c           |  136 +++++++++++++++++++++++++++++++++++++++++++
- kernel/power/suspend.c       |    6 +
- 8 files changed, 168 insertions(+), 161 deletions(-)
-
---- a/arch/x86/kernel/e820.c
-+++ b/arch/x86/kernel/e820.c
-@@ -729,7 +729,7 @@ static int __init e820_mark_nvs_memory(v
-               struct e820entry *ei = &e820.map[i];
-               if (ei->type == E820_NVS)
--                      hibernate_nvs_register(ei->addr, ei->size);
-+                      suspend_nvs_register(ei->addr, ei->size);
-       }
-       return 0;
---- a/drivers/acpi/sleep.c
-+++ b/drivers/acpi/sleep.c
-@@ -393,7 +393,7 @@ static int acpi_hibernation_begin(void)
- {
-       int error;
--      error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
-+      error = s4_no_nvs ? 0 : suspend_nvs_alloc();
-       if (!error) {
-               acpi_target_sleep_state = ACPI_STATE_S4;
-               acpi_sleep_tts_switch(acpi_target_sleep_state);
-@@ -407,7 +407,7 @@ static int acpi_hibernation_pre_snapshot
-       int error = acpi_pm_prepare();
-       if (!error)
--              hibernate_nvs_save();
-+              suspend_nvs_save();
-       return error;
- }
-@@ -432,7 +432,7 @@ static int acpi_hibernation_enter(void)
- static void acpi_hibernation_finish(void)
- {
--      hibernate_nvs_free();
-+      suspend_nvs_free();
-       acpi_pm_finish();
- }
-@@ -452,7 +452,7 @@ static void acpi_hibernation_leave(void)
-               panic("ACPI S4 hardware signature mismatch");
-       }
-       /* Restore the NVS memory area */
--      hibernate_nvs_restore();
-+      suspend_nvs_restore();
- }
- static int acpi_pm_pre_restore(void)
-@@ -501,7 +501,7 @@ static int acpi_hibernation_begin_old(vo
-       if (!error) {
-               if (!s4_no_nvs)
--                      error = hibernate_nvs_alloc();
-+                      error = suspend_nvs_alloc();
-               if (!error)
-                       acpi_target_sleep_state = ACPI_STATE_S4;
-       }
-@@ -513,7 +513,7 @@ static int acpi_hibernation_pre_snapshot
-       int error = acpi_pm_disable_gpes();
-       if (!error)
--              hibernate_nvs_save();
-+              suspend_nvs_save();
-       return error;
- }
---- a/include/linux/suspend.h
-+++ b/include/linux/suspend.h
-@@ -256,22 +256,22 @@ static inline int hibernate(void) { retu
- static inline bool system_entering_hibernation(void) { return false; }
- #endif /* CONFIG_HIBERNATION */
--#ifdef CONFIG_HIBERNATION_NVS
--extern int hibernate_nvs_register(unsigned long start, unsigned long size);
--extern int hibernate_nvs_alloc(void);
--extern void hibernate_nvs_free(void);
--extern void hibernate_nvs_save(void);
--extern void hibernate_nvs_restore(void);
--#else /* CONFIG_HIBERNATION_NVS */
--static inline int hibernate_nvs_register(unsigned long a, unsigned long b)
-+#ifdef CONFIG_SUSPEND_NVS
-+extern int suspend_nvs_register(unsigned long start, unsigned long size);
-+extern int suspend_nvs_alloc(void);
-+extern void suspend_nvs_free(void);
-+extern void suspend_nvs_save(void);
-+extern void suspend_nvs_restore(void);
-+#else /* CONFIG_SUSPEND_NVS */
-+static inline int suspend_nvs_register(unsigned long a, unsigned long b)
- {
-       return 0;
- }
--static inline int hibernate_nvs_alloc(void) { return 0; }
--static inline void hibernate_nvs_free(void) {}
--static inline void hibernate_nvs_save(void) {}
--static inline void hibernate_nvs_restore(void) {}
--#endif /* CONFIG_HIBERNATION_NVS */
-+static inline int suspend_nvs_alloc(void) { return 0; }
-+static inline void suspend_nvs_free(void) {}
-+static inline void suspend_nvs_save(void) {}
-+static inline void suspend_nvs_restore(void) {}
-+#endif /* CONFIG_SUSPEND_NVS */
- #ifdef CONFIG_PM_SLEEP
- void save_processor_state(void);
---- a/kernel/power/Kconfig
-+++ b/kernel/power/Kconfig
-@@ -99,9 +99,13 @@ config PM_SLEEP_ADVANCED_DEBUG
-       depends on PM_ADVANCED_DEBUG
-       default n
-+config SUSPEND_NVS
-+       bool
-+
- config SUSPEND
-       bool "Suspend to RAM and standby"
-       depends on PM && ARCH_SUSPEND_POSSIBLE
-+      select SUSPEND_NVS if HAS_IOMEM
-       default y
-       ---help---
-         Allow the system to enter sleep states in which main memory is
-@@ -130,13 +134,10 @@ config SUSPEND_FREEZER
-         Turning OFF this setting is NOT recommended! If in doubt, say Y.
--config HIBERNATION_NVS
--      bool
--
- config HIBERNATION
-       bool "Hibernation (aka 'suspend to disk')"
-       depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
--      select HIBERNATION_NVS if HAS_IOMEM
-+      select SUSPEND_NVS if HAS_IOMEM
-       ---help---
-         Enable the suspend to disk (STD) functionality, which is usually
-         called "hibernation" in user interfaces.  STD checkpoints the
---- a/kernel/power/Makefile
-+++ b/kernel/power/Makefile
-@@ -9,6 +9,6 @@ obj-$(CONFIG_FREEZER)          += process.o
- obj-$(CONFIG_SUSPEND)         += suspend.o
- obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o
- obj-$(CONFIG_HIBERNATION)     += hibernate.o snapshot.o swap.o user.o
--obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o
-+obj-$(CONFIG_SUSPEND_NVS)     += nvs.o
- obj-$(CONFIG_MAGIC_SYSRQ)     += poweroff.o
---- a/kernel/power/hibernate_nvs.c
-+++ /dev/null
-@@ -1,136 +0,0 @@
--/*
-- * linux/kernel/power/hibernate_nvs.c - Routines for handling NVS memory
-- *
-- * Copyright (C) 2008,2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
-- *
-- * This file is released under the GPLv2.
-- */
--
--#include <linux/io.h>
--#include <linux/kernel.h>
--#include <linux/list.h>
--#include <linux/mm.h>
--#include <linux/slab.h>
--#include <linux/suspend.h>
--
--/*
-- * Platforms, like ACPI, may want us to save some memory used by them during
-- * hibernation and to restore the contents of this memory during the subsequent
-- * resume.  The code below implements a mechanism allowing us to do that.
-- */
--
--struct nvs_page {
--      unsigned long phys_start;
--      unsigned int size;
--      void *kaddr;
--      void *data;
--      struct list_head node;
--};
--
--static LIST_HEAD(nvs_list);
--
--/**
-- *    hibernate_nvs_register - register platform NVS memory region to save
-- *    @start - physical address of the region
-- *    @size - size of the region
-- *
-- *    The NVS region need not be page-aligned (both ends) and we arrange
-- *    things so that the data from page-aligned addresses in this region will
-- *    be copied into separate RAM pages.
-- */
--int hibernate_nvs_register(unsigned long start, unsigned long size)
--{
--      struct nvs_page *entry, *next;
--
--      while (size > 0) {
--              unsigned int nr_bytes;
--
--              entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
--              if (!entry)
--                      goto Error;
--
--              list_add_tail(&entry->node, &nvs_list);
--              entry->phys_start = start;
--              nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
--              entry->size = (size < nr_bytes) ? size : nr_bytes;
--
--              start += entry->size;
--              size -= entry->size;
--      }
--      return 0;
--
-- Error:
--      list_for_each_entry_safe(entry, next, &nvs_list, node) {
--              list_del(&entry->node);
--              kfree(entry);
--      }
--      return -ENOMEM;
--}
--
--/**
-- *    hibernate_nvs_free - free data pages allocated for saving NVS regions
-- */
--void hibernate_nvs_free(void)
--{
--      struct nvs_page *entry;
--
--      list_for_each_entry(entry, &nvs_list, node)
--              if (entry->data) {
--                      free_page((unsigned long)entry->data);
--                      entry->data = NULL;
--                      if (entry->kaddr) {
--                              iounmap(entry->kaddr);
--                              entry->kaddr = NULL;
--                      }
--              }
--}
--
--/**
-- *    hibernate_nvs_alloc - allocate memory necessary for saving NVS regions
-- */
--int hibernate_nvs_alloc(void)
--{
--      struct nvs_page *entry;
--
--      list_for_each_entry(entry, &nvs_list, node) {
--              entry->data = (void *)__get_free_page(GFP_KERNEL);
--              if (!entry->data) {
--                      hibernate_nvs_free();
--                      return -ENOMEM;
--              }
--      }
--      return 0;
--}
--
--/**
-- *    hibernate_nvs_save - save NVS memory regions
-- */
--void hibernate_nvs_save(void)
--{
--      struct nvs_page *entry;
--
--      printk(KERN_INFO "PM: Saving platform NVS memory\n");
--
--      list_for_each_entry(entry, &nvs_list, node)
--              if (entry->data) {
--                      entry->kaddr = ioremap(entry->phys_start, entry->size);
--                      memcpy(entry->data, entry->kaddr, entry->size);
--              }
--}
--
--/**
-- *    hibernate_nvs_restore - restore NVS memory regions
-- *
-- *    This function is going to be called with interrupts disabled, so it
-- *    cannot iounmap the virtual addresses used to access the NVS region.
-- */
--void hibernate_nvs_restore(void)
--{
--      struct nvs_page *entry;
--
--      printk(KERN_INFO "PM: Restoring platform NVS memory\n");
--
--      list_for_each_entry(entry, &nvs_list, node)
--              if (entry->data)
--                      memcpy(entry->kaddr, entry->data, entry->size);
--}
---- /dev/null
-+++ b/kernel/power/nvs.c
-@@ -0,0 +1,136 @@
-+/*
-+ * linux/kernel/power/hibernate_nvs.c - Routines for handling NVS memory
-+ *
-+ * Copyright (C) 2008,2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
-+ *
-+ * This file is released under the GPLv2.
-+ */
-+
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/suspend.h>
-+
-+/*
-+ * Platforms, like ACPI, may want us to save some memory used by them during
-+ * suspend and to restore the contents of this memory during the subsequent
-+ * resume.  The code below implements a mechanism allowing us to do that.
-+ */
-+
-+struct nvs_page {
-+      unsigned long phys_start;
-+      unsigned int size;
-+      void *kaddr;
-+      void *data;
-+      struct list_head node;
-+};
-+
-+static LIST_HEAD(nvs_list);
-+
-+/**
-+ *    suspend_nvs_register - register platform NVS memory region to save
-+ *    @start - physical address of the region
-+ *    @size - size of the region
-+ *
-+ *    The NVS region need not be page-aligned (both ends) and we arrange
-+ *    things so that the data from page-aligned addresses in this region will
-+ *    be copied into separate RAM pages.
-+ */
-+int suspend_nvs_register(unsigned long start, unsigned long size)
-+{
-+      struct nvs_page *entry, *next;
-+
-+      while (size > 0) {
-+              unsigned int nr_bytes;
-+
-+              entry = kzalloc(sizeof(struct nvs_page), GFP_KERNEL);
-+              if (!entry)
-+                      goto Error;
-+
-+              list_add_tail(&entry->node, &nvs_list);
-+              entry->phys_start = start;
-+              nr_bytes = PAGE_SIZE - (start & ~PAGE_MASK);
-+              entry->size = (size < nr_bytes) ? size : nr_bytes;
-+
-+              start += entry->size;
-+              size -= entry->size;
-+      }
-+      return 0;
-+
-+ Error:
-+      list_for_each_entry_safe(entry, next, &nvs_list, node) {
-+              list_del(&entry->node);
-+              kfree(entry);
-+      }
-+      return -ENOMEM;
-+}
-+
-+/**
-+ *    suspend_nvs_free - free data pages allocated for saving NVS regions
-+ */
-+void suspend_nvs_free(void)
-+{
-+      struct nvs_page *entry;
-+
-+      list_for_each_entry(entry, &nvs_list, node)
-+              if (entry->data) {
-+                      free_page((unsigned long)entry->data);
-+                      entry->data = NULL;
-+                      if (entry->kaddr) {
-+                              iounmap(entry->kaddr);
-+                              entry->kaddr = NULL;
-+                      }
-+              }
-+}
-+
-+/**
-+ *    suspend_nvs_alloc - allocate memory necessary for saving NVS regions
-+ */
-+int suspend_nvs_alloc(void)
-+{
-+      struct nvs_page *entry;
-+
-+      list_for_each_entry(entry, &nvs_list, node) {
-+              entry->data = (void *)__get_free_page(GFP_KERNEL);
-+              if (!entry->data) {
-+                      suspend_nvs_free();
-+                      return -ENOMEM;
-+              }
-+      }
-+      return 0;
-+}
-+
-+/**
-+ *    suspend_nvs_save - save NVS memory regions
-+ */
-+void suspend_nvs_save(void)
-+{
-+      struct nvs_page *entry;
-+
-+      printk(KERN_INFO "PM: Saving platform NVS memory\n");
-+
-+      list_for_each_entry(entry, &nvs_list, node)
-+              if (entry->data) {
-+                      entry->kaddr = ioremap(entry->phys_start, entry->size);
-+                      memcpy(entry->data, entry->kaddr, entry->size);
-+              }
-+}
-+
-+/**
-+ *    suspend_nvs_restore - restore NVS memory regions
-+ *
-+ *    This function is going to be called with interrupts disabled, so it
-+ *    cannot iounmap the virtual addresses used to access the NVS region.
-+ */
-+void suspend_nvs_restore(void)
-+{
-+      struct nvs_page *entry;
-+
-+      printk(KERN_INFO "PM: Restoring platform NVS memory\n");
-+
-+      list_for_each_entry(entry, &nvs_list, node)
-+              if (entry->data)
-+                      memcpy(entry->kaddr, entry->data, entry->size);
-+}
---- a/kernel/power/suspend.c
-+++ b/kernel/power/suspend.c
-@@ -16,6 +16,12 @@
- #include <linux/cpu.h>
- #include <linux/syscalls.h>
- #include <linux/gfp.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/suspend.h>
- #include "power.h"