aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2013-02-21 19:42:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 20:22:16 -0500
commit42b5dd51930c04dc6fb59c7c7a79354ff91bc9a4 (patch)
treedcda22bae7d2b4550570ce87af1abfdb81069954 /drivers/pcmcia
parentddfe9b359f8a256e711430c29d7c553b1569faed (diff)
pcmcia: move unbind/rebind into dev_pm_ops.complete
Move the device rebind procedures for cardbus devices from the pm.resume into the pm.complete callback. The reason for moving the code is: "[...] The PM code needs to send suspend and resume messages to every device in the right order, and it can't do that if new devices are being added at the same time. [...]" However the situation really isn't quite that rigid. In particular, adding new children during a resume callback shouldn't cause much of problem because the children don't need to be resumed anyway (since they were never suspended). On the other hand, if you do it you will get a dev_warn() from the PM core, something like 'parent should not be sleeping'. Still, it is considered bad form and should be avoided if possible." (Alan Stern's full comment about the topic can be found here: <https://lkml.org/lkml/2012/7/10/254>) Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Cc: Dominik Brodowski <linux@dominikbrodowski.net> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: Greg KH <greg@kroah.com> Acked-by: "Rafael J. Wysocki" <rjw@sisk.pl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/cs.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 673c14ea11e3..5292db69c426 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -484,7 +484,7 @@ static int socket_early_resume(struct pcmcia_socket *skt)
484 484
485static int socket_late_resume(struct pcmcia_socket *skt) 485static int socket_late_resume(struct pcmcia_socket *skt)
486{ 486{
487 int ret; 487 int ret = 0;
488 488
489 mutex_lock(&skt->ops_mutex); 489 mutex_lock(&skt->ops_mutex);
490 skt->state &= ~SOCKET_SUSPEND; 490 skt->state &= ~SOCKET_SUSPEND;
@@ -511,19 +511,31 @@ static int socket_late_resume(struct pcmcia_socket *skt)
511 return socket_insert(skt); 511 return socket_insert(skt);
512 } 512 }
513 513
514 if (!(skt->state & SOCKET_CARDBUS) && (skt->callback))
515 ret = skt->callback->early_resume(skt);
516 return ret;
517}
518
519/*
520 * Finalize the resume. In case of a cardbus socket, we have
521 * to rebind the devices as we can't be certain that it has been
522 * replaced, or not.
523 */
524static int socket_complete_resume(struct pcmcia_socket *skt)
525{
526 int ret = 0;
514#ifdef CONFIG_CARDBUS 527#ifdef CONFIG_CARDBUS
515 if (skt->state & SOCKET_CARDBUS) { 528 if (skt->state & SOCKET_CARDBUS) {
516 /* We can't be sure the CardBus card is the same 529 /* We can't be sure the CardBus card is the same
517 * as the one previously inserted. Therefore, remove 530 * as the one previously inserted. Therefore, remove
518 * and re-add... */ 531 * and re-add... */
519 cb_free(skt); 532 cb_free(skt);
520 cb_alloc(skt); 533 ret = cb_alloc(skt);
521 return 0; 534 if (ret)
535 cb_free(skt);
522 } 536 }
523#endif 537#endif
524 if (!(skt->state & SOCKET_CARDBUS) && (skt->callback)) 538 return ret;
525 skt->callback->early_resume(skt);
526 return 0;
527} 539}
528 540
529/* 541/*
@@ -533,11 +545,15 @@ static int socket_late_resume(struct pcmcia_socket *skt)
533 */ 545 */
534static int socket_resume(struct pcmcia_socket *skt) 546static int socket_resume(struct pcmcia_socket *skt)
535{ 547{
548 int err;
536 if (!(skt->state & SOCKET_SUSPEND)) 549 if (!(skt->state & SOCKET_SUSPEND))
537 return -EBUSY; 550 return -EBUSY;
538 551
539 socket_early_resume(skt); 552 socket_early_resume(skt);
540 return socket_late_resume(skt); 553 err = socket_late_resume(skt);
554 if (!err)
555 err = socket_complete_resume(skt);
556 return err;
541} 557}
542 558
543static void socket_remove(struct pcmcia_socket *skt) 559static void socket_remove(struct pcmcia_socket *skt)
@@ -848,6 +864,12 @@ static int __used pcmcia_socket_dev_resume(struct device *dev)
848 return __pcmcia_pm_op(dev, socket_late_resume); 864 return __pcmcia_pm_op(dev, socket_late_resume);
849} 865}
850 866
867static void __used pcmcia_socket_dev_complete(struct device *dev)
868{
869 WARN(__pcmcia_pm_op(dev, socket_complete_resume),
870 "failed to complete resume");
871}
872
851static const struct dev_pm_ops pcmcia_socket_pm_ops = { 873static const struct dev_pm_ops pcmcia_socket_pm_ops = {
852 /* dev_resume may be called with IRQs enabled */ 874 /* dev_resume may be called with IRQs enabled */
853 SET_SYSTEM_SLEEP_PM_OPS(NULL, 875 SET_SYSTEM_SLEEP_PM_OPS(NULL,
@@ -862,6 +884,7 @@ static const struct dev_pm_ops pcmcia_socket_pm_ops = {
862 .resume_noirq = pcmcia_socket_dev_resume_noirq, 884 .resume_noirq = pcmcia_socket_dev_resume_noirq,
863 .thaw_noirq = pcmcia_socket_dev_resume_noirq, 885 .thaw_noirq = pcmcia_socket_dev_resume_noirq,
864 .restore_noirq = pcmcia_socket_dev_resume_noirq, 886 .restore_noirq = pcmcia_socket_dev_resume_noirq,
887 .complete = pcmcia_socket_dev_complete,
865}; 888};
866 889
867#define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops) 890#define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops)