]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
a pcmcia regression fix from Rafael for .31
authorGreg Kroah-Hartman <gregkh@suse.de>
Mon, 9 Nov 2009 17:24:07 +0000 (09:24 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 9 Nov 2009 17:24:07 +0000 (09:24 -0800)
review-2.6.31/pm-yenta-split-resume-into-early-and-late-parts-rev.-4.patch [new file with mode: 0644]
review-2.6.31/series

diff --git a/review-2.6.31/pm-yenta-split-resume-into-early-and-late-parts-rev.-4.patch b/review-2.6.31/pm-yenta-split-resume-into-early-and-late-parts-rev.-4.patch
new file mode 100644 (file)
index 0000000..8cb1363
--- /dev/null
@@ -0,0 +1,207 @@
+From 9905d1b411946fb3fb228e8c6529fd94afda8a92 Mon Sep 17 00:00:00 2001
+From: Rafael J. Wysocki <rjw@sisk.pl>
+Date: Tue, 3 Nov 2009 10:54:58 +0100
+Subject: PM / yenta: Split resume into early and late parts (rev. 4)
+
+From: Rafael J. Wysocki <rjw@sisk.pl>
+
+commit 9905d1b411946fb3fb228e8c6529fd94afda8a92 upstream.
+
+Commit 0c570cdeb8fdfcb354a3e9cd81bfc6a09c19de0c
+(PM / yenta: Fix cardbus suspend/resume regression) caused resume to
+fail on systems with two CardBus bridges.  While the exact nature
+of the failure is not known at the moment, it can be worked around by
+splitting the yenta resume into an early part, executed during the
+early phase of resume, that will only resume the socket and power it
+up if there was a card in it during suspend, and a late part,
+executed during "regular" resume, that will carry out all of the
+remaining yenta resume operations.
+
+Fixes http://bugzilla.kernel.org/show_bug.cgi?id=14334, which is a
+listed regression from 2.6.31.
+
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Acked-by: Dominik Brodowski <linux@dominikbrodowski.net>
+Reported-by: Stephen J. Gowdy <gowdy@cern.ch>
+Tested-by: Jose Marino <braket@hotmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pcmcia/cs.c           |   69 ++++++++++++++++++++++++++----------------
+ drivers/pcmcia/yenta_socket.c |   12 ++++++-
+ include/pcmcia/ss.h           |    4 ++
+ 3 files changed, 58 insertions(+), 27 deletions(-)
+
+--- a/drivers/pcmcia/cs.c
++++ b/drivers/pcmcia/cs.c
+@@ -98,10 +98,13 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
+  * These functions check for the appropriate struct pcmcia_soket arrays,
+  * and pass them to the low-level functions pcmcia_{suspend,resume}_socket
+  */
++static int socket_early_resume(struct pcmcia_socket *skt);
++static int socket_late_resume(struct pcmcia_socket *skt);
+ static int socket_resume(struct pcmcia_socket *skt);
+ static int socket_suspend(struct pcmcia_socket *skt);
+-int pcmcia_socket_dev_suspend(struct device *dev)
++static void pcmcia_socket_dev_run(struct device *dev,
++                                int (*cb)(struct pcmcia_socket *))
+ {
+       struct pcmcia_socket *socket;
+@@ -110,29 +113,34 @@ int pcmcia_socket_dev_suspend(struct dev
+               if (socket->dev.parent != dev)
+                       continue;
+               mutex_lock(&socket->skt_mutex);
+-              socket_suspend(socket);
++              cb(socket);
+               mutex_unlock(&socket->skt_mutex);
+       }
+       up_read(&pcmcia_socket_list_rwsem);
++}
++int pcmcia_socket_dev_suspend(struct device *dev)
++{
++      pcmcia_socket_dev_run(dev, socket_suspend);
+       return 0;
+ }
+ EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
+-int pcmcia_socket_dev_resume(struct device *dev)
++void pcmcia_socket_dev_early_resume(struct device *dev)
+ {
+-      struct pcmcia_socket *socket;
++      pcmcia_socket_dev_run(dev, socket_early_resume);
++}
++EXPORT_SYMBOL(pcmcia_socket_dev_early_resume);
+-      down_read(&pcmcia_socket_list_rwsem);
+-      list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
+-              if (socket->dev.parent != dev)
+-                      continue;
+-              mutex_lock(&socket->skt_mutex);
+-              socket_resume(socket);
+-              mutex_unlock(&socket->skt_mutex);
+-      }
+-      up_read(&pcmcia_socket_list_rwsem);
++void pcmcia_socket_dev_late_resume(struct device *dev)
++{
++      pcmcia_socket_dev_run(dev, socket_late_resume);
++}
++EXPORT_SYMBOL(pcmcia_socket_dev_late_resume);
++int pcmcia_socket_dev_resume(struct device *dev)
++{
++      pcmcia_socket_dev_run(dev, socket_resume);
+       return 0;
+ }
+ EXPORT_SYMBOL(pcmcia_socket_dev_resume);
+@@ -546,29 +554,24 @@ static int socket_suspend(struct pcmcia_
+       return 0;
+ }
+-/*
+- * Resume a socket.  If a card is present, verify its CIS against
+- * our cached copy.  If they are different, the card has been
+- * replaced, and we need to tell the drivers.
+- */
+-static int socket_resume(struct pcmcia_socket *skt)
++static int socket_early_resume(struct pcmcia_socket *skt)
+ {
+-      int ret;
+-
+-      if (!(skt->state & SOCKET_SUSPEND))
+-              return -EBUSY;
+-
+       skt->socket = dead_socket;
+       skt->ops->init(skt);
+       skt->ops->set_socket(skt, &skt->socket);
++      if (skt->state & SOCKET_PRESENT)
++              skt->resume_status = socket_setup(skt, resume_delay);
++      return 0;
++}
++static int socket_late_resume(struct pcmcia_socket *skt)
++{
+       if (!(skt->state & SOCKET_PRESENT)) {
+               skt->state &= ~SOCKET_SUSPEND;
+               return socket_insert(skt);
+       }
+-      ret = socket_setup(skt, resume_delay);
+-      if (ret == 0) {
++      if (skt->resume_status == 0) {
+               /*
+                * FIXME: need a better check here for cardbus cards.
+                */
+@@ -596,6 +599,20 @@ static int socket_resume(struct pcmcia_s
+       return 0;
+ }
++/*
++ * Resume a socket.  If a card is present, verify its CIS against
++ * our cached copy.  If they are different, the card has been
++ * replaced, and we need to tell the drivers.
++ */
++static int socket_resume(struct pcmcia_socket *skt)
++{
++      if (!(skt->state & SOCKET_SUSPEND))
++              return -EBUSY;
++
++      socket_early_resume(skt);
++      return socket_late_resume(skt);
++}
++
+ static void socket_remove(struct pcmcia_socket *skt)
+ {
+       dev_printk(KERN_NOTICE, &skt->dev,
+--- a/drivers/pcmcia/yenta_socket.c
++++ b/drivers/pcmcia/yenta_socket.c
+@@ -1275,16 +1275,26 @@ static int yenta_dev_resume_noirq(struct
+       if (socket->type && socket->type->restore_state)
+               socket->type->restore_state(socket);
+-      return pcmcia_socket_dev_resume(dev);
++      pcmcia_socket_dev_early_resume(dev);
++      return 0;
++}
++
++static int yenta_dev_resume(struct device *dev)
++{
++      pcmcia_socket_dev_late_resume(dev);
++      return 0;
+ }
+ static struct dev_pm_ops yenta_pm_ops = {
+       .suspend_noirq = yenta_dev_suspend_noirq,
+       .resume_noirq = yenta_dev_resume_noirq,
++      .resume = yenta_dev_resume,
+       .freeze_noirq = yenta_dev_suspend_noirq,
+       .thaw_noirq = yenta_dev_resume_noirq,
++      .thaw = yenta_dev_resume,
+       .poweroff_noirq = yenta_dev_suspend_noirq,
+       .restore_noirq = yenta_dev_resume_noirq,
++      .restore = yenta_dev_resume,
+ };
+ #define YENTA_PM_OPS  (&yenta_pm_ops)
+--- a/include/pcmcia/ss.h
++++ b/include/pcmcia/ss.h
+@@ -262,6 +262,8 @@ struct pcmcia_socket {
+       struct device                   dev;
+       /* data internal to the socket driver */
+       void                            *driver_data;
++      /* status of the card during resume from a system sleep state */
++      int                             resume_status;
+ };
+@@ -280,6 +282,8 @@ extern struct pccard_resource_ops pccard
+ /* socket drivers are expected to use these callbacks in their .drv struct */
+ extern int pcmcia_socket_dev_suspend(struct device *dev);
++extern void pcmcia_socket_dev_early_resume(struct device *dev);
++extern void pcmcia_socket_dev_late_resume(struct device *dev);
+ extern int pcmcia_socket_dev_resume(struct device *dev);
+ /* socket drivers use this callback in their IRQ handler */
index 850e3872e7ccf01e5383492eb46cb58f1da68d65..0f084aeaecb832afe74ded35c91e753b48bd70a6 100644 (file)
@@ -97,3 +97,4 @@ powerpc-pci-fix-regression-in-powerpc-msi-x.patch
 powerpc-fix-some-late-powermac-g5-with-pcie-ati-graphics.patch
 sata_via-remove-redundant-device-id-for-via-vt8261.patch
 pata_via-extend-the-rev_max-for-vt6330.patch
+pm-yenta-split-resume-into-early-and-late-parts-rev.-4.patch