]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.27 pci resume patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Thu, 15 Jan 2009 21:04:22 +0000 (13:04 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 15 Jan 2009 21:04:22 +0000 (13:04 -0800)
queue-2.6.27/pci-handle-pci-state-saving-with-interrupts-disabled.patch [new file with mode: 0644]
queue-2.6.27/pci-pm-split-pci-express-port-suspend-resume.patch [new file with mode: 0644]
queue-2.6.27/pci-rework-default-handling-of-suspend-and-resume.patch [new file with mode: 0644]
queue-2.6.27/pci-suspend-and-resume-pci-express-ports-with-interrupts-disabled.patch [new file with mode: 0644]
queue-2.6.27/series

diff --git a/queue-2.6.27/pci-handle-pci-state-saving-with-interrupts-disabled.patch b/queue-2.6.27/pci-handle-pci-state-saving-with-interrupts-disabled.patch
new file mode 100644 (file)
index 0000000..6a0a6b6
--- /dev/null
@@ -0,0 +1,170 @@
+From rjw@sisk.pl  Thu Jan 15 12:58:36 2009
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+Date: Wed, 14 Jan 2009 00:39:19 +0100
+Subject: PCI: handle PCI state saving with interrupts disabled
+To: stable@kernel.org
+Cc: Pavel Machek <pavel@suse.cz>, Greg KH <gregkh@suse.de>, Jesse Barnes <jbarnes@virtuousgeek.org>
+Message-ID: <200901140039.19568.rjw@sisk.pl>
+Content-Disposition: inline
+
+From: Rafael J. Wysocki <rjw@sisk.pl>
+
+commit 63f4898ace2788a89ed685672aab092e1c3e50e6 upstream.
+
+Since interrupts will soon be disabled at PCI resume time, we need to
+pre-allocate memory to save/restore PCI config space (or use GFP_ATOMIC,
+but this is safer).
+
+Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: "Rafael J. Wysocki" <rjw@sisk.pl>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/pci.c   |   72 ++++++++++++++++++++++++++++++++++++----------------
+ drivers/pci/pci.h   |    1 
+ drivers/pci/probe.c |    3 ++
+ 3 files changed, 54 insertions(+), 22 deletions(-)
+
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -636,19 +636,14 @@ static int pci_save_pcie_state(struct pc
+       int pos, i = 0;
+       struct pci_cap_saved_state *save_state;
+       u16 *cap;
+-      int found = 0;
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (pos <= 0)
+               return 0;
+       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+-      if (!save_state)
+-              save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+-      else
+-              found = 1;
+       if (!save_state) {
+-              dev_err(&dev->dev, "out of memory in pci_save_pcie_state\n");
++              dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__);
+               return -ENOMEM;
+       }
+       cap = (u16 *)&save_state->data[0];
+@@ -657,9 +652,7 @@ static int pci_save_pcie_state(struct pc
+       pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
+       pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
+       pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
+-      save_state->cap_nr = PCI_CAP_ID_EXP;
+-      if (!found)
+-              pci_add_saved_cap(dev, save_state);
++
+       return 0;
+ }
+@@ -684,30 +677,21 @@ static void pci_restore_pcie_state(struc
+ static int pci_save_pcix_state(struct pci_dev *dev)
+ {
+-      int pos, i = 0;
++      int pos;
+       struct pci_cap_saved_state *save_state;
+-      u16 *cap;
+-      int found = 0;
+       pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+       if (pos <= 0)
+               return 0;
+       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
+-      if (!save_state)
+-              save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+-      else
+-              found = 1;
+       if (!save_state) {
+-              dev_err(&dev->dev, "out of memory in pci_save_pcie_state\n");
++              dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__);
+               return -ENOMEM;
+       }
+-      cap = (u16 *)&save_state->data[0];
+-      pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
+-      save_state->cap_nr = PCI_CAP_ID_PCIX;
+-      if (!found)
+-              pci_add_saved_cap(dev, save_state);
++      pci_read_config_word(dev, pos + PCI_X_CMD, (u16 *)save_state->data);
++
+       return 0;
+ }
+@@ -726,6 +710,50 @@ static void pci_restore_pcix_state(struc
+       pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
+ }
++ /**
++ * pci_add_save_buffer - allocate buffer for saving given capability registers
++ * @dev: the PCI device
++ * @cap: the capability to allocate the buffer for
++ * @size: requested size of the buffer
++ */
++static int pci_add_cap_save_buffer(
++      struct pci_dev *dev, char cap, unsigned int size)
++{
++      int pos;
++      struct pci_cap_saved_state *save_state;
++
++      pos = pci_find_capability(dev, cap);
++      if (pos <= 0)
++              return 0;
++
++      save_state = kzalloc(sizeof(*save_state) + size, GFP_KERNEL);
++      if (!save_state)
++              return -ENOMEM;
++
++      save_state->cap_nr = cap;
++      pci_add_saved_cap(dev, save_state);
++
++      return 0;
++}
++
++/**
++ * pci_allocate_cap_save_buffers - allocate buffers for saving capabilities
++ * @dev: the PCI device
++ */
++void pci_allocate_cap_save_buffers(struct pci_dev *dev)
++{
++      int error;
++
++      error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP, 4 * sizeof(u16));
++      if (error)
++              dev_err(&dev->dev,
++                      "unable to preallocate PCI Express save buffer\n");
++
++      error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_PCIX, sizeof(u16));
++      if (error)
++              dev_err(&dev->dev,
++                      "unable to preallocate PCI-X save buffer\n");
++}
+ /**
+  * pci_save_state - save the PCI configuration space of a device before suspending
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -35,6 +35,7 @@ struct pci_platform_pm_ops {
+ extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
+ extern void pci_pm_init(struct pci_dev *dev);
++extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
+ extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
+ extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -1028,6 +1028,9 @@ void pci_device_add(struct pci_dev *dev,
+       /* Fix up broken headers */
+       pci_fixup_device(pci_fixup_header, dev);
++      /* Buffers for saving PCIe and PCI-X capabilities */
++      pci_allocate_cap_save_buffers(dev);
++
+       /* Initialize power management of the device */
+       pci_pm_init(dev);
diff --git a/queue-2.6.27/pci-pm-split-pci-express-port-suspend-resume.patch b/queue-2.6.27/pci-pm-split-pci-express-port-suspend-resume.patch
new file mode 100644 (file)
index 0000000..095fe6e
--- /dev/null
@@ -0,0 +1,95 @@
+From rjw@sisk.pl  Thu Jan 15 12:58:53 2009
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+Date: Wed, 14 Jan 2009 00:40:38 +0100
+Subject: PCI PM: Split PCI Express port suspend-resume
+To: stable@kernel.org
+Cc: Pavel Machek <pavel@suse.cz>, Greg KH <gregkh@suse.de>, Jesse Barnes <jbarnes@virtuousgeek.org>
+Message-ID: <200901140040.39247.rjw@sisk.pl>
+Content-Disposition: inline
+
+From: Rafael J. Wysocki <rjw@sisk.pl>
+
+commit a79d682f789730dfabaebbb507c87a90c0671a62 upstream
+
+Suspend-resume of PCI Express ports has recently been moved into
+_suspend_late() and _resume_early() callbacks, but some functions
+executed from there should not be called with interrupts disabled,
+eg. pci_enable_device().  For this reason, split the suspend-resume
+of PCI Express ports into parts to be executed with interrupts
+disabled and with interrupts enabled.
+
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/pcie/portdrv_pci.c |   23 +++++++++++++++++------
+ 1 file changed, 17 insertions(+), 6 deletions(-)
+
+--- a/drivers/pci/pcie/portdrv_pci.c
++++ b/drivers/pci/pcie/portdrv_pci.c
+@@ -41,7 +41,6 @@ static int pcie_portdrv_restore_config(s
+ {
+       int retval;
+-      pci_restore_state(dev);
+       retval = pci_enable_device(dev);
+       if (retval)
+               return retval;
+@@ -50,23 +49,32 @@ static int pcie_portdrv_restore_config(s
+ }
+ #ifdef CONFIG_PM
+-static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
++static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
+ {
+-      int ret = pcie_port_device_suspend(dev, state);
++      return pcie_port_device_suspend(dev, state);
++
++}
+-      if (!ret)
+-              ret = pcie_portdrv_save_config(dev);
+-      return ret;
++static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
++{
++      return pci_save_state(dev);
+ }
+ static int pcie_portdrv_resume_early(struct pci_dev *dev)
+ {
++      return pci_restore_state(dev);
++}
++
++static int pcie_portdrv_resume(struct pci_dev *dev)
++{
+       pcie_portdrv_restore_config(dev);
+       return pcie_port_device_resume(dev);
+ }
+ #else
++#define pcie_portdrv_suspend NULL
+ #define pcie_portdrv_suspend_late NULL
+ #define pcie_portdrv_resume_early NULL
++#define pcie_portdrv_resume NULL
+ #endif
+ /*
+@@ -221,6 +229,7 @@ static pci_ers_result_t pcie_portdrv_slo
+       /* If fatal, restore cfg space for possible link reset at upstream */
+       if (dev->error_state == pci_channel_io_frozen) {
++              pci_restore_state(dev);
+               pcie_portdrv_restore_config(dev);
+               pci_enable_pcie_error_reporting(dev);
+       }
+@@ -282,8 +291,10 @@ static struct pci_driver pcie_portdriver
+       .probe          = pcie_portdrv_probe,
+       .remove         = pcie_portdrv_remove,
++      .suspend        = pcie_portdrv_suspend,
+       .suspend_late   = pcie_portdrv_suspend_late,
+       .resume_early   = pcie_portdrv_resume_early,
++      .resume         = pcie_portdrv_resume,
+       .err_handler    = &pcie_portdrv_err_handler,
+ };
diff --git a/queue-2.6.27/pci-rework-default-handling-of-suspend-and-resume.patch b/queue-2.6.27/pci-rework-default-handling-of-suspend-and-resume.patch
new file mode 100644 (file)
index 0000000..325774c
--- /dev/null
@@ -0,0 +1,268 @@
+From rjw@sisk.pl  Thu Jan 15 12:55:26 2009
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+Date: Wed, 14 Jan 2009 00:38:13 +0100
+Subject: PCI: Rework default handling of suspend and resume
+To: stable@kernel.org
+Cc: Pavel Machek <pavel@suse.cz>, Greg KH <gregkh@suse.de>, Jesse Barnes <jbarnes@virtuousgeek.org>
+Message-ID: <200901140038.13695.rjw@sisk.pl>
+Content-Disposition: inline
+
+From: Rafael J. Wysocki <rjw@sisk.pl>
+
+commit 355a72d75b3b4f4877db4c9070c798238028ecb5 upstream.
+
+Rework the handling of suspend and resume of PCI devices which have
+no drivers or the drivers of which do not provide any suspend-resume
+callbacks in such a way that their standard PCI configuration
+registers will be saved and restored with interrupts disabled.  This
+should prevent such devices, including PCI bridges, from being
+resumed too late to be able to function correctly during the resume
+of the other PCI devices that may depend on them.
+
+Also, to remove one possible source of future confusion, drop the
+default handling of suspend and resume for PCI devices with drivers
+providing the 'pm' object introduced by the new suspend-resume
+framework (there are no such PCI drivers at the moment).
+
+This patch addresses the regression from 2.6.26 tracked as
+http://bugzilla.kernel.org/show_bug.cgi?id=12121 .
+
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
+Cc: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/pci-driver.c |   90 ++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 59 insertions(+), 31 deletions(-)
+
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -287,6 +287,14 @@ static void pci_device_shutdown(struct d
+ #ifdef CONFIG_PM_SLEEP
++static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
++{
++      struct pci_driver *drv = pci_dev->driver;
++
++      return drv && (drv->suspend || drv->suspend_late || drv->resume
++              || drv->resume_early);
++}
++
+ /*
+  * Default "suspend" method for devices that have no driver provided suspend,
+  * or not even a driver at all.
+@@ -304,14 +312,22 @@ static void pci_default_pm_suspend(struc
+ /*
+  * Default "resume" method for devices that have no driver provided resume,
+- * or not even a driver at all.
++ * or not even a driver at all (first part).
+  */
+-static int pci_default_pm_resume(struct pci_dev *pci_dev)
++static void pci_default_pm_resume_early(struct pci_dev *pci_dev)
+ {
+-      int retval = 0;
+-
+       /* restore the PCI config space */
+       pci_restore_state(pci_dev);
++}
++
++/*
++ * Default "resume" method for devices that have no driver provided resume,
++ * or not even a driver at all (second part).
++ */
++static int pci_default_pm_resume_late(struct pci_dev *pci_dev)
++{
++      int retval;
++
+       /* if the device was enabled before suspend, reenable */
+       retval = pci_reenable_device(pci_dev);
+       /*
+@@ -358,10 +374,12 @@ static int pci_legacy_resume(struct devi
+       struct pci_dev * pci_dev = to_pci_dev(dev);
+       struct pci_driver * drv = pci_dev->driver;
+-      if (drv && drv->resume)
++      if (drv && drv->resume) {
+               error = drv->resume(pci_dev);
+-      else
+-              error = pci_default_pm_resume(pci_dev);
++      } else {
++              pci_default_pm_resume_early(pci_dev);
++              error = pci_default_pm_resume_late(pci_dev);
++      }
+       return error;
+ }
+@@ -407,10 +425,8 @@ static int pci_pm_suspend(struct device 
+               if (drv->pm->suspend) {
+                       error = drv->pm->suspend(dev);
+                       suspend_report_result(drv->pm->suspend, error);
+-              } else {
+-                      pci_default_pm_suspend(pci_dev);
+               }
+-      } else {
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               error = pci_legacy_suspend(dev, PMSG_SUSPEND);
+       }
+       pci_fixup_device(pci_fixup_suspend, pci_dev);
+@@ -429,8 +445,10 @@ static int pci_pm_suspend_noirq(struct d
+                       error = drv->pm->suspend_noirq(dev);
+                       suspend_report_result(drv->pm->suspend_noirq, error);
+               }
+-      } else {
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               error = pci_legacy_suspend_late(dev, PMSG_SUSPEND);
++      } else {
++              pci_default_pm_suspend(pci_dev);
+       }
+       return error;
+@@ -440,15 +458,17 @@ static int pci_pm_resume(struct device *
+ {
+       struct pci_dev *pci_dev = to_pci_dev(dev);
+       struct device_driver *drv = dev->driver;
+-      int error;
++      int error = 0;
+       pci_fixup_device(pci_fixup_resume, pci_dev);
+       if (drv && drv->pm) {
+-              error = drv->pm->resume ? drv->pm->resume(dev) :
+-                      pci_default_pm_resume(pci_dev);
+-      } else {
++              if (drv->pm->resume)
++                      error = drv->pm->resume(dev);
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               error = pci_legacy_resume(dev);
++      } else {
++              error = pci_default_pm_resume_late(pci_dev);
+       }
+       return error;
+@@ -465,8 +485,10 @@ static int pci_pm_resume_noirq(struct de
+       if (drv && drv->pm) {
+               if (drv->pm->resume_noirq)
+                       error = drv->pm->resume_noirq(dev);
+-      } else {
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               error = pci_legacy_resume_early(dev);
++      } else {
++              pci_default_pm_resume_early(pci_dev);
+       }
+       return error;
+@@ -493,10 +515,8 @@ static int pci_pm_freeze(struct device *
+               if (drv->pm->freeze) {
+                       error = drv->pm->freeze(dev);
+                       suspend_report_result(drv->pm->freeze, error);
+-              } else {
+-                      pci_default_pm_suspend(pci_dev);
+               }
+-      } else {
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               error = pci_legacy_suspend(dev, PMSG_FREEZE);
+               pci_fixup_device(pci_fixup_suspend, pci_dev);
+       }
+@@ -515,8 +535,10 @@ static int pci_pm_freeze_noirq(struct de
+                       error = drv->pm->freeze_noirq(dev);
+                       suspend_report_result(drv->pm->freeze_noirq, error);
+               }
+-      } else {
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               error = pci_legacy_suspend_late(dev, PMSG_FREEZE);
++      } else {
++              pci_default_pm_suspend(pci_dev);
+       }
+       return error;
+@@ -524,14 +546,15 @@ static int pci_pm_freeze_noirq(struct de
+ static int pci_pm_thaw(struct device *dev)
+ {
++      struct pci_dev *pci_dev = to_pci_dev(dev);
+       struct device_driver *drv = dev->driver;
+       int error = 0;
+       if (drv && drv->pm) {
+               if (drv->pm->thaw)
+                       error =  drv->pm->thaw(dev);
+-      } else {
+-              pci_fixup_device(pci_fixup_resume, to_pci_dev(dev));
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
++              pci_fixup_device(pci_fixup_resume, pci_dev);
+               error = pci_legacy_resume(dev);
+       }
+@@ -547,7 +570,7 @@ static int pci_pm_thaw_noirq(struct devi
+       if (drv && drv->pm) {
+               if (drv->pm->thaw_noirq)
+                       error = drv->pm->thaw_noirq(dev);
+-      } else {
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               pci_fixup_device(pci_fixup_resume_early, pci_dev);
+               error = pci_legacy_resume_early(dev);
+       }
+@@ -557,17 +580,18 @@ static int pci_pm_thaw_noirq(struct devi
+ static int pci_pm_poweroff(struct device *dev)
+ {
++      struct pci_dev *pci_dev = to_pci_dev(dev);
+       struct device_driver *drv = dev->driver;
+       int error = 0;
+-      pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev));
++      pci_fixup_device(pci_fixup_suspend, pci_dev);
+       if (drv && drv->pm) {
+               if (drv->pm->poweroff) {
+                       error = drv->pm->poweroff(dev);
+                       suspend_report_result(drv->pm->poweroff, error);
+               }
+-      } else {
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               error = pci_legacy_suspend(dev, PMSG_HIBERNATE);
+       }
+@@ -585,7 +609,7 @@ static int pci_pm_poweroff_noirq(struct 
+                       error = drv->pm->poweroff_noirq(dev);
+                       suspend_report_result(drv->pm->poweroff_noirq, error);
+               }
+-      } else {
++      } else if (pci_has_legacy_pm_support(to_pci_dev(dev))) {
+               error = pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
+       }
+@@ -596,13 +620,15 @@ static int pci_pm_restore(struct device 
+ {
+       struct pci_dev *pci_dev = to_pci_dev(dev);
+       struct device_driver *drv = dev->driver;
+-      int error;
++      int error = 0;
+       if (drv && drv->pm) {
+-              error = drv->pm->restore ? drv->pm->restore(dev) :
+-                      pci_default_pm_resume(pci_dev);
+-      } else {
++              if (drv->pm->restore)
++                      error = drv->pm->restore(dev);
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               error = pci_legacy_resume(dev);
++      } else {
++              error = pci_default_pm_resume_late(pci_dev);
+       }
+       pci_fixup_device(pci_fixup_resume, pci_dev);
+@@ -620,8 +646,10 @@ static int pci_pm_restore_noirq(struct d
+       if (drv && drv->pm) {
+               if (drv->pm->restore_noirq)
+                       error = drv->pm->restore_noirq(dev);
+-      } else {
++      } else if (pci_has_legacy_pm_support(pci_dev)) {
+               error = pci_legacy_resume_early(dev);
++      } else {
++              pci_default_pm_resume_early(pci_dev);
+       }
+       pci_fixup_device(pci_fixup_resume_early, pci_dev);
diff --git a/queue-2.6.27/pci-suspend-and-resume-pci-express-ports-with-interrupts-disabled.patch b/queue-2.6.27/pci-suspend-and-resume-pci-express-ports-with-interrupts-disabled.patch
new file mode 100644 (file)
index 0000000..4eed3d4
--- /dev/null
@@ -0,0 +1,71 @@
+From rjw@sisk.pl  Thu Jan 15 12:56:08 2009
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+Date: Wed, 14 Jan 2009 00:38:27 +0100
+Subject: PCI: Suspend and resume PCI Express ports with interrupts disabled
+To: stable@kernel.org
+Cc: Pavel Machek <pavel@suse.cz>, Greg KH <gregkh@suse.de>, Jesse Barnes <jbarnes@virtuousgeek.org>
+Message-ID: <200901140038.27587.rjw@sisk.pl>
+Content-Disposition: inline
+
+From: Rafael J. Wysocki <rjw@sisk.pl>
+
+commit 90d25f246ddefbb743764f8d45ae97e545a6ee86 upstream
+
+I don't see why the suspend and resume of PCI Express ports should be
+handled with interrupts enabled and it may even lead to problems in
+some situations.  For this reason, move the suspending and resuming
+of PCI Express ports into ->suspend_late() and ->resume_early()
+callbacks executed with interrupts disabled.
+
+This patch addresses the regression from 2.6.26 tracked as
+http://bugzilla.kernel.org/show_bug.cgi?id=12121 .
+
+Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/pcie/portdrv_pci.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/pci/pcie/portdrv_pci.c
++++ b/drivers/pci/pcie/portdrv_pci.c
+@@ -50,7 +50,7 @@ static int pcie_portdrv_restore_config(s
+ }
+ #ifdef CONFIG_PM
+-static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
++static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
+ {
+       int ret = pcie_port_device_suspend(dev, state);
+@@ -59,14 +59,14 @@ static int pcie_portdrv_suspend(struct p
+       return ret;
+ }
+-static int pcie_portdrv_resume(struct pci_dev *dev)
++static int pcie_portdrv_resume_early(struct pci_dev *dev)
+ {
+       pcie_portdrv_restore_config(dev);
+       return pcie_port_device_resume(dev);
+ }
+ #else
+-#define pcie_portdrv_suspend NULL
+-#define pcie_portdrv_resume NULL
++#define pcie_portdrv_suspend_late NULL
++#define pcie_portdrv_resume_early NULL
+ #endif
+ /*
+@@ -282,8 +282,8 @@ static struct pci_driver pcie_portdriver
+       .probe          = pcie_portdrv_probe,
+       .remove         = pcie_portdrv_remove,
+-      .suspend        = pcie_portdrv_suspend,
+-      .resume         = pcie_portdrv_resume,
++      .suspend_late   = pcie_portdrv_suspend_late,
++      .resume_early   = pcie_portdrv_resume_early,
+       .err_handler    = &pcie_portdrv_err_handler,
+ };
index df1f461f4724a42a1c2cbd44c4634c3dd47d579c..3ac4fa4326e2f80fa60f8ae5b88823d13cc69aab 100644 (file)
@@ -79,3 +79,7 @@ usb-storage-recognizing-and-enabling-nokia-5200-cell-phoes.patch
 x86-avoid-theoretical-vmalloc-fault-loop.patch
 x86-cpa-dont-use-large-pages-for-kernel-identity-mapping-with-debug_pagealloc.patch
 x86-fix-rip-printout-in-early_idt_handler.patch
+pci-rework-default-handling-of-suspend-and-resume.patch
+pci-suspend-and-resume-pci-express-ports-with-interrupts-disabled.patch
+pci-handle-pci-state-saving-with-interrupts-disabled.patch
+pci-pm-split-pci-express-port-suspend-resume.patch